Compare commits
1116 Commits
media-upda
...
feature/re
| Author | SHA1 | Date | |
|---|---|---|---|
| 1d5ee292a9 | |||
| 6f53c7ea6f | |||
| 7d9b6793d3 | |||
|
|
c432b32d08 | ||
|
|
8cf628153c | ||
|
|
ab0bd9e7d9 | ||
|
|
51cd70f2ec | ||
| 235d4e3784 | |||
|
|
dd0bbad18f | ||
| f32059c3e7 | |||
|
|
92578ef738 | ||
| 367205f955 | |||
| 1fdf36669f | |||
|
|
dfa06b148f | ||
|
|
139b437118 | ||
| 4dca636359 | |||
| 4f1d2a179b | |||
|
|
ede28f375a | ||
|
|
06dfb8d7f6 | ||
| 2d4090922f | |||
| 3d58a09c21 | |||
| 05da5f016c | |||
|
|
256eead944 | ||
|
|
dcb8ffaa0d | ||
|
|
def671dd47 | ||
| 717f360952 | |||
|
|
1c0b91f52c | ||
| c733d39d30 | |||
| 87bdea3bba | |||
| efe80694f9 | |||
| be7e6ee400 | |||
| 319a7b27c5 | |||
| dbe20ac724 | |||
|
|
dc6ed3f43a | ||
| ecddb5c6d3 | |||
| 34e5a37e24 | |||
| eaca6bcc72 | |||
|
|
bad588d4b2 | ||
|
|
d5daf20351 | ||
|
|
f512ab96fc | ||
|
|
0cfa9a5483 | ||
|
|
979f934f22 | ||
|
|
1fa5820550 | ||
| 8233afa825 | |||
| ba6f67798d | |||
| daabbaa3e4 | |||
| caa68b24d6 | |||
| 114db744b4 | |||
| 8c910ed5f3 | |||
| 1ef4332df6 | |||
| 6e98269a0b | |||
|
|
c918b91438 | ||
| 2a1e634b34 | |||
|
|
d45165d759 | ||
| a0a885e004 | |||
| 52f7070311 | |||
| e0650da5e9 | |||
| bf5cf3bce4 | |||
| 07d1dc4955 | |||
| 11db41b900 | |||
| 3bca959d49 | |||
| 3fee673314 | |||
| 3121d12f3a | |||
| b8731c3f37 | |||
| b445a42896 | |||
| dbab224a9d | |||
| 03f9659243 | |||
| 0fb56133ff | |||
| afa7ca629c | |||
| 9a9c382d7f | |||
| 518b8d67bc | |||
| ff0f8194e0 | |||
| f84f982c29 | |||
| 420d81866c | |||
| 1cd78ce93a | |||
| 7cae8af89a | |||
| 5088cea413 | |||
| d670d52083 | |||
| 004aa116fb | |||
| 32a08e1e10 | |||
| 30d39c5326 | |||
| 8affea3360 | |||
| 3b6b4dc388 | |||
| 9a9e75d96d | |||
| ad6e4f0a23 | |||
| f66bc6d8aa | |||
| 845bb4763b | |||
| e476b203c7 | |||
| dd163630cb | |||
| 5d8a5ede7d | |||
| 35ccb03c2b | |||
| f6df068787 | |||
| b60a3601cb | |||
| 8676844930 | |||
| 7e80e19eec | |||
| e21c7ce1d0 | |||
| 42f2baca5e | |||
| d9c0c8f1d8 | |||
| b98e184d32 | |||
| f764466199 | |||
| 6adfd9f3fa | |||
| dbf9db1c92 | |||
| 6cb7a8cb43 | |||
| 2913960bcb | |||
| 8d0382a279 | |||
| aa5ef50ed0 | |||
| d87b869633 | |||
| 99782bdf67 | |||
| 6fa459e88e | |||
| 954f2beea7 | |||
| f216413a23 | |||
| 63572a2740 | |||
| aeb7595166 | |||
| f507d198a7 | |||
| 9b5166c570 | |||
| 2271aae557 | |||
| 8ed07e539f | |||
| b029574fa5 | |||
| e9d903ce79 | |||
| 1c9100e5de | |||
| 1a59ac955d | |||
| 4d8e58f920 | |||
|
|
55ce8e0d9e | ||
|
|
0d1a3f8dbf | ||
|
|
9687a3c7a8 | ||
|
|
471534021e | ||
| 8c75abf16a | |||
| 472abaf30b | |||
| 35426e1189 | |||
| 6507d57424 | |||
| 4252878019 | |||
|
|
8451cc1547 | ||
|
|
70ecefb007 | ||
| 4e7be1a18c | |||
| d1cc468dfa | |||
| 484512f2c7 | |||
| 83b4df3462 | |||
| 8ea46b4ea8 | |||
| a68faa11b0 | |||
| 541cd93c99 | |||
| c5a7982945 | |||
| 5cee36453e | |||
| 47ea87b614 | |||
| 4ad0df2c39 | |||
| f2ff8398eb | |||
| 3f915d6964 | |||
| 3e6a9da0d1 | |||
|
|
ca5f4ffd84 | ||
|
|
b66f9f79d2 | ||
|
|
dc0bfe6d7a | ||
|
|
5de463bd02 | ||
|
|
f3d858d785 | ||
|
|
0e537a6b46 | ||
| 8d78b15751 | |||
|
|
e1fc2fa271 | ||
|
|
27466ad3a6 | ||
|
|
f0d63b4120 | ||
|
|
163dd98b7b | ||
| 8610a1678d | |||
|
|
d20c7832da | ||
|
|
fcba4015ed | ||
|
|
bb34a3c33a | ||
|
|
dbded3ba14 | ||
|
|
3a654e0480 | ||
|
|
4b358fba4f | ||
|
|
5aaeab686d | ||
|
|
5ff0a4e86f | ||
|
|
0c866ed009 | ||
|
|
f09bf02c10 | ||
|
|
ee2c30f938 | ||
|
|
82f28bc712 | ||
|
|
8020baf9d1 | ||
|
|
b1cac44432 | ||
|
|
ab46b6118d | ||
|
|
52a1bfe804 | ||
|
|
c7c5b5298c | ||
|
|
4c07917542 | ||
|
|
fe06a2dd55 | ||
| 143f002ead | |||
| 83c0ae5841 | |||
| 0c05386804 | |||
| 9a70d4de0d | |||
| 8950b5f50b | |||
| 59e077fd6a | |||
| c9fc5b2157 | |||
| e128bcfaf9 | |||
| 7cf6b0bba6 | |||
| c36d4783e7 | |||
| 29acd76051 | |||
| eacf33b642 | |||
| 46666db231 | |||
| 3dfa753f33 | |||
| 41ae64a8c9 | |||
| fcf5400f71 | |||
| 2257736ad9 | |||
| 147b55ae78 | |||
| 5b6c951dc0 | |||
| 0840d65011 | |||
| 6394234960 | |||
| e1dde655cb | |||
| e01d59cbd8 | |||
| 22d1e195ed | |||
| c776e7b102 | |||
|
|
3cd95a5a6b | ||
| aba7845a4b | |||
| f23c4c42b5 | |||
| 05149dc723 | |||
| a615c9d1d8 | |||
| eed9ac8ff4 | |||
| 258e7fe307 | |||
| a49a86a597 | |||
| b01c5d57c7 | |||
| 4b0c113941 | |||
| 277a0ae2e3 | |||
| a61aafdc6a | |||
| 3a2899f913 | |||
| 05b172cd47 | |||
| 351259909c | |||
| 0af44ffe02 | |||
| 06799a90b0 | |||
| c7fc9a1480 | |||
| d5b8a89776 | |||
| eada83aaf8 | |||
| 9a63a9de80 | |||
| b4859fd97f | |||
| 794a18cfa0 | |||
| 581b732b05 | |||
| 0119875d22 | |||
| 0f34c7dfb9 | |||
| 04be7fdb3c | |||
| 123d45d172 | |||
|
|
864ae189af | ||
|
|
13b2620d2e | ||
|
|
75c4ad73ed | ||
|
|
2c2f5621df | ||
|
|
855accab4f | ||
|
|
afaa702a02 | ||
|
|
15637d398e | ||
|
|
f346625bb1 | ||
| 9764fef01c | |||
| 338d6c6f9d | |||
| 9da6f39e6e | |||
| 5759794f71 | |||
| ee9d96a5bf | |||
| 9197a86670 | |||
| 64e45b1892 | |||
| 6890a0939d | |||
| 61c78534d8 | |||
| 5a611f96a8 | |||
| 3e7f34d5c4 | |||
|
|
78d16bec5f | ||
| 33f658e088 | |||
| 0b46c34abe | |||
| f1ad20cb0b | |||
| 511da54909 | |||
| 104407646c | |||
| 622229cfc9 | |||
| f50e6ad209 | |||
| d7529cef80 | |||
|
|
f7432158e1 | ||
|
|
2df6597771 | ||
| 60a15c2227 | |||
| a369db9ca1 | |||
|
|
ac35d61ae2 | ||
| 489668a2ff | |||
| c9087d5df4 | |||
| ac06b3700c | |||
| 31578f5ed3 | |||
| 9b178ade4b | |||
| 92522b5494 | |||
| ccebb4eb73 | |||
| 16873e7477 | |||
| 79318e2f28 | |||
| f44a4f5d9d | |||
| b28925079b | |||
| cbf6803812 | |||
|
|
a0e804aa62 | ||
| d1b87bd64b | |||
| 5b783035a3 | |||
| a06363da75 | |||
| a68c691f75 | |||
|
|
8a61d258fb | ||
|
|
fd3f220752 | ||
|
|
0a0b2927ae | ||
|
|
4c19773818 | ||
|
|
071af03577 | ||
|
|
58da0b54b3 | ||
|
|
528ea4bcfb | ||
|
|
ca124d34cd | ||
| 70b53ce21a | |||
| 6dc226ab0b | |||
| d6524942f7 | |||
| 3ca5e81e34 | |||
| 561b5ad1b9 | |||
| 229bb9a5e0 | |||
| 280d3e9043 | |||
| a2384f4b35 | |||
| d65bf5bcd5 | |||
| e763a9140c | |||
| 3a06a375ef | |||
| bdf3f38190 | |||
| 5b2f6e44b1 | |||
| 250401fd62 | |||
| c1fb03add1 | |||
|
|
56bf7efcef | ||
| cc0508683e | |||
|
|
b232b65860 | ||
| 406d1d31c0 | |||
| f8fe5c92aa | |||
| 69623bd248 | |||
| 6d4995074b | |||
| ac94068864 | |||
| 31ed355d64 | |||
| 8a54fb272a | |||
| 6ecf807081 | |||
| 728472b897 | |||
| 30a8c8a03a | |||
| 00e7490037 | |||
| 1d152d730a | |||
| a010d91da2 | |||
| 3717248764 | |||
| 27753e903b | |||
| b621f71b54 | |||
| d4b3300b88 | |||
| 242fb9dda0 | |||
| 4f505cd155 | |||
| dca70a0f53 | |||
| b9a8c826ec | |||
| 363deb3ca7 | |||
| f77b5f7556 | |||
| d60efe38e2 | |||
| f779342e02 | |||
| 204e62b3bb | |||
| 5adc24f997 | |||
| ab25b0f64a | |||
| dd8e59cd4f | |||
| 0c4c36eb74 | |||
|
|
3481f10033 | ||
|
|
fdf61fef3d | ||
|
|
30c3c5d33f | ||
|
|
6cd7df79d9 | ||
|
|
b5b0b5d7bd | ||
|
|
d0266c7d0c | ||
|
|
283fd30c19 | ||
|
|
5d13135bd0 | ||
|
|
6c2961eef6 | ||
|
|
f9c006403e | ||
|
|
1f65f0fe30 | ||
|
|
a49a287855 | ||
| bf7f830f9e | |||
| ffce564a47 | |||
| 2cdcd9a424 | |||
| ffbc733571 | |||
| 3ea7188253 | |||
| 97c6a4c4ef | |||
| f3fe112427 | |||
| 189e4ef230 | |||
| d35b895ff4 | |||
| c47c511674 | |||
| 20be21c87d | |||
| 1d57dc519f | |||
| 644b42afe9 | |||
| 9ad11f24c2 | |||
| 1e2564f753 | |||
| f1ab544aae | |||
|
|
aa85d24952 | ||
|
|
b0f8817aae | ||
|
|
b9e3e9f5f2 | ||
|
|
ea05f5992d | ||
|
|
9c138d6bee | ||
|
|
7325880a70 | ||
|
|
320631e91d | ||
|
|
0997864cd6 | ||
|
|
9e0451d541 | ||
|
|
84245c5584 | ||
|
|
d72c0ea9f5 | ||
|
|
bf9500f960 | ||
|
|
f18cda6c00 | ||
| 0ab20a75ac | |||
| 133a6ed4ea | |||
| bc424b7a00 | |||
| be3c6d89ee | |||
| d814ed1972 | |||
| 8322229001 | |||
| da2a76d6cf | |||
|
|
abf7a2783c | ||
| 6690c69efe | |||
| 67044b7cf9 | |||
| 048d3af39b | |||
| 816989d472 | |||
| 8f6310b463 | |||
| 3cebdd838b | |||
| 9996404e29 | |||
| 1598efac35 | |||
| bfacb86f35 | |||
|
|
e5e5c7e19c | ||
|
|
9ede1d7eea | ||
| ff8cf83f1b | |||
| 326c8e7b81 | |||
| daeecfbd4f | |||
| 15c330c784 | |||
| 7ba80ccc58 | |||
| ef4efe723f | |||
| 64ef8e9acd | |||
| d88b6f6e95 | |||
| 440d66322c | |||
|
|
469a646ae3 | ||
| 9cb9ebbe4f | |||
|
|
d004855dd8 | ||
|
|
911645c9f5 | ||
|
|
6a16e78d80 | ||
| 937c5024cb | |||
|
|
7e12ba1a00 | ||
| 89d57bb915 | |||
| a111387a3f | |||
| 234fcb13af | |||
| 377fdad6e0 | |||
| 68020b0201 | |||
| f0628c5c05 | |||
| 66d2a2c48c | |||
| 6f1229418e | |||
| a430fee568 | |||
| 53b7ce651e | |||
| 1028064abe | |||
| ab285870e3 | |||
| 1a02d46151 | |||
| 1bb70bbe66 | |||
| c158155194 | |||
| 7bfd4c1198 | |||
| ea959d1a10 | |||
| 9fc5d81877 | |||
| 719aac6727 | |||
| c8398920c5 | |||
|
|
55bd914b8f | ||
|
|
2b06a52705 | ||
|
|
2c9c997d5a | ||
|
|
17f305d9cb | ||
|
|
44d071696f | ||
|
|
fa8f44135c | ||
|
|
b38e79ef8f | ||
|
|
e2e39fbdf5 | ||
|
|
a8262932cc | ||
|
|
6d3e9b3c1d | ||
|
|
b91619801d | ||
|
|
f1e32096f3 | ||
|
|
f5a327e72c | ||
| 4fe05e39f7 | |||
|
|
c3779bf371 | ||
| 54aa7e249e | |||
| 1744d192b5 | |||
| 3f7426c550 | |||
| c4e017c7b7 | |||
| e723831548 | |||
| 56b5dcd7d8 | |||
|
|
913d229630 | ||
| 3dfb11d692 | |||
| 759ab14899 | |||
| 329ff7c478 | |||
| a6022f7251 | |||
| d345be889e | |||
| 2dbe9955d9 | |||
|
|
8fcd33e0a1 | ||
| 14aa5e3b28 | |||
| 2cb9aac070 | |||
| 1c6a5c9d04 | |||
| 936aabf412 | |||
| fa7478a5b5 | |||
| 8992554ba6 | |||
| c8895137fa | |||
| f8bc75f1f9 | |||
| 43faa0f020 | |||
| 8e76a18590 | |||
| 9c1df26b4b | |||
| 6d89a499b1 | |||
| 03430c272f | |||
| baf15296ce | |||
| 56f74964ed | |||
| afad2df8f5 | |||
| d17ff1f2e7 | |||
| 4d9be34b4e | |||
|
|
5213b28c2e | ||
|
|
e0df5a53dc | ||
|
|
f13022ee1d | ||
|
|
c063badb38 | ||
|
|
693cf4cd2a | ||
| cc70b1a67f | |||
| 08d3366fe1 | |||
| 080b2fcfc4 | |||
| 5b1d02e3c1 | |||
| b322a405c7 | |||
| 0ed05b103b | |||
| 5431da3930 | |||
| 2a6e5b7992 | |||
| 85af95a8a0 | |||
| e0b04a57ae | |||
| 0533cd24fe | |||
| 9598031dd1 | |||
| 9f808717d2 | |||
| b4aa71b81b | |||
|
|
321a8f0946 | ||
|
|
93124cdad0 | ||
|
|
26eae9b1cf | ||
| f803bc0a59 | |||
| be5925f40d | |||
| b25b697e7b | |||
| 66e2a68cde | |||
| 673f6051c1 | |||
| 0478ab9eb2 | |||
| b7fde520be | |||
| 6f031f78e8 | |||
| 2f850ce152 | |||
|
|
a6240a3ca9 | ||
| 8906936e51 | |||
| fd6867740e | |||
| 183231206b | |||
| d4e832b526 | |||
| 667ff5cf94 | |||
| 6d2db21a62 | |||
| df398faddb | |||
| e07e2d2e2c | |||
| ca29189f9e | |||
|
|
15a1a3f666 | ||
|
|
8c4c09bc90 | ||
|
|
5a926d2d41 | ||
|
|
5127d8b283 | ||
|
|
c043a43fc5 | ||
|
|
013930d7c3 | ||
|
|
6b0d66be25 | ||
|
|
3b492d2005 | ||
|
|
29f4bfd3cc | ||
|
|
86e42c36cb | ||
|
|
c1d81c65d2 | ||
|
|
fd864b03d9 | ||
|
|
97eb51a434 | ||
|
|
76f9b96369 | ||
|
|
13e5cf2133 | ||
|
|
1c92f6449e | ||
|
|
3ed6cc8d5c | ||
|
|
5b79e415e0 | ||
|
|
98036c7266 | ||
|
|
8c8c59d8bd | ||
| fdbadbac7f | |||
| 9d788f919a | |||
| fac00bc4f6 | |||
| 6e511fc4a9 | |||
| 2f6214c48d | |||
| b2f791fc5f | |||
| 39140611ca | |||
| 567ee3062b | |||
| 584e0903c8 | |||
| 8990006d4c | |||
| 7feb78ba70 | |||
| d67ca133eb | |||
| f95557aa3a | |||
| f539ab7294 | |||
|
|
79284e2271 | ||
|
|
e303b565fc | ||
|
|
985e8a5cd6 | ||
|
|
541e1c4c2c | ||
|
|
10c1d500f3 | ||
|
|
678f16788c | ||
|
|
8871a1b7ae | ||
|
|
05c2f28f25 | ||
|
|
30179fe353 | ||
|
|
6846dd760d | ||
|
|
408f285cf3 | ||
|
|
fa76fc0f78 | ||
|
|
ade9cd6b05 | ||
|
|
933d18b784 | ||
| 48bae3b181 | |||
| 78f6ed1ef6 | |||
| 6d503939a5 | |||
| 3677f1c45b | |||
|
|
a23ce4e0e6 | ||
|
|
e7c43fa53a | ||
|
|
0de6735855 | ||
|
|
aa274b1df4 | ||
|
|
51261a4a5c | ||
|
|
9e92561502 | ||
| 2b28ebc014 | |||
| 196d9c358c | |||
|
|
38d58d92b4 | ||
| e136c910b5 | |||
| d0c4f7eea2 | |||
| bf9b0f3973 | |||
| 4534b46e97 | |||
| 68affe4e4c | |||
| aa2671f167 | |||
| 2178b61602 | |||
| 6a6b8ed9b2 | |||
| 784e8cf787 | |||
| 89a8b6926a | |||
| 9c926d15c1 | |||
|
|
1b1144c628 | ||
|
|
e9b1802af3 | ||
|
|
fe7c1d93ae | ||
|
|
8d1be827a7 | ||
|
|
cd4fe13117 | ||
|
|
34e169adba | ||
|
|
d064756cc6 | ||
|
|
bf7e1658f4 | ||
| 8de3c5dcba | |||
| e8827cbd50 | |||
| f839003f5e | |||
| b68d97455b | |||
|
|
e9dcb8b3f0 | ||
|
|
5e838ad61e | ||
|
|
a365977702 | ||
| 8b2542ebef | |||
|
|
69c5018367 | ||
|
|
4f536ae5a9 | ||
|
|
95395d1da7 | ||
|
|
c6c639afc2 | ||
| 41147b26f2 | |||
|
|
fbf437ac99 | ||
|
|
5faf49688d | ||
|
|
4d7d0ed74d | ||
|
|
979b9f704c | ||
|
|
4124cf39db | ||
|
|
c83e21d588 | ||
|
|
c88630e9af | ||
|
|
40b265e145 | ||
|
|
3ad2b2fb8e | ||
|
|
8b671065e9 | ||
|
|
028e1a191e | ||
|
|
a133f82997 | ||
|
|
c4f3eb9a4e | ||
|
|
8a52c4529f | ||
|
|
d0493f3dd0 | ||
|
|
b845552c37 | ||
| 4e97209494 | |||
| aa0b010bed | |||
| cb79ea64cf | |||
|
|
38409d0d63 | ||
|
|
32dfb4eef3 | ||
|
|
a6de64a089 | ||
|
|
b226814676 | ||
|
|
805de3291b | ||
|
|
b0ab63e30e | ||
|
|
13bfc52b77 | ||
|
|
bbce78cab4 | ||
|
|
1e084d5131 | ||
|
|
af699161da | ||
| 2e1c2cd0b2 | |||
| cd7366b8ff | |||
| ec74f6594c | |||
| 5d2e9affc0 | |||
| 06b7ce4db0 | |||
|
|
4bf695f559 | ||
| 59daa1ff08 | |||
| 04044673e2 | |||
| 3b837dc6b0 | |||
| 2f029e2523 | |||
| 66d477795f | |||
| 78f23db801 | |||
| e62a21c469 | |||
| 9756622148 | |||
| 065cb1b746 | |||
| 54a7ad86dc | |||
| 0e7c86ac2b | |||
| e023964cb2 | |||
| 16f4eb65ef | |||
| 11eb12324e | |||
| 7a0d3fc8a0 | |||
| 3ed2aadc34 | |||
| b2004e3483 | |||
| 55f363a64f | |||
| 7a6ed9f7f4 | |||
| 8fa8c85077 | |||
| 245ffc9d45 | |||
| 6a9a2f0a9e | |||
| 9dbefe5a8a | |||
| cce2a79ee4 | |||
| 8e94ab2d7d | |||
| 6e0337cdeb | |||
| 1c3b8f065e | |||
| c43d5574b4 | |||
| 0e5c654b02 | |||
| 14d6d59581 | |||
| 3796961293 | |||
| c471a97a23 | |||
| fc853bd5f1 | |||
| d0ea0ae4d3 | |||
| 8a6d1281bb | |||
| 8797d51ef4 | |||
| 2c8ac1f155 | |||
| 42706de9df | |||
| 3ce99b8751 | |||
| 44c4f16c5c | |||
| cdccde528e | |||
| f32655c156 | |||
| d7255f004d | |||
| 56a1aaa19c | |||
| 86491bfb2e | |||
| 8dc43ccfce | |||
| 7ff49700fd | |||
| e14c7aafb3 | |||
| 0f727168be | |||
| 0de47b3104 | |||
| 6b3eb97568 | |||
| bd4ba41b0b | |||
| fb2f2d9739 | |||
| a468ae01ff | |||
| 6d534bd1c3 | |||
| 31820317de | |||
| e2efa1f1bd | |||
| 86a0936cd4 | |||
| 645b623a40 | |||
| 96bd56a828 | |||
| 870f1c5194 | |||
| 5d1adf7af8 | |||
| a1170a1347 | |||
| 9b5aab6e6e | |||
| a25776fbbb | |||
| 54b5929aa4 | |||
| 729fc3fd39 | |||
| b4cf05ad44 | |||
| 4da8b32b1a | |||
| c35342df59 | |||
| 7d8d407d07 | |||
| 1ceb109a28 | |||
| a8181ff2b7 | |||
| e42c4c3023 | |||
| ff040eec58 | |||
| 5d663d21b3 | |||
| b73c2d3726 | |||
| ee96acbe4f | |||
| fd22b79d42 | |||
| 99f56b9ef8 | |||
| 9a686c1112 | |||
| ffcf823a7f | |||
| a85c4bf115 | |||
| 29d7167c24 | |||
| 3c6a570394 | |||
| 419fa322a3 | |||
| 71a2e1b6dd | |||
| a352c21198 | |||
| 4accb60a24 | |||
| 88b92a9572 | |||
| e39fa78981 | |||
| 4205113b00 | |||
| ad47efefaf | |||
| 890399dd74 | |||
| 2698ede55e | |||
| c9f0ea2512 | |||
| 228f9c7c6b | |||
| 63e05e924a | |||
| a66cde3934 | |||
| 0b8a2904ec | |||
| 5fffa97ea7 | |||
| 1d14d86d8e | |||
| 217ab89667 | |||
| ac2dd23ad7 | |||
| 7a4f72378d | |||
| 8190839823 | |||
| 4e9d97268f | |||
| 985f7c94da | |||
| 3d28e73369 | |||
| 4076b138b9 | |||
|
|
99d4c709bd | ||
| 93951cfbc8 | |||
| 4ac86c434e | |||
| 171cfa7aab | |||
| a494dbe662 | |||
| c9d02fb11c | |||
| 3ba65385c5 | |||
| 58a2da1996 | |||
| 845d6ba12b | |||
| f0b55b7b2e | |||
| e6dd75c2a8 | |||
| 7b7154085e | |||
| 1c119e80e9 | |||
| 3d86f859c6 | |||
| 0bfad00df7 | |||
| 64efa723b3 | |||
| 0072b28965 | |||
| 21fa5d24af | |||
| 16ec3c515e | |||
| 6868144e25 | |||
| 0e5af96900 | |||
| ded5caf271 | |||
| e8e1e91d1c | |||
| 6a16d545ec | |||
| 976b6fbb78 | |||
| efc5571fb3 | |||
| 6ad4b3a6c4 | |||
| cc0fe080cf | |||
|
|
1de89fba5f | ||
| 0c668c9c62 | |||
| 6a3c3a3566 | |||
| e17f79e0b1 | |||
| f0461fb65f | |||
| aa38927522 | |||
| 881d06deea | |||
| 683869214b | |||
| 3322a6e005 | |||
| 65a48454ba | |||
| 0de8e17593 | |||
| 17beb4152b | |||
| b09097294f | |||
| c6e1b0248d | |||
| 0a956e1fc5 | |||
| e2dee426bf | |||
| 37a738c094 | |||
| bef4c3440b | |||
| b36ad8042f | |||
| 6ec38853ff | |||
| 69144a665f | |||
| 382a1d0ef8 | |||
| 41c751a76d | |||
| 01e46042fb | |||
| f1a28b6efe | |||
| 7fddeeeaae | |||
| bacf35bb4b | |||
| 4a83c7e171 | |||
| 3cbce25394 | |||
|
|
c2b58cc82d | ||
| ac326d2d74 | |||
| 50aaf8b343 | |||
| f667ac6430 | |||
| e2e599ed35 | |||
| 897e422e15 | |||
| 0031be6882 | |||
| 45880ed7a8 | |||
| b7e964174a | |||
| 77b8f60cb1 | |||
| 4cbde00ef3 | |||
| 196472181e | |||
| 2fa7a0c7a5 | |||
| 38e982e70b | |||
| 8a9b57547a | |||
| 6dd3d6255d | |||
| 656de567d7 | |||
| 24e80d7851 | |||
| bc642b48da | |||
| cc07998a8a | |||
| 178309bb1e | |||
| 40c19f47c7 | |||
| 7f82b24b0c | |||
| f31a8da0e1 | |||
| 8ed158ab3c | |||
| 08af379a57 | |||
| 79dbdd3e5a | |||
| f7e8d5bdf7 | |||
| 52eba56e34 | |||
| 4c42276deb | |||
| b4eb772662 | |||
| 825730c3f9 | |||
| b7a2253b01 | |||
| ce1174d41b | |||
| f2da168a03 | |||
| fec4b29261 | |||
| 01b8dadd5f | |||
| 3ee97468f9 | |||
| c6d318bbc3 | |||
| 4ebb07a79a | |||
| 2580d0874f | |||
| 2168e693d8 | |||
| bc2a25346b | |||
| 03e969e08c | |||
| 37e3872782 | |||
| 71442e4160 | |||
| c2b69a769a | |||
| c0bc0e03c0 | |||
| f49bef1112 | |||
| 191b2978ec | |||
| 2771cdd053 | |||
| 2d576645d8 | |||
| be9884b468 | |||
| df280ce7a6 | |||
| c1182b3b90 | |||
| 425a3561ac | |||
| 12be354cc9 | |||
| 7e2917d447 | |||
| cb0de6a2d5 | |||
| 95318d1b36 | |||
| b92456c178 | |||
| bcb25b5d5e | |||
| 6a79204204 | |||
| d3776a8d3f | |||
| 325c6a0448 | |||
| 7c089eed80 | |||
| 8b40a46c1b | |||
| ef4061b96c | |||
|
|
506849b450 | ||
|
|
e73ce8c943 | ||
| bb4543bc65 | |||
|
|
f8d5850a89 | ||
| cce994d35c | |||
| 02cfb53147 | |||
| 0755df03cf | |||
| 51f0ad7497 | |||
| b4a49d20c8 | |||
| 44ccaf10d4 | |||
| 967c14b93a | |||
| 0e42fc657b | |||
| 2d7a91e368 | |||
| 072ab038fe | |||
| 6723c27d5e | |||
| f5fc700886 | |||
| 96a5ba0ceb | |||
| dfe5e72526 | |||
| d1cbebee84 | |||
| eac313feb8 | |||
| a71ed56cf2 | |||
| e3bc72e8d2 | |||
| 0fadfed7f6 | |||
| 031db78590 | |||
| 6fd32fb84b | |||
| 98e6464be6 | |||
| 52ce2afad2 | |||
| 28f89c9469 | |||
| 6f7de8da66 | |||
| 50caf2753d | |||
| 30c0caa04d | |||
| e53d8c14a9 | |||
| eca89358db | |||
| 1e58c71e67 | |||
| 43beaefc07 | |||
| f74faadace | |||
| 77aa622610 | |||
| 95aadd45ee | |||
| 89880016ea | |||
| beb91553ef | |||
| b2037c9575 | |||
| ce4cec5589 | |||
| e8a597ec6b | |||
| a663e2bd56 | |||
| 84bfd3cda2 | |||
| 3dfe96fa89 | |||
| 93cbcef93f | |||
| 5c758536a4 | |||
| bc5a9aa9f1 | |||
| b8ed77f6d5 | |||
| 6c25cd029f | |||
| 68d59eda69 | |||
| 2534d4c159 | |||
| 54252e768c | |||
| 7a2f263061 | |||
| 5ae6e02ce8 | |||
| fb9944ef14 | |||
| 190493179f | |||
| 4b1bc23622 | |||
| 2ad5b04a48 | |||
| afbbbcb4d1 | |||
| 820c3aec9d | |||
| eafbcd8389 | |||
| f0459b3f6e | |||
| ff93265890 | |||
| 320e282dc8 | |||
| d23c911c78 | |||
| 51df812a6c | |||
| a96aba57f7 | |||
| 36c71da4bb | |||
| b53fca9648 | |||
| 9fafb8bd2a | |||
| 41c7ba35a0 | |||
| 4cc5702da7 | |||
| 65f626f15e | |||
| 2abf6f67af | |||
| 72cde997ab | |||
| 8b27cb4690 | |||
| fb0cec0850 | |||
| a9a0bfdad0 | |||
| 00a752173d | |||
| 24caa9a4f4 | |||
| a1075e000a | |||
| c416902280 | |||
| a29d707183 | |||
| 69d08a85ac | |||
| 475ea08517 | |||
| b4c97c20d6 | |||
| f7da2c8185 | |||
| a1a630fc02 | |||
| 22ef117493 | |||
| 04b80d5ff8 | |||
| b764979c3b | |||
| a78c0491ef | |||
| 6082beb964 | |||
| 9d9a5fd9d2 | |||
| 4332f389a1 | |||
| a26b60e726 | |||
| 465d76cd08 | |||
| e0300148cf | |||
| 4442c6c625 | |||
| 289eb86d97 | |||
| 59724777e9 | |||
| 99e0b297b2 | |||
| 7036747042 | |||
| b9cd3e3f9f | |||
| c8e90b6887 | |||
| 56973b62f6 | |||
| 990a13e777 | |||
| cd37623746 | |||
| 193620e4e4 | |||
| 78d85e2440 | |||
| 9fa9689db9 | |||
| 81fc33183c | |||
| 2600011736 | |||
| e5c297eb7c | |||
| a3766aca6c | |||
| 857689dc22 | |||
| 2ed5917e96 | |||
| 84380bf333 | |||
| e7d517f264 | |||
| 40a9cc424e | |||
| b725bc2b5b | |||
| 50306c319e | |||
| c1e86c6897 | |||
| eb02142afc | |||
| 5f0526eef7 | |||
| cbdc55df8f | |||
| e0022b15c5 | |||
| 983edc53d1 | |||
| 2af1dcd24e | |||
| 2814a5f044 | |||
| 802fd87850 | |||
| 50a6a39632 | |||
| 49d0d3b35a | |||
| 8017f017f2 | |||
| 864798be7c | |||
| e20ef40e02 | |||
| 955f9021f7 | |||
| e006090be2 | |||
| 1c6bc56e08 | |||
| aa2da29b4c | |||
| 9e47d28660 | |||
| a5383c87c7 | |||
| 152a637e31 | |||
| 5d947000ca | |||
| bf4f378108 | |||
| 7f03228efa | |||
| 7e6fd1859e | |||
| 979c77c1b9 | |||
| 15c9603902 | |||
| 20dd8bcb3a | |||
| bec4b03a17 | |||
| 2686a162e7 | |||
| 7d9c982cf5 | |||
| d1c09ce74e | |||
| fe5f429039 | |||
| 8937571214 | |||
| f9591951cb | |||
| 956d2a25f2 | |||
| 365bec10a6 | |||
| c69c11b0fe | |||
| 40b8414f8a | |||
| 06cb735b68 | |||
| 985f32e06e | |||
| 36469b20b3 | |||
| 2173e4c6b8 | |||
| d7a35e651e | |||
| 4238c977f3 | |||
| 74e9a3204f | |||
| 7bf94ced84 | |||
| 1b3a40c22a | |||
| 28bef07e37 | |||
| 3b7cb57e7a | |||
| 3f069e6d22 | |||
| 12e7269591 | |||
| 0127cf0a6b | |||
| fd1522a2ca | |||
| c79ec065d3 | |||
| 19fe484049 | |||
| db3d831bc0 | |||
| d27e707044 | |||
| c142440068 | |||
| df6456f5d2 | |||
| 1578a2b8d1 | |||
| 4a43c152d5 | |||
| 0d1ee37272 | |||
| 5c0b97cd1e | |||
| 511e8d6074 | |||
| 826e4a7de2 | |||
| 1ac66b4ece | |||
| 8f58de9f4e | |||
| 611d997df9 | |||
| 3f66e3f1f1 | |||
| 6154fa5dcc | |||
| dd0914cd89 | |||
| b8000d9a64 | |||
| d94bd66c54 | |||
| 2ebd2018db | |||
| 04b41e16e1 | |||
| 7ad73f3c84 | |||
| 359698d54f | |||
| 26ea658f9c | |||
| a13be0530f | |||
| b018b11c57 | |||
| aac023351a | |||
| fd2fbea03f | |||
| f3bbdec77c | |||
| b54ace0272 | |||
| 55bc78d9cb | |||
| fabe027d54 | |||
| b4f4450573 | |||
| 990cc66600 | |||
| aa76147144 | |||
| ee46af08ca | |||
| c33de944ef | |||
| 79e5103b08 | |||
| 4797b213ee | |||
| c232042af5 | |||
| 252448f4a9 | |||
| ec4febe5e9 | |||
| 35ca0d90f7 | |||
| eae3d4689b | |||
| 67c9d4084c | |||
| fb52428219 | |||
| 23e620e168 | |||
| 324054b3db | |||
| d9dcbeef7b | |||
| 9b31d52d7e | |||
| 260d2d28ad | |||
| dd74bdda6a | |||
| 7486390da5 |
@@ -3,7 +3,6 @@ APP_ENV=local
|
||||
APP_KEY=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://localhost
|
||||
APP_URL_API="${APP_URL}/api/"
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_DEPRECATIONS_CHANNEL=null
|
||||
@@ -30,7 +29,7 @@ REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=smtp
|
||||
MAIL_HOST=mailhog
|
||||
MAIL_HOST=mailpit
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
@@ -52,6 +51,7 @@ PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_APP_NAME="${APP_NAME}"
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
|
||||
59
.env.testing
59
.env.testing
@@ -1,59 +0,0 @@
|
||||
APP_NAME=Laravel
|
||||
APP_ENV=local
|
||||
APP_KEY=base64:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX=
|
||||
APP_DEBUG=true
|
||||
APP_URL=http://127.0.0.1
|
||||
APP_URL_API="${APP_URL}/api/"
|
||||
|
||||
LOG_CHANNEL=stack
|
||||
LOG_LEVEL=debug
|
||||
|
||||
DB_CONNECTION=sqlite
|
||||
DB_DATABASE=:memory:
|
||||
|
||||
BROADCAST_DRIVER=log
|
||||
CACHE_DRIVER=array
|
||||
QUEUE_CONNECTION=sync
|
||||
SESSION_DRIVER=file
|
||||
SESSION_LIFETIME=120
|
||||
|
||||
MEMCACHED_HOST=127.0.0.1
|
||||
|
||||
REDIS_HOST=127.0.0.1
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
MAIL_MAILER=log
|
||||
MAIL_HOST=null
|
||||
MAIL_PORT=null
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDRESS="hello@example.com"
|
||||
MAIL_FROM_NAME="${APP_NAME}"
|
||||
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_DEFAULT_REGION=us-east-1
|
||||
AWS_BUCKET=
|
||||
AWS_USE_PATH_STYLE_ENDPOINT=false
|
||||
|
||||
PUSHER_APP_ID=
|
||||
PUSHER_APP_KEY=
|
||||
PUSHER_APP_SECRET=
|
||||
PUSHER_HOST=
|
||||
PUSHER_PORT=443
|
||||
PUSHER_SCHEME=https
|
||||
PUSHER_APP_CLUSTER=mt1
|
||||
|
||||
VITE_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
|
||||
VITE_PUSHER_HOST="${PUSHER_HOST}"
|
||||
VITE_PUSHER_PORT="${PUSHER_PORT}"
|
||||
VITE_PUSHER_SCHEME="${PUSHER_SCHEME}"
|
||||
VITE_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"
|
||||
|
||||
CONTACT_ADDRESS="hello@stemmechanics.com.au"
|
||||
CONTACT_SUBJECT="Contact from website"
|
||||
|
||||
STORAGE_LOCAL_URL="${APP_URL}/api/media/%ID%/download"
|
||||
STORAGE_PUBLIC_URL="${APP_URL}/uploads/%NAME%"
|
||||
@@ -1,3 +0,0 @@
|
||||
.github/
|
||||
.vscode/
|
||||
vendor/
|
||||
22
.eslintrc.js
22
.eslintrc.js
@@ -1,22 +0,0 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
node: true,
|
||||
},
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/vue3-strongly-recommended",
|
||||
"prettier",
|
||||
"plugin:jsdoc/recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
],
|
||||
rules: {
|
||||
"vue/multi-word-component-names": "off",
|
||||
indent: ["off", 4, { ignoredNodes: ["ConditionalExpression"] }],
|
||||
"@typescript-eslint/no-inferrable-types": "off",
|
||||
},
|
||||
plugins: ["jsdoc", "@typescript-eslint"],
|
||||
parser: "vue-eslint-parser",
|
||||
parserOptions: {
|
||||
parser: "@typescript-eslint/parser",
|
||||
},
|
||||
};
|
||||
2
.gitattributes
vendored
2
.gitattributes
vendored
@@ -1,4 +1,4 @@
|
||||
* text=auto
|
||||
* text=auto eol=lf
|
||||
|
||||
*.blade.php diff=html
|
||||
*.css diff=css
|
||||
|
||||
42
.github/workflows/laravel.yml
vendored
42
.github/workflows/laravel.yml
vendored
@@ -1,42 +0,0 @@
|
||||
name: Laravel
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
|
||||
jobs:
|
||||
laravel-tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: "8.1"
|
||||
- uses: actions/checkout@v3
|
||||
- name: Copy .env
|
||||
run: php -r "file_exists('.env') || copy('.env.example', '.env');"
|
||||
- name: Install Dependencies
|
||||
run: composer install -q --no-interaction --no-progress --prefer-dist
|
||||
- name: Generate key
|
||||
run: php artisan key:generate
|
||||
- name: Directory Permissions
|
||||
run: chmod -R 777 storage bootstrap/cache
|
||||
- name: Create Database
|
||||
run: |
|
||||
mkdir -p database
|
||||
touch database/database.sqlite
|
||||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||
env:
|
||||
DB_CONNECTION: sqlite
|
||||
DB_DATABASE: database/database.sqlite
|
||||
run: vendor/bin/phpunit
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "16.x"
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run Vue tests
|
||||
env:
|
||||
LARAVEL_BYPASS_ENV_CHECK: "1"
|
||||
run: npm run test
|
||||
261
.gitignore
vendored
261
.gitignore
vendored
@@ -1,247 +1,20 @@
|
||||
### Composer ###
|
||||
composer.phar
|
||||
/vendor/
|
||||
|
||||
# composer.lock
|
||||
|
||||
### Laravel ###
|
||||
node_modules/
|
||||
/.phpunit.cache
|
||||
/node_modules
|
||||
/public/build
|
||||
/public/hot
|
||||
/public/storage
|
||||
/storage/*.key
|
||||
/vendor
|
||||
.env
|
||||
.env.backup
|
||||
.env.production
|
||||
.phpunit.result.cache
|
||||
Homestead.json
|
||||
Homestead.yaml
|
||||
auth.json
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
|
||||
# Laravel 4 specific
|
||||
bootstrap/compiled.php
|
||||
app/storage/
|
||||
|
||||
# Laravel 5 & Lumen specific
|
||||
public/storage
|
||||
public/hot
|
||||
|
||||
# Laravel 5 & Lumen specific with changed public path
|
||||
public_html/storage
|
||||
public_html/hot
|
||||
|
||||
storage/*.key
|
||||
.env
|
||||
Homestead.yaml
|
||||
Homestead.json
|
||||
/.vagrant
|
||||
.phpunit.result.cache
|
||||
|
||||
### macOS ###
|
||||
# General
|
||||
/.fleet
|
||||
/.idea
|
||||
/.vscode
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
|
||||
# Icon must end with two \r
|
||||
Icon
|
||||
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear in the root of a volume
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
.VolumeIcon.icns
|
||||
.com.apple.timemachine.donotpresent
|
||||
|
||||
# Directories potentially created on remote AFP share
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
Network Trash Folder
|
||||
Temporary Items
|
||||
.apdisk
|
||||
|
||||
### macOS Patch ###
|
||||
# iCloud generated files
|
||||
*.icloud
|
||||
|
||||
### Node ###
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
### Node Patch ###
|
||||
# Serverless Webpack directories
|
||||
.webpack/
|
||||
|
||||
# Optional stylelint cache
|
||||
|
||||
# SvelteKit build / generate output
|
||||
.svelte-kit
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
|
||||
### Vue ###
|
||||
# gitignore template for Vue.js projects
|
||||
#
|
||||
# Recommended template: Node.gitignore
|
||||
|
||||
# TODO: where does this rule come from?
|
||||
docs/_book
|
||||
|
||||
# TODO: where does this rule come from?
|
||||
test/
|
||||
|
||||
### Vuejs ###
|
||||
# Recommended template: Node.gitignore
|
||||
|
||||
dist/
|
||||
|
||||
### This Project ###
|
||||
/public/uploads
|
||||
/public/build
|
||||
/public/tinymce
|
||||
*.key
|
||||
|
||||
### Synk ###
|
||||
.dccache
|
||||
|
||||
### TempCodeRunner ###
|
||||
tempCodeRunnerFile.*
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"bracketSameLine": true,
|
||||
"tabWidth": 4
|
||||
}
|
||||
18
.vscode/settings.json
vendored
18
.vscode/settings.json
vendored
@@ -1,19 +1,5 @@
|
||||
{
|
||||
"editor.formatOnType": true,
|
||||
"editor.formatOnSave": true,
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
// "source.organizeImports": true // <-- when enabled, breaks tinymce required import order
|
||||
},
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"[vue]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[javascript]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[php]": {
|
||||
// "editor.defaultFormatter": "bmewburn.vscode-intelephense-client"
|
||||
"editor.defaultFormatter": "wongjn.php-sniffer"
|
||||
"files.associations": {
|
||||
"*.css": "tailwindcss"
|
||||
}
|
||||
}
|
||||
|
||||
18
README.md
18
README.md
@@ -1,7 +1,7 @@
|
||||
<p align="center"><a href="https://laravel.com" target="_blank"><img src="https://raw.githubusercontent.com/laravel/art/master/logo-lockup/5%20SVG/2%20CMYK/1%20Full%20Color/laravel-logolockup-cmyk-red.svg" width="400" alt="Laravel Logo"></a></p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.org/laravel/framework"><img src="https://travis-ci.org/laravel/framework.svg" alt="Build Status"></a>
|
||||
<a href="https://github.com/laravel/framework/actions"><img src="https://github.com/laravel/framework/workflows/tests/badge.svg" alt="Build Status"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/dt/laravel/framework" alt="Total Downloads"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/v/laravel/framework" alt="Latest Stable Version"></a>
|
||||
<a href="https://packagist.org/packages/laravel/framework"><img src="https://img.shields.io/packagist/l/laravel/framework" alt="License"></a>
|
||||
@@ -31,23 +31,23 @@ If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Lar
|
||||
|
||||
## Laravel Sponsors
|
||||
|
||||
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell).
|
||||
We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the [Laravel Partners program](https://partners.laravel.com).
|
||||
|
||||
### Premium Partners
|
||||
|
||||
- **[Vehikl](https://vehikl.com/)**
|
||||
- **[Tighten Co.](https://tighten.co)**
|
||||
- **[WebReinvent](https://webreinvent.com/)**
|
||||
- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)**
|
||||
- **[64 Robots](https://64robots.com)**
|
||||
- **[Cubet Techno Labs](https://cubettech.com)**
|
||||
- **[Cyber-Duck](https://cyber-duck.co.uk)**
|
||||
- **[Many](https://www.many.co.uk)**
|
||||
- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)**
|
||||
- **[DevSquad](https://devsquad.com)**
|
||||
- **[Curotec](https://www.curotec.com/services/technologies/laravel/)**
|
||||
- **[Cyber-Duck](https://cyber-duck.co.uk)**
|
||||
- **[DevSquad](https://devsquad.com/hire-laravel-developers)**
|
||||
- **[Jump24](https://jump24.co.uk)**
|
||||
- **[Redberry](https://redberry.international/laravel/)**
|
||||
- **[Active Logic](https://activelogic.com)**
|
||||
- **[byte5](https://byte5.de)**
|
||||
- **[OP.GG](https://op.gg)**
|
||||
- **[WebReinvent](https://webreinvent.com/?utm_source=laravel&utm_medium=github&utm_campaign=patreon-sponsors)**
|
||||
- **[Lendio](https://lendio.com)**
|
||||
|
||||
## Contributing
|
||||
|
||||
|
||||
@@ -1,715 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Conductors;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class Conductor
|
||||
{
|
||||
/**
|
||||
* The Conductors Model class.
|
||||
*
|
||||
* @var string|null
|
||||
*/
|
||||
protected $class = null;
|
||||
|
||||
/**
|
||||
* The default sorting fields of a collection. Can be an array. Supports - and + prefixes.
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $sort = "id";
|
||||
|
||||
/**
|
||||
* The default collection size limit per request.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $limit = 50;
|
||||
|
||||
/**
|
||||
* The maximum collection size limit per request.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
protected $maxLimit = 100;
|
||||
|
||||
/**
|
||||
* The default includes to include in a request.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $includes = [];
|
||||
|
||||
/**
|
||||
* The conductor collection.
|
||||
*
|
||||
* @var Collection
|
||||
*/
|
||||
private $collection = null;
|
||||
|
||||
/**
|
||||
* The conductor query.
|
||||
*
|
||||
* @var Builder
|
||||
*/
|
||||
private $query = null;
|
||||
|
||||
|
||||
/**
|
||||
* Split a string on commas, keeping quotes intact.
|
||||
*
|
||||
* @param string $string The string to split.
|
||||
* @return array The split string.
|
||||
*/
|
||||
private function splitString(string $string)
|
||||
{
|
||||
$parts = [];
|
||||
$start = 0;
|
||||
$len = strlen($string);
|
||||
|
||||
while ($start < $len) {
|
||||
$commaPos = strpos($string, ',', $start);
|
||||
$singlePos = strpos($string, '\'', $start);
|
||||
$doublePos = strpos($string, '"', $start);
|
||||
|
||||
// Find the smallest position that is not false
|
||||
$minPos = false;
|
||||
if ($commaPos !== false) {
|
||||
$minPos = $commaPos;
|
||||
}
|
||||
if ($singlePos !== false && ($minPos === false || $singlePos < $minPos)) {
|
||||
$minPos = $singlePos;
|
||||
}
|
||||
if ($doublePos !== false && ($minPos === false || $doublePos < $minPos)) {
|
||||
$minPos = $doublePos;
|
||||
}
|
||||
|
||||
if ($minPos === false) {
|
||||
// No more commas, single quotes, or double quotes found
|
||||
$part = substr($string, $start);
|
||||
$parts[] = trim($part);
|
||||
break;
|
||||
} else {
|
||||
// Add the current part to the parts array
|
||||
$part = substr($string, $start, ($minPos - $start));
|
||||
$parts[] = trim($part);
|
||||
|
||||
// Update the start position to the next character after the comma, single quote, or double quote
|
||||
if ($string[$minPos] === ',') {
|
||||
$start = ($minPos + 1);
|
||||
} else {
|
||||
$quoteChar = $string[$minPos];
|
||||
$endPos = strpos($string, $quoteChar, ($minPos + 1));
|
||||
if ($endPos === false) {
|
||||
$part = substr($string, ($minPos + 1));
|
||||
$parts[] = trim($part);
|
||||
break;
|
||||
} else {
|
||||
$part = substr($string, ($minPos + 1), ($endPos - $minPos - 1));
|
||||
$parts[] = trim($part);
|
||||
$start = ($endPos + 1);
|
||||
}
|
||||
}
|
||||
}//end if
|
||||
}//end while
|
||||
|
||||
return array_filter($parts, function ($value) {
|
||||
return $value !== '';
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a field with a specific Builder object
|
||||
*
|
||||
* @param Builder $builder The builder object to append.
|
||||
* @param string $field The field name.
|
||||
* @param mixed $value The value or array of values to filter.
|
||||
* @param string $boolean The comparision boolean (AND or OR).
|
||||
* @return void
|
||||
*/
|
||||
private function filterFieldWithBuilder(Builder $builder, string $field, mixed $value, string $boolean = 'AND')
|
||||
{
|
||||
$values = [];
|
||||
|
||||
// Split by comma, but respect quotation marks
|
||||
if (is_string($value) === true) {
|
||||
$values = $this->splitString($value);
|
||||
} elseif (is_array($value) === true) {
|
||||
$values = $value;
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Expected string or array, got ' . gettype($value));
|
||||
}
|
||||
|
||||
// Add each AND check to the query
|
||||
$builder->where(function ($query) use ($field, $values) {
|
||||
foreach ($values as $value) {
|
||||
$value = trim($value);
|
||||
$prefix = '';
|
||||
|
||||
// Check if value has a prefix and remove it if it's a number
|
||||
if (preg_match('/^(!?=|[<>]=?|<>|!)([^=!<>].*)$/', $value, $matches) > 0) {
|
||||
$prefix = $matches[1];
|
||||
$value = $matches[2];
|
||||
}
|
||||
|
||||
// Apply the prefix to the query if the value is a number
|
||||
switch ($prefix) {
|
||||
case '=':
|
||||
$query->orWhere($field, '=', $value);
|
||||
break;
|
||||
case '!':
|
||||
$query->orWhere($field, 'NOT LIKE', "%$value%");
|
||||
break;
|
||||
case '>':
|
||||
$query->orWhere($field, '>', $value);
|
||||
break;
|
||||
case '<':
|
||||
$query->orWhere($field, '<', $value);
|
||||
break;
|
||||
case '>=':
|
||||
$query->orWhere($field, '>=', $value);
|
||||
break;
|
||||
case '<=':
|
||||
$query->orWhere($field, '<=', $value);
|
||||
break;
|
||||
case '!=':
|
||||
$query->orWhere($field, '!=', $value);
|
||||
break;
|
||||
case '<>':
|
||||
$seperatorPos = strpos($value, '|');
|
||||
if ($seperatorPos !== false) {
|
||||
$query->orWhereBetween($field, [substr($value, 0, $seperatorPos), substr($value, ($seperatorPos + 1))]);
|
||||
} else {
|
||||
$query->orWhere($field, '!=', $value);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$query->orWhere($field, 'LIKE', "%$value%");
|
||||
break;
|
||||
}//end switch
|
||||
}//end foreach
|
||||
}, null, null, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the conductor on a Request to generate a collection and total.
|
||||
*
|
||||
* @param Request $request The request data.
|
||||
* @return array The processed and transformed collection | the total rows found.
|
||||
*/
|
||||
final public static function request(Request $request)
|
||||
{
|
||||
$conductor_class = get_called_class();
|
||||
$conductor = new $conductor_class();
|
||||
|
||||
$total = 0;
|
||||
|
||||
try {
|
||||
$conductor->query = $conductor->class::query();
|
||||
} catch (\Throwable $e) {
|
||||
throw new \Exception('Failed to create query builder instance for ' . $conductor->class . '.', 0, $e);
|
||||
}
|
||||
|
||||
// Filter request
|
||||
$fields = $conductor->fields(new $conductor->class());
|
||||
if (is_array($fields) === false) {
|
||||
$fields = [];
|
||||
}
|
||||
|
||||
$params = $request->all();
|
||||
$filterFields = array_intersect_key($params, array_flip($fields));
|
||||
$conductor->filter($filterFields);
|
||||
if ($request->has('filter') === true) {
|
||||
$conductor->filterRaw($request->input('filter', ''), $fields);
|
||||
}
|
||||
|
||||
// After Scope query
|
||||
$conductor->query->where(function ($query) use ($conductor) {
|
||||
$conductor->scope($query);
|
||||
});
|
||||
|
||||
// Sort request
|
||||
$conductor->sort($request->input('sort', $conductor->sort));
|
||||
|
||||
// Get total
|
||||
$total = $conductor->count();
|
||||
|
||||
// Paginate
|
||||
$conductor->paginate($request->input('page', 1), $request->input('limit', -1));
|
||||
|
||||
// Limit fields
|
||||
$limitFields = explode(',', $request->input('fields'));
|
||||
if ($limitFields === null) {
|
||||
$limitFields = $fields;
|
||||
} else {
|
||||
$limitFields = array_intersect($limitFields, $fields);
|
||||
}
|
||||
$conductor->limitFields($limitFields);
|
||||
|
||||
$conductor->collection = $conductor->query->get();
|
||||
|
||||
|
||||
// Transform and Includes
|
||||
$includes = $conductor->includes;
|
||||
if ($request->has('includes') === true) {
|
||||
$includes = explode(',', $request->input('includes'));
|
||||
}
|
||||
|
||||
$conductor->collection = $conductor->collection->map(function ($model) use ($conductor, $includes) {
|
||||
$conductor->includes($model, $includes);
|
||||
$model = $conductor->transform($model);
|
||||
|
||||
return $model;
|
||||
});
|
||||
|
||||
return [$conductor->collection, $total];
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the conductor on a collection with the data stored in a Request.
|
||||
*
|
||||
* @param Request $request The request data.
|
||||
* @param Collection $collection The collection.
|
||||
* @return array The processed and transformed model data.
|
||||
*/
|
||||
final public static function collection(Request $request, Collection $collection)
|
||||
{
|
||||
$conductor_class = get_called_class();
|
||||
$conductor = new $conductor_class();
|
||||
|
||||
$transformedCollection = collect();
|
||||
|
||||
foreach ($collection as $item) {
|
||||
if ($conductor->viewable($item)) {
|
||||
$transformedCollection->push($conductor->transform($item));
|
||||
}
|
||||
}
|
||||
|
||||
return $transformedCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the conductor on a Model with the data stored in a Request.
|
||||
*
|
||||
* @param Request $request The request data.
|
||||
* @param Model $model The model.
|
||||
* @return array The processed and transformed model data.
|
||||
*/
|
||||
final public static function model(Request $request, Model $model)
|
||||
{
|
||||
$conductor_class = get_called_class();
|
||||
$conductor = new $conductor_class();
|
||||
|
||||
$fields = $conductor->fields(new $conductor->class());
|
||||
|
||||
// Limit fields
|
||||
$limitFields = $fields;
|
||||
if ($request !== null && $request->has('fields') === true) {
|
||||
$requestFields = $request->input('fields');
|
||||
if ($requestFields !== null) {
|
||||
$limitFields = array_intersect(explode(',', $requestFields), $fields);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($limitFields) === false) {
|
||||
$modelSubset = new $conductor->class();
|
||||
foreach ($limitFields as $field) {
|
||||
$modelSubset->setAttribute($field, $model->$field);
|
||||
}
|
||||
$model = $modelSubset;
|
||||
}
|
||||
|
||||
// Includes
|
||||
$includes = $conductor->includes;
|
||||
if ($request !== null && $request->has('includes') === true) {
|
||||
$includes = explode(',', $request->input('includes', ''));
|
||||
}
|
||||
$conductor->includes($model, $includes);
|
||||
|
||||
// Transform
|
||||
$model = $conductor->transform($model);
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter a single field in the conductor collection.
|
||||
*
|
||||
* @param string $field The field name.
|
||||
* @param mixed $value The value or array of values to filter.
|
||||
* @param string $boolean The comparision boolean (AND or OR).
|
||||
* @return void
|
||||
*/
|
||||
final public function filterField(string $field, mixed $value, string $boolean = 'AND')
|
||||
{
|
||||
$this->filterFieldWithBuilder($this->query, $field, $value, $boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or Set the conductor collection.
|
||||
*
|
||||
* @param Collection $collection If not null, use the passed collection.
|
||||
* @return Collection The current conductor collection.
|
||||
*/
|
||||
// final public function collection(Collection $collection = null)
|
||||
// {
|
||||
// if ($collection !== null) {
|
||||
// $this->collection = $collection;
|
||||
// }
|
||||
|
||||
// return $this->collection;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Return the current conductor collection count.
|
||||
*
|
||||
* @return integer The current collection count.
|
||||
*/
|
||||
final public function count()
|
||||
{
|
||||
if ($this->query !== null) {
|
||||
return $this->query->count();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort the conductor collection.
|
||||
*
|
||||
* @param mixed $fields A field name or array of field names to sort. Supports a prefix of + or - to change direction.
|
||||
* @return void
|
||||
*/
|
||||
final public function sort(mixed $fields = null)
|
||||
{
|
||||
if (is_string($fields) === true) {
|
||||
$fields = explode(',', $fields);
|
||||
} elseif ($fields === null) {
|
||||
$fields = $this->sort;
|
||||
}
|
||||
|
||||
if (is_array($fields) === true) {
|
||||
foreach ($fields as $orderByField) {
|
||||
$direction = 'asc';
|
||||
$directionChar = substr($orderByField, 0, 1);
|
||||
|
||||
if (in_array($directionChar, ['-', '+']) === true) {
|
||||
$orderByField = substr($orderByField, 1);
|
||||
if ($directionChar === '-') {
|
||||
$direction = 'desc';
|
||||
}
|
||||
}
|
||||
|
||||
$this->query->orderBy(trim($orderByField), $direction);
|
||||
}
|
||||
} else {
|
||||
throw new \InvalidArgumentException('Expected string or array, got ' . gettype($fields));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the conductor collection based on an array of field => value.
|
||||
*
|
||||
* @param array $filters An array of field => value to filter.
|
||||
* @return void
|
||||
*/
|
||||
final public function filter(array $filters)
|
||||
{
|
||||
foreach ($filters as $param => $value) {
|
||||
$this->filterField($param, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Paginate the conductor collection.
|
||||
*
|
||||
* @param integer $page The current page to return.
|
||||
* @param integer $limit The limit of items to include or use default.
|
||||
* @return void
|
||||
*/
|
||||
final public function paginate(int $page = 1, int $limit = -1)
|
||||
{
|
||||
// Limit
|
||||
if ($limit < 1) {
|
||||
$limit = $this->limit;
|
||||
} else {
|
||||
$limit = min($limit, $this->maxLimit);
|
||||
}
|
||||
$this->query->limit($limit);
|
||||
|
||||
// Page
|
||||
if ($page < 1) {
|
||||
$page = 1;
|
||||
}
|
||||
$this->query->offset(($page - 1) * $limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a list of includes to the model.
|
||||
*
|
||||
* @param Model $model The model to append.
|
||||
* @param array $includes The list of includes to include.
|
||||
* @return void
|
||||
*/
|
||||
final public function includes(Model $model, array $includes)
|
||||
{
|
||||
foreach ($includes as $include) {
|
||||
$includeMethodName = 'include' . Str::studly($include);
|
||||
if (method_exists($this, $includeMethodName) === true) {
|
||||
$attributeName = Str::snake($include);
|
||||
$attributeValue = $this->{$includeMethodName}($model);
|
||||
if ($attributeValue !== null) {
|
||||
$model->$attributeName = $this->{$includeMethodName}($model);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Limit the returned fields in the conductor collection.
|
||||
*
|
||||
* @param array $fields An array of field names.
|
||||
* @return void
|
||||
*/
|
||||
final public function limitFields(array $fields)
|
||||
{
|
||||
if (empty($fields) !== true) {
|
||||
$this->query->select($fields);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the conductor collection using raw data.
|
||||
*
|
||||
* @param string $filterString The raw filter string to parse.
|
||||
* @param array|null $limitFields The fields to ignore in the filter string.
|
||||
* @return void
|
||||
*/
|
||||
final public function filterRaw(string $filterString, array|null $limitFields = null)
|
||||
{
|
||||
if (is_array($limitFields) === false || empty($limitFields) === true) {
|
||||
$limitFields = null;
|
||||
} else {
|
||||
$limitFields = array_map('strtolower', $limitFields);
|
||||
}
|
||||
|
||||
$tokens = preg_split('/([()]|,OR,|,AND,|,)/', $filterString, -1, (PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE));
|
||||
$glued = [];
|
||||
$glueToken = '';
|
||||
foreach ($tokens as $item) {
|
||||
if ($glueToken === '') {
|
||||
if (preg_match('/(?<!\\\\)[\'"]/', $item, $matches, PREG_OFFSET_CAPTURE) === 1) {
|
||||
$glueToken = $matches[0][0];
|
||||
$item = substr($item, 0, $matches[0][1]) . substr($item, ($matches[0][1] + 1));
|
||||
$item = str_replace("\\$glueToken", $glueToken, $item);
|
||||
}
|
||||
|
||||
$glued[] = $item;
|
||||
} else {
|
||||
// search for ending glue token
|
||||
if (preg_match('/(?<!\\\\)' . $glueToken . '/', $item, $matches, PREG_OFFSET_CAPTURE) === 1) {
|
||||
$item = substr($item, 0, $matches[0][1]) . substr($item, ($matches[0][1] + 1));
|
||||
$glueToken = '';
|
||||
}
|
||||
|
||||
$item = str_replace("\\$glueToken", $glueToken, $item);
|
||||
|
||||
$glued[(count($glued) - 1)] .= $item;
|
||||
}
|
||||
}//end foreach
|
||||
$tokens = $glued;
|
||||
|
||||
$parseTokens = function ($tokenList, $level, $index, $groupBoolean = null) use ($limitFields, &$parseTokens) {
|
||||
$tokenGroup = [];
|
||||
$firstToken = false;
|
||||
$tokenGroupBoolean = 'AND';
|
||||
|
||||
if ($groupBoolean !== null) {
|
||||
$firstToken = true;
|
||||
$tokenGroupBoolean = $groupBoolean;
|
||||
}
|
||||
|
||||
while ($index < count($tokenList)) {
|
||||
$token = $tokenList[$index];
|
||||
|
||||
++$index;
|
||||
if ($token === '(') {
|
||||
// next group
|
||||
$nextGroupBoolean = null;
|
||||
if (count($tokenGroup) > 0 && strlen($tokenGroup[(count($tokenGroup) - 1)]['field']) === 0) {
|
||||
$nextGroupBoolean = $tokenGroup[(count($tokenGroup) - 1)]['boolean'];
|
||||
unset($tokenGroup[(count($tokenGroup) - 1)]);
|
||||
}
|
||||
|
||||
$index = $parseTokens($tokenList, $level + 1, $index, $nextGroupBoolean);
|
||||
} elseif ($token === ')') {
|
||||
// end group
|
||||
break;
|
||||
} elseif (in_array(strtoupper($token), [',AND,', ',OR,']) === true) {
|
||||
// update boolean
|
||||
$boolean = trim(strtoupper($token), ',');
|
||||
|
||||
if ($firstToken === false && $level > 0) {
|
||||
$tokenGroupBoolean = $boolean;
|
||||
} else {
|
||||
$firstToken = true;
|
||||
$tokenGroup[] = [
|
||||
'field' => '',
|
||||
'value' => '',
|
||||
'boolean' => $boolean
|
||||
];
|
||||
}
|
||||
} elseif (strpos($token, ':') !== false) {
|
||||
// set tokenGroup
|
||||
$firstToken = true;
|
||||
$field = substr($token, 0, strpos($token, ':'));
|
||||
$value = substr($token, (strpos($token, ':') + 1));
|
||||
$boolean = 'AND';
|
||||
|
||||
if (count($tokenGroup) > 0 && strlen($tokenGroup[(count($tokenGroup) - 1)]['field']) === 0) {
|
||||
$tokenGroup[(count($tokenGroup) - 1)]['field'] = $field;
|
||||
$tokenGroup[(count($tokenGroup) - 1)]['value'] = $value;
|
||||
$boolean = $tokenGroup[(count($tokenGroup) - 1)]['boolean'];
|
||||
} else {
|
||||
$tokenGroup[] = [
|
||||
'field' => $field,
|
||||
'value' => $value,
|
||||
'boolean' => 'AND'
|
||||
];
|
||||
}
|
||||
|
||||
if ($limitFields === null || in_array(strtolower($field), $limitFields) !== true) {
|
||||
unset($tokenGroup[(count($tokenGroup) - 1)]);
|
||||
}
|
||||
|
||||
if ($level === 0) {
|
||||
$this->filterFieldWithBuilder($this->query, $field, $value, $boolean);
|
||||
}
|
||||
}//end if
|
||||
}//end while
|
||||
|
||||
if ($level > 0) {
|
||||
if ($tokenGroupBoolean === 'OR') {
|
||||
$this->query->orWhere(function ($query) use ($tokenGroup) {
|
||||
foreach ($tokenGroup as $tokenItem) {
|
||||
if (strlen($tokenItem['field']) > 0) {
|
||||
$this->filterFieldWithBuilder($query, $tokenItem['field'], $tokenItem['value'], $tokenItem['boolean']);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
$this->query->where(function ($query) use ($tokenGroup) {
|
||||
foreach ($tokenGroup as $tokenItem) {
|
||||
if (strlen($tokenItem['field']) > 0) {
|
||||
$this->filterFieldWithBuilder($query, $tokenItem['field'], $tokenItem['value'], $tokenItem['boolean']);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}//end if
|
||||
|
||||
return $index;
|
||||
};
|
||||
|
||||
$parseTokens($tokens, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a scope query on the collection before anything else.
|
||||
*
|
||||
* @param Builder $builder The builder in use.
|
||||
* @return void
|
||||
*/
|
||||
public function scope(Builder $builder)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array of model fields visible to the current user.
|
||||
*
|
||||
* @param Model $model The model in question.
|
||||
* @return array The array of field names.
|
||||
*/
|
||||
public function fields(Model $model)
|
||||
{
|
||||
$visibleFields = $model->getVisible();
|
||||
if (empty($visibleFields) === true) {
|
||||
$visibleFields = $model->getConnection()
|
||||
->getSchemaBuilder()
|
||||
->getColumnListing($model->getTable());
|
||||
}
|
||||
|
||||
$appends = $model->getAppends();
|
||||
if(is_array($appends) === true) {
|
||||
$visibleFields = array_merge($visibleFields, $appends);
|
||||
}
|
||||
|
||||
return $visibleFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the passed Model to an array
|
||||
*
|
||||
* @param Model $model The model to transform.
|
||||
* @return array The transformed model.
|
||||
*/
|
||||
public function transform(Model $model)
|
||||
{
|
||||
$result = $model->toArray();
|
||||
|
||||
$fields = $this->fields($model);
|
||||
if(is_array($fields) === true) {
|
||||
$result = array_intersect_key($result, array_flip($fields));
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the passed model viewable by the current user?
|
||||
*
|
||||
* @param Model $model The model in question.
|
||||
* @return boolean Is the model viewable.
|
||||
*/
|
||||
public static function viewable(Model $model)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the model creatable by the current user?
|
||||
*
|
||||
* @return boolean Is the model creatable.
|
||||
*/
|
||||
public static function creatable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the passed model updateable by the current user?
|
||||
*
|
||||
* @param Model $model The model in question.
|
||||
* @return boolean Is the model updateable.
|
||||
*/
|
||||
public static function updatable(Model $model)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the passed model destroyable by the current user?
|
||||
*
|
||||
* @param Model $model The model in question.
|
||||
* @return boolean Is the model destroyable.
|
||||
*/
|
||||
public static function destroyable(Model $model)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,110 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Conductors;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\InvalidCastException;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class EventConductor extends Conductor
|
||||
{
|
||||
/**
|
||||
* The Model Class
|
||||
* @var string
|
||||
*/
|
||||
protected $class = '\App\Models\Event';
|
||||
|
||||
/**
|
||||
* The default sorting field
|
||||
* @var string
|
||||
*/
|
||||
protected $sort = 'start_at';
|
||||
|
||||
|
||||
/**
|
||||
* Run a scope query on the collection before anything else.
|
||||
*
|
||||
* @param Builder $builder The builder in use.
|
||||
* @return void
|
||||
*/
|
||||
public function scope(Builder $builder)
|
||||
{
|
||||
$user = auth()->user();
|
||||
if ($user === null || $user->hasPermission('admin/events') === false) {
|
||||
$builder
|
||||
->where('status', '!=', 'draft')
|
||||
->where('publish_at', '<=', now());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is visible.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow model to be visible.
|
||||
*/
|
||||
public static function viewable(Model $model)
|
||||
{
|
||||
if (strtolower($model->status) === 'draft' || Carbon::parse($model->publish_at)->isFuture() === true) {
|
||||
$user = auth()->user();
|
||||
if ($user === null || $user->hasPermission('admin/events') === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is creatable.
|
||||
*
|
||||
* @return boolean Allow creating model.
|
||||
*/
|
||||
public static function creatable()
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && $user->hasPermission('admin/events') === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is updatable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow updating model.
|
||||
*/
|
||||
public static function updatable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && $user->hasPermission('admin/events') === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is destroyable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow deleting model.
|
||||
*/
|
||||
public static function destroyable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && $user->hasPermission('admin/events') === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the model
|
||||
*
|
||||
* @param Model $model The model to transform.
|
||||
* @return array The transformed model.
|
||||
* @throws InvalidCastException Cannot cast item to model.
|
||||
*/
|
||||
public function transform(Model $model)
|
||||
{
|
||||
$result = $model->toArray();
|
||||
$result['attachments'] = $model->attachments()->get()->map(function ($attachment) {
|
||||
return MediaConductor::model(request(), $attachment->media);
|
||||
});
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Conductors;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class MediaConductor extends Conductor
|
||||
{
|
||||
/**
|
||||
* The Model Class
|
||||
* @var string
|
||||
*/
|
||||
protected $class = '\App\Models\Media';
|
||||
|
||||
/**
|
||||
* The default sorting field
|
||||
* @var string
|
||||
*/
|
||||
protected $sort = 'created_at';
|
||||
|
||||
|
||||
/**
|
||||
* Return an array of model fields visible to the current user.
|
||||
*
|
||||
* @param Model $model The model in question.
|
||||
* @return array The array of field names.
|
||||
*/
|
||||
public function fields(Model $model)
|
||||
{
|
||||
$fields = parent::fields($model);
|
||||
|
||||
$user = auth()->user();
|
||||
if ($user === null || $user->hasPermission('admin/media') === false) {
|
||||
$fields = arrayRemoveItem($fields, 'permission');
|
||||
}
|
||||
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a scope query on the collection before anything else.
|
||||
*
|
||||
* @param Builder $builder The builder in use.
|
||||
* @return void
|
||||
*/
|
||||
public function scope(Builder $builder)
|
||||
{
|
||||
$user = auth()->user();
|
||||
if ($user === null) {
|
||||
$builder->whereNull('permission');
|
||||
} else {
|
||||
$builder->whereNull('permission')->orWhereIn('permission', $user->permissions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is visible.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow model to be visible.
|
||||
*/
|
||||
public static function viewable(Model $model)
|
||||
{
|
||||
if ($model->permission !== null) {
|
||||
$user = auth()->user();
|
||||
if ($user === null || $user->hasPermission($model->permission) === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is creatable.
|
||||
*
|
||||
* @return boolean Allow creating model.
|
||||
*/
|
||||
public static function creatable()
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is updatable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow updating model.
|
||||
*/
|
||||
public static function updatable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && (strcasecmp($model->user_id, $user->id) === 0 || $user->hasPermission('admin/media') === true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is destroyable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow deleting model.
|
||||
*/
|
||||
public static function destroyable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && ($model->user_id === $user->id || $user->hasPermission('admin/media') === true));
|
||||
}
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Conductors;
|
||||
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PostConductor extends Conductor
|
||||
{
|
||||
/**
|
||||
* The Model Class
|
||||
* @var string
|
||||
*/
|
||||
protected $class = '\App\Models\Post';
|
||||
|
||||
/**
|
||||
* The default sorting field
|
||||
* @var string
|
||||
*/
|
||||
protected $sort = '-publish_at';
|
||||
|
||||
|
||||
/**
|
||||
* Run a scope query on the collection before anything else.
|
||||
*
|
||||
* @param Builder $builder The builder in use.
|
||||
* @return void
|
||||
*/
|
||||
public function scope(Builder $builder)
|
||||
{
|
||||
$user = auth()->user();
|
||||
if ($user === null || $user->hasPermission('admin/posts') === false) {
|
||||
$builder
|
||||
->where('publish_at', '<=', now());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is visible.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow model to be visible.
|
||||
*/
|
||||
public static function viewable(Model $model)
|
||||
{
|
||||
if (Carbon::parse($model->publish_at)->isFuture() === true) {
|
||||
$user = auth()->user();
|
||||
if ($user === null || $user->hasPermission('admin/posts') === false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is creatable.
|
||||
*
|
||||
* @return boolean Allow creating model.
|
||||
*/
|
||||
public static function creatable()
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && $user->hasPermission('admin/posts') === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is updatable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow updating model.
|
||||
*/
|
||||
public static function updatable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && $user->hasPermission('admin/posts') === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is destroyable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow deleting model.
|
||||
*/
|
||||
public static function destroyable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && $user->hasPermission('admin/posts') === true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the model
|
||||
*
|
||||
* @param Model $model The model to transform.
|
||||
* @return array The transformed model.
|
||||
* @throws InvalidCastException Cannot cast item to model.
|
||||
*/
|
||||
public function transform(Model $model)
|
||||
{
|
||||
$result = $model->toArray();
|
||||
$result['attachments'] = $model->attachments()->get()->map(function ($attachment) {
|
||||
return MediaConductor::model(request(), $attachment->media);
|
||||
});
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Conductors;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SubscriptionConductor extends Conductor
|
||||
{
|
||||
/**
|
||||
* The Model Class
|
||||
* @var string
|
||||
*/
|
||||
protected $class = '\App\Models\Subscription';
|
||||
|
||||
|
||||
/**
|
||||
* Return if the current model is updatable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow updating model.
|
||||
*/
|
||||
public static function updatable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && ((strcasecmp($model->email, $user->email) === 0 && $user->email_verified_at !== null) || $user->hasPermission('admin/subscriptions') === true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is destroyable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow deleting model.
|
||||
*/
|
||||
public static function destroyable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && ((strcasecmp($model->email, $user->email) === 0 && $user->email_verified_at !== null) || $user->hasPermission('admin/subscriptions') === true));
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Conductors;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UserConductor extends Conductor
|
||||
{
|
||||
/**
|
||||
* The Model Class
|
||||
* @var string
|
||||
*/
|
||||
protected $class = '\App\Models\User';
|
||||
|
||||
|
||||
/**
|
||||
* Return the visible API fields.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return string[] The fields visible.
|
||||
*/
|
||||
public function fields(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
if ($user === null || $user->hasPermission('admin/users') === false) {
|
||||
return ['id', 'username'];
|
||||
}
|
||||
|
||||
return parent::fields($model);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform the passed Model to an array
|
||||
*
|
||||
* @param Model $model The model to transform.
|
||||
* @return array The transformed model.
|
||||
*/
|
||||
public function transform(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
$data = $model->toArray();
|
||||
|
||||
if ($user === null || ($user->hasPermission('admin/users') === false && strcasecmp($user->id, $model->id) !== 0)) {
|
||||
$fields = ['id', 'username'];
|
||||
$data = arrayLimitKeys($data, $fields);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is updatable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow updating model.
|
||||
*/
|
||||
public static function updatable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
if ($user !== null) {
|
||||
return ($user->hasPermission('admin/users') === true || strcasecmp($user->id, $model->id) === 0);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return if the current model is destroyable.
|
||||
*
|
||||
* @param Model $model The model.
|
||||
* @return boolean Allow deleting model.
|
||||
*/
|
||||
public static function destroyable(Model $model)
|
||||
{
|
||||
$user = auth()->user();
|
||||
return ($user !== null && $user->hasPermission('admin/users') === true);
|
||||
}
|
||||
}
|
||||
@@ -9,23 +9,18 @@ class Kernel extends ConsoleKernel
|
||||
{
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule The schedule.
|
||||
* @return void
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
protected function schedule(Schedule $schedule): void
|
||||
{
|
||||
// $schedule->command('inspire')->hourly();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the commands for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function commands()
|
||||
protected function commands(): void
|
||||
{
|
||||
$this->load(__DIR__ . '/Commands');
|
||||
$this->load(__DIR__.'/Commands');
|
||||
|
||||
require base_path('routes/console.php');
|
||||
}
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enum;
|
||||
|
||||
class CurlErrorCodes extends Enum
|
||||
{
|
||||
public const CURLE_UNSUPPORTED_PROTOCOL = 1;
|
||||
public const CURLE_FAILED_INIT = 2;
|
||||
public const CURLE_URL_MALFORMAT = 3;
|
||||
public const CURLE_URL_MALFORMAT_USER = 4;
|
||||
public const CURLE_COULDNT_RESOLVE_PROXY = 5;
|
||||
public const CURLE_COULDNT_RESOLVE_HOST = 6;
|
||||
public const CURLE_COULDNT_CONNECT = 7;
|
||||
public const CURLE_FTP_WEIRD_SERVER_REPLY = 8;
|
||||
public const CURLE_REMOTE_ACCESS_DENIED = 9;
|
||||
public const CURLE_FTP_WEIRD_PASS_REPLY = 11;
|
||||
public const CURLE_FTP_WEIRD_PASV_REPLY = 13;
|
||||
public const CURLE_FTP_WEIRD_227_FORMAT = 14;
|
||||
public const CURLE_FTP_CANT_GET_HOST = 15;
|
||||
public const CURLE_FTP_COULDNT_SET_TYPE = 17;
|
||||
public const CURLE_PARTIAL_FILE = 18;
|
||||
public const CURLE_FTP_COULDNT_RETR_FILE = 19;
|
||||
public const CURLE_QUOTE_ERROR = 21;
|
||||
public const CURLE_HTTP_RETURNED_ERROR = 22;
|
||||
public const CURLE_WRITE_ERROR = 23;
|
||||
public const CURLE_UPLOAD_FAILED = 25;
|
||||
public const CURLE_READ_ERROR = 26;
|
||||
public const CURLE_OUT_OF_MEMORY = 27;
|
||||
public const CURLE_OPERATION_TIMEDOUT = 28;
|
||||
public const CURLE_FTP_PORT_FAILED = 30;
|
||||
public const CURLE_FTP_COULDNT_USE_REST = 31;
|
||||
public const CURLE_RANGE_ERROR = 33;
|
||||
public const CURLE_HTTP_POST_ERROR = 34;
|
||||
public const CURLE_SSL_CONNECT_ERROR = 35;
|
||||
public const CURLE_BAD_DOWNLOAD_RESUME = 36;
|
||||
public const CURLE_FILE_COULDNT_READ_FILE = 37;
|
||||
public const CURLE_LDAP_CANNOT_BIND = 38;
|
||||
public const CURLE_LDAP_SEARCH_FAILED = 39;
|
||||
public const CURLE_FUNCTION_NOT_FOUND = 41;
|
||||
public const CURLE_ABORTED_BY_CALLBACK = 42;
|
||||
public const CURLE_BAD_FUNCTION_ARGUMENT = 43;
|
||||
public const CURLE_INTERFACE_FAILED = 45;
|
||||
public const CURLE_TOO_MANY_REDIRECTS = 47;
|
||||
public const CURLE_UNKNOWN_TELNET_OPTION = 48;
|
||||
public const CURLE_TELNET_OPTION_SYNTAX = 49;
|
||||
public const CURLE_PEER_FAILED_VERIFICATION = 51;
|
||||
public const CURLE_GOT_NOTHING = 52;
|
||||
public const CURLE_SSL_ENGINE_NOTFOUND = 53;
|
||||
public const CURLE_SSL_ENGINE_SETFAILED = 54;
|
||||
public const CURLE_SEND_ERROR = 55;
|
||||
public const CURLE_RECV_ERROR = 56;
|
||||
public const CURLE_SSL_CERTPROBLEM = 58;
|
||||
public const CURLE_SSL_CIPHER = 59;
|
||||
public const CURLE_SSL_CACERT = 60;
|
||||
public const CURLE_BAD_CONTENT_ENCODING = 61;
|
||||
public const CURLE_LDAP_INVALID_URL = 62;
|
||||
public const CURLE_FILESIZE_EXCEEDED = 63;
|
||||
public const CURLE_USE_SSL_FAILED = 64;
|
||||
public const CURLE_SEND_FAIL_REWIND = 65;
|
||||
public const CURLE_SSL_ENGINE_INITFAILED = 66;
|
||||
public const CURLE_LOGIN_DENIED = 67;
|
||||
public const CURLE_TFTP_NOTFOUND = 68;
|
||||
public const CURLE_TFTP_PERM = 69;
|
||||
public const CURLE_REMOTE_DISK_FULL = 70;
|
||||
public const CURLE_TFTP_ILLEGAL = 71;
|
||||
public const CURLE_TFTP_UNKNOWNID = 72;
|
||||
public const CURLE_REMOTE_FILE_EXISTS = 73;
|
||||
public const CURLE_TFTP_NOSUCHUSER = 74;
|
||||
public const CURLE_CONV_FAILED = 75;
|
||||
public const CURLE_CONV_REQD = 76;
|
||||
public const CURLE_SSL_CACERT_BADFILE = 77;
|
||||
public const CURLE_REMOTE_FILE_NOT_FOUND = 78;
|
||||
public const CURLE_SSH = 79;
|
||||
public const CURLE_SSL_SHUTDOWN_FAILED = 80;
|
||||
public const CURLE_AGAIN = 81;
|
||||
public const CURLE_SSL_CRL_BADFILE = 82;
|
||||
public const CURLE_SSL_ISSUER_ERROR = 83;
|
||||
public const CURLE_FTP_PRET_FAILED = 84;
|
||||
public const CURLE_RTSP_CSEQ_ERROR = 85;
|
||||
public const CURLE_RTSP_SESSION_ERROR = 86;
|
||||
public const CURLE_FTP_BAD_FILE_LIST = 87;
|
||||
public const CURLE_CHUNK_FAILED = 88;
|
||||
|
||||
|
||||
/**
|
||||
* Curl Error messages
|
||||
* @var string[]
|
||||
*/
|
||||
public static $messages = [
|
||||
1 => 'Unsupported protocol.',
|
||||
2 => 'Failed initalization.',
|
||||
3 => 'Invalid URL format.',
|
||||
4 => 'CURLE_URL_MALFORMAT_USER.',
|
||||
5 => 'Could not resolve proxy.',
|
||||
6 => 'Could not resolve host.',
|
||||
7 => 'Could not connect to host.',
|
||||
8 => 'Invalid reply from FTP server.',
|
||||
9 => 'Access denied on host.',
|
||||
11 => 'Invalid pass reply from FTP server.',
|
||||
13 => 'Invalid pasv reply from FTP server.',
|
||||
14 => 'Invalid 227 format from FTP server.',
|
||||
15 => 'Could not get FTP host.',
|
||||
17 => 'Could not set type for FTP transfer.',
|
||||
18 => 'Invalid partial size.',
|
||||
19 => 'Could not retrieve file from FTP server.',
|
||||
21 => 'Quote error.',
|
||||
22 => 'HTTP server returned error.',
|
||||
23 => 'File write error.',
|
||||
25 => 'Upload file error.',
|
||||
26 => 'File read error.',
|
||||
27 => 'Out of memory.',
|
||||
28 => 'File transfer timed out.',
|
||||
30 => 'Invalid port for FTP server.',
|
||||
31 => 'Could not use rest for FTP server.',
|
||||
33 => 'File range error.',
|
||||
34 => 'Invalid POST for HTTP server.',
|
||||
35 => 'SSL connectio error.',
|
||||
36 => 'Invalid resume download.',
|
||||
37 => 'Could not read file.',
|
||||
38 => 'Could not bind to LDAP.',
|
||||
39 => 'LDAP search failed.',
|
||||
41 => 'Function not found.',
|
||||
42 => 'Aborted by callback.',
|
||||
43 => 'Bad function argument.',
|
||||
45 => 'Interface failed.',
|
||||
47 => 'Too many redirects.',
|
||||
48 => 'Unknown telnet option.',
|
||||
49 => 'Telnet option syntax invalid.',
|
||||
51 => 'Peer failed verification.',
|
||||
52 => 'Did not receive any data.',
|
||||
53 => 'SSL engine was not found.',
|
||||
54 => 'SSL engine failed.',
|
||||
55 => 'Send data error.',
|
||||
56 => 'Receive data error.',
|
||||
58 => 'SSL certificate error.',
|
||||
59 => 'SSL cipher error.',
|
||||
60 => 'SSL CACertificate failed.',
|
||||
61 => 'Invalid content encoding.',
|
||||
62 => 'Invalid LDAP url.',
|
||||
63 => 'Filesize exceeded.',
|
||||
64 => 'SSL Failed.',
|
||||
65 => 'CURLE_SEND_FAIL_REWIND.',
|
||||
66 => 'SSL engine initalization failed.',
|
||||
67 => 'CURLE_LOGIN_DENIED.',
|
||||
68 => 'CURLE_TFTP_NOTFOUND.',
|
||||
69 => 'CURLE_TFTP_PERM.',
|
||||
70 => 'CURLE_REMOTE_DISK_FULL.',
|
||||
71 => 'CURLE_TFTP_ILLEGAL.',
|
||||
72 => 'CURLE_TFTP_UNKNOWNID.',
|
||||
73 => 'Remote file already exists.',
|
||||
74 => 'No such user on FTP server.',
|
||||
75 => 'Conversion failed.',
|
||||
76 => 'Conversion required.',
|
||||
77 => 'SSL CACertificate bad file.',
|
||||
78 => 'Remove file not found.',
|
||||
79 => 'SSH error.',
|
||||
80 => 'SSL Shutdown failed.',
|
||||
81 => 'Again.',
|
||||
82 => 'SSL bad CRL file.',
|
||||
83 => 'SSL issuer error.',
|
||||
84 => 'FTP pret failed.',
|
||||
85 => 'CURLE_RTSP_CSEQ_ERROR.',
|
||||
86 => 'CURLE_RTSP_SESSION_ERROR.',
|
||||
87 => 'CURLE_FTP_BAD_FILE_LIST.',
|
||||
88 => 'CURLE_CHUNK_FAILED.',
|
||||
|
||||
|
||||
];
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enum;
|
||||
|
||||
use ReflectionClass;
|
||||
|
||||
class Enum
|
||||
{
|
||||
/**
|
||||
* Message list
|
||||
*
|
||||
* @var array<string<static>>
|
||||
*/
|
||||
public static $messages = [];
|
||||
|
||||
/**
|
||||
* Caches reflections of enum subclasses.
|
||||
*
|
||||
* @var array<class-string<static>, ReflectionClass<static>>
|
||||
*/
|
||||
public static $reflectionCache = [];
|
||||
|
||||
|
||||
/**
|
||||
* Returns a reflection of the enum subclass.
|
||||
*
|
||||
* @return ReflectionClass<static>
|
||||
*/
|
||||
public static function getReflection(): ReflectionClass
|
||||
{
|
||||
$class = static::class;
|
||||
|
||||
return static::$reflectionCache[$class] ??= new ReflectionClass($class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the constants in the enum subclass
|
||||
*
|
||||
* @return array<static>
|
||||
*/
|
||||
public static function getConstants(): array
|
||||
{
|
||||
return static::getReflection()->getConstants();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the constants values in the enum subclass
|
||||
*
|
||||
* @return array<static>
|
||||
*/
|
||||
public static function getConstantValues(): array
|
||||
{
|
||||
return array_values(static::getReflection()->getConstants());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a message from the enum subclass
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function getMessage(int $messageIndex, string $defaultMessage = 'Unknown'): string
|
||||
{
|
||||
if(array_key_exists($messageIndex, self::$messages) === true) {
|
||||
return self::$messages[$messageIndex];
|
||||
}
|
||||
|
||||
return $defaultMessage;
|
||||
}
|
||||
}
|
||||
@@ -1,165 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Enum;
|
||||
|
||||
class HttpResponseCodes extends Enum
|
||||
{
|
||||
public const HTTP_CONTINUE = 100;
|
||||
public const HTTP_SWITCHING_PROTOCOLS = 101;
|
||||
public const HTTP_PROCESSING = 102;
|
||||
|
||||
public const HTTP_OK = 200;
|
||||
public const HTTP_CREATED = 201;
|
||||
public const HTTP_ACCEPTED = 202;
|
||||
public const HTTP_NON_AUTHORITATIVE_INFORMATION = 203;
|
||||
public const HTTP_NO_CONTENT = 204;
|
||||
public const HTTP_RESET_CONTENT = 205;
|
||||
public const HTTP_PARTIAL_CONTENT = 206;
|
||||
public const HTTP_MULTI_STATUS = 207;
|
||||
|
||||
public const HTTP_ALREADY_REPORTED = 208;
|
||||
|
||||
public const HTTP_IM_USED = 226;
|
||||
|
||||
public const HTTP_MULTIPLE_CHOICES = 300;
|
||||
public const HTTP_MOVED_PERMANENTLY = 301;
|
||||
public const HTTP_FOUND = 302;
|
||||
public const HTTP_SEE_OTHER = 303;
|
||||
public const HTTP_NOT_MODIFIED = 304;
|
||||
public const HTTP_USE_PROXY = 305;
|
||||
public const HTTP_RESERVED = 306;
|
||||
public const HTTP_TEMPORARY_REDIRECT = 307;
|
||||
public const HTTP_PERMANENTLY_REDIRECT = 308;
|
||||
|
||||
public const HTTP_BAD_REQUEST = 400;
|
||||
public const HTTP_UNAUTHORIZED = 401;
|
||||
public const HTTP_PAYMENT_REQUIRED = 402;
|
||||
public const HTTP_FORBIDDEN = 403;
|
||||
public const HTTP_NOT_FOUND = 404;
|
||||
public const HTTP_METHOD_NOT_ALLOWED = 405;
|
||||
public const HTTP_NOT_ACCEPTABLE = 406;
|
||||
public const HTTP_PROXY_AUTHENTICATION_REQUIRED = 407;
|
||||
public const HTTP_REQUEST_TIMEOUT = 408;
|
||||
public const HTTP_CONFLICT = 409;
|
||||
public const HTTP_GONE = 410;
|
||||
public const HTTP_LENGTH_REQUIRED = 411;
|
||||
public const HTTP_PRECONDITION_FAILED = 412;
|
||||
public const HTTP_REQUEST_ENTITY_TOO_LARGE = 413;
|
||||
public const HTTP_REQUEST_URI_TOO_LONG = 414;
|
||||
public const HTTP_UNSUPPORTED_MEDIA_TYPE = 415;
|
||||
public const HTTP_REQUESTED_RANGE_NOT_SATISFIABLE = 416;
|
||||
public const HTTP_EXPECTATION_FAILED = 417;
|
||||
public const HTTP_I_AM_A_TEAPOT = 418;
|
||||
|
||||
public const HTTP_MISDIRECTED_REQUEST = 421;
|
||||
public const HTTP_UNPROCESSABLE_ENTITY = 422;
|
||||
public const HTTP_LOCKED = 423;
|
||||
public const HTTP_FAILED_DEPENDENCY = 424;
|
||||
public const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425;
|
||||
public const HTTP_UPGRADE_REQUIRED = 426;
|
||||
public const HTTP_PRECONDITION_REQUIRED = 428;
|
||||
public const HTTP_TOO_MANY_REQUESTS = 429;
|
||||
public const HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
|
||||
public const HTTP_UNAVAILABLE_FOR_LEGAL_REASONS = 451;
|
||||
|
||||
public const HTTP_INTERNAL_SERVER_ERROR = 500;
|
||||
public const HTTP_NOT_IMPLEMENTED = 501;
|
||||
public const HTTP_BAD_GATEWAY = 502;
|
||||
public const HTTP_SERVICE_UNAVAILABLE = 503;
|
||||
public const HTTP_GATEWAY_TIMEOUT = 504;
|
||||
public const HTTP_VERSION_NOT_SUPPORTED = 505;
|
||||
public const HTTP_VARIANT_ALSO_NEGOTIATES_EXPERIMENTAL = 506;
|
||||
public const HTTP_INSUFFICIENT_STORAGE = 507;
|
||||
public const HTTP_LOOP_DETECTED = 508;
|
||||
public const HTTP_NOT_EXTENDED = 510;
|
||||
public const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511;
|
||||
|
||||
/**
|
||||
* HTTP Response Messages
|
||||
* @var string[]
|
||||
*/
|
||||
public static $statusTexts = [
|
||||
100 => 'Continue.',
|
||||
101 => 'Switching Protocols.',
|
||||
102 => 'Processing.',
|
||||
// RFC2518
|
||||
200 => 'OK.',
|
||||
201 => 'Created.',
|
||||
202 => 'Accepted.',
|
||||
203 => 'Non-Authoritative Information.',
|
||||
204 => 'No Content.',
|
||||
205 => 'Reset Content.',
|
||||
206 => 'Partial Content.',
|
||||
207 => 'Multi-Status.',
|
||||
// RFC4918
|
||||
208 => 'Already Reported.',
|
||||
// RFC5842
|
||||
226 => 'IM Used.',
|
||||
// RFC3229
|
||||
300 => 'Multiple Choices.',
|
||||
301 => 'Moved Permanently.',
|
||||
302 => 'Found.',
|
||||
303 => 'See Other.',
|
||||
304 => 'Not Modified.',
|
||||
305 => 'Use Proxy.',
|
||||
307 => 'Temporary Redirect.',
|
||||
308 => 'Permanent Redirect.',
|
||||
// RFC7238
|
||||
400 => 'Bad Request.',
|
||||
401 => 'Unauthorized.',
|
||||
402 => 'Payment Required.',
|
||||
403 => 'Forbidden.',
|
||||
404 => 'Not Found.',
|
||||
405 => 'Method Not Allowed.',
|
||||
406 => 'Not Acceptable.',
|
||||
407 => 'Proxy Authentication Required.',
|
||||
408 => 'Request Timeout.',
|
||||
409 => 'Conflict.',
|
||||
410 => 'Gone.',
|
||||
411 => 'Length Required.',
|
||||
412 => 'Precondition Failed.',
|
||||
413 => 'Payload Too Large.',
|
||||
414 => 'URI Too Long.',
|
||||
415 => 'Unsupported Media Type.',
|
||||
416 => 'Range Not Satisfiable.',
|
||||
417 => 'Expectation Failed.',
|
||||
418 => 'I\'m a teapot.',
|
||||
// RFC2324
|
||||
421 => 'Misdirected Request.',
|
||||
// RFC7540
|
||||
422 => 'Unprocessable Entity.',
|
||||
// RFC4918
|
||||
423 => 'Locked.',
|
||||
// RFC4918
|
||||
424 => 'Failed Dependency.',
|
||||
// RFC4918
|
||||
425 => 'Reserved for WebDAV advanced collections expired proposal.',
|
||||
// RFC2817
|
||||
426 => 'Upgrade Required.',
|
||||
// RFC2817
|
||||
428 => 'Precondition Required.',
|
||||
// RFC6585
|
||||
429 => 'Too Many Requests.',
|
||||
// RFC6585
|
||||
431 => 'Request Header Fields Too Large.',
|
||||
// RFC6585
|
||||
451 => 'Unavailable For Legal Reasons.',
|
||||
// RFC7725
|
||||
500 => 'Internal Server Error.',
|
||||
501 => 'Not Implemented.',
|
||||
502 => 'Bad Gateway.',
|
||||
503 => 'Service Unavailable.',
|
||||
504 => 'Gateway Timeout.',
|
||||
505 => 'HTTP Version Not Supported.',
|
||||
506 => 'Variant Also Negotiates.',
|
||||
// RFC2295
|
||||
507 => 'Insufficient Storage.',
|
||||
// RFC4918
|
||||
508 => 'Loop Detected.',
|
||||
// RFC5842
|
||||
510 => 'Not Extended.',
|
||||
// RFC2774
|
||||
511 => 'Network Authentication Required.',
|
||||
// RFC6585
|
||||
];
|
||||
}
|
||||
@@ -2,36 +2,13 @@
|
||||
|
||||
namespace App\Exceptions;
|
||||
|
||||
use App\Enum\HttpResponseCodes;
|
||||
use Exception;
|
||||
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
use Throwable;
|
||||
use PDOException;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
/**
|
||||
* A list of exception types with their corresponding custom log levels.
|
||||
*
|
||||
* @var array<class-string<\Throwable>, \Psr\Log\LogLevel::*>
|
||||
*/
|
||||
protected $levels = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the exception types that are not reported.
|
||||
*
|
||||
* @var array<int, class-string<\Throwable>>
|
||||
*/
|
||||
protected $dontReport = [
|
||||
//
|
||||
];
|
||||
|
||||
/**
|
||||
* A list of the inputs that are never flashed to the session on validation exceptions.
|
||||
* The list of the inputs that are never flashed to the session on validation exceptions.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
@@ -41,43 +18,11 @@ class Handler extends ExceptionHandler
|
||||
'password_confirmation',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Register the exception handling callbacks for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
public function register(): void
|
||||
{
|
||||
// $this->renderable(function (HttpException $e, $request) {
|
||||
// if ($request->is('api/*')) {
|
||||
// $message = $e->getMessage();
|
||||
// if ($message === '') {
|
||||
// $message = HttpResponseCodes::$statusTexts[$e->getStatusCode()];
|
||||
// }
|
||||
|
||||
// return response()->json([
|
||||
// 'message' => $message
|
||||
// ], $e->getStatusCode());
|
||||
// }
|
||||
// });
|
||||
|
||||
$this->renderable(function (NotFoundHttpException $e, $request) {
|
||||
if ($request->is('api/*') === true) {
|
||||
return response()->json([
|
||||
'message' => 'Resource not found'
|
||||
], 404);
|
||||
}
|
||||
});
|
||||
|
||||
$this->renderable(function (PDOException $e, $request) {
|
||||
if ($request->is('api/*') === true) {
|
||||
return response()->json([
|
||||
'message' => 'The server is currently unavailable'
|
||||
], 503);
|
||||
}
|
||||
});
|
||||
|
||||
$this->reportable(function (Throwable $e) {
|
||||
//
|
||||
});
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Models\Subscriber;
|
||||
|
||||
class SubscriptionFilter extends FilterAbstract
|
||||
{
|
||||
/**
|
||||
* The model class to filter
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $class = '\App\Models\Subscription';
|
||||
|
||||
|
||||
/**
|
||||
* Return an array of attributes visible in the results
|
||||
*
|
||||
* @param array $attributes Attributes currently visible.
|
||||
* @param User|null $user Current logged in user or null.
|
||||
* @return mixed
|
||||
*/
|
||||
protected function seeAttributes(array $attributes, mixed $user)
|
||||
{
|
||||
if ($user?->hasPermission('admin/users') !== true) {
|
||||
return ['id', 'email', 'confirmed_at'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
/* Array Helper Functions */
|
||||
|
||||
|
||||
/**
|
||||
* Remove an item from an array.
|
||||
*
|
||||
* @param array $arr The array to check.
|
||||
* @param string|array $item The item or items to remove.
|
||||
* @return array The filtered array.
|
||||
*/
|
||||
function arrayRemoveItem(array $arr, string|array $item): array
|
||||
{
|
||||
$filteredArr = $arr;
|
||||
|
||||
if (is_string($item) === true) {
|
||||
$item = [$item];
|
||||
}
|
||||
|
||||
foreach ($item as $str) {
|
||||
$filteredArr = array_filter($arr, function ($item) use ($str) {
|
||||
return $item !== $str;
|
||||
});
|
||||
}
|
||||
|
||||
return $filteredArr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an array with specified the keys
|
||||
*
|
||||
* @param array $arr The array to filter.
|
||||
* @param string|array $keys The keys to keep.
|
||||
* @return array The filtered array.
|
||||
*/
|
||||
function arrayLimitKeys(array $arr, array $keys): array
|
||||
{
|
||||
return array_intersect_key($arr, array_flip($keys));
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Enum\HttpResponseCodes;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ApiController extends Controller
|
||||
{
|
||||
/**
|
||||
* Resource name
|
||||
* @var string
|
||||
*/
|
||||
protected $resourceName = '';
|
||||
|
||||
|
||||
/**
|
||||
* Return generic json response with the given data.
|
||||
*
|
||||
* @param array $data Response data.
|
||||
* @param integer $respondCode Response status code.
|
||||
* @param array $headers Response headers.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function respondJson(array $data, int $respondCode = HttpResponseCodes::HTTP_OK, array $headers = [])
|
||||
{
|
||||
return response()->json($data, $respondCode, $headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return forbidden message
|
||||
*
|
||||
* @param string $message Response message.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function respondForbidden(string $message = 'You do not have permission to access the resource.')
|
||||
{
|
||||
return response()->json(['message' => $message], HttpResponseCodes::HTTP_FORBIDDEN);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return forbidden message
|
||||
*
|
||||
* @param string $message Response message.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function respondNotFound(string $message = 'The resource was not found.')
|
||||
{
|
||||
return response()->json(['message' => $message], HttpResponseCodes::HTTP_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return too large message
|
||||
*
|
||||
* @param string $message Response message.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function respondTooLarge(string $message = 'The request entity is too large.')
|
||||
{
|
||||
return response()->json(['message' => $message], HttpResponseCodes::HTTP_REQUEST_ENTITY_TOO_LARGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return no content
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function respondNoContent()
|
||||
{
|
||||
return response()->json([], HttpResponseCodes::HTTP_NO_CONTENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return created
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function respondCreated()
|
||||
{
|
||||
return response()->json([], HttpResponseCodes::HTTP_CREATED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return single error message
|
||||
*
|
||||
* @param string $message Error message.
|
||||
* @param integer $responseCode Resource code.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function respondError(string $message, int $responseCode = HttpResponseCodes::HTTP_UNPROCESSABLE_ENTITY)
|
||||
{
|
||||
return response()->json([
|
||||
'message' => $message
|
||||
], $responseCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return formatted errors
|
||||
*
|
||||
* @param array $errors Error messages.
|
||||
* @param integer $responseCode Resource code.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function respondWithErrors(array $errors, int $responseCode = HttpResponseCodes::HTTP_UNPROCESSABLE_ENTITY)
|
||||
{
|
||||
$keys = array_keys($errors);
|
||||
$error = $errors[$keys[0]];
|
||||
|
||||
if (count($keys) > 1) {
|
||||
$additional_errors = (count($keys) - 1);
|
||||
$error .= sprintf(' (and %d more %s', $additional_errors, Str::plural('error', $additional_errors));
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'message' => $error,
|
||||
'errors' => $errors
|
||||
], $responseCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return resource data
|
||||
*
|
||||
* @param array|Model|Collection $data Resource data.
|
||||
* @param array $options Respond options.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
protected function respondAsResource(
|
||||
mixed $data,
|
||||
array $options = [],
|
||||
) {
|
||||
$isCollection = $options['isCollection'] ?? false;
|
||||
$appendData = $options['appendData'] ?? null;
|
||||
$resourceName = $options['resourceName'] ?? null;
|
||||
$respondCode = $options['respondCode'] ?? HttpResponseCodes::HTTP_OK;
|
||||
|
||||
if ($data === null || ($data instanceof Collection && $data->count() === 0)) {
|
||||
return $this->respondNotFound();
|
||||
}
|
||||
|
||||
if(is_null($resourceName) === true || empty($resourceName) === true) {
|
||||
$resourceName = $this->resourceName;
|
||||
}
|
||||
|
||||
if(is_null($resourceName) === true || empty($resourceName) === true) {
|
||||
$resourceName = get_class($this);
|
||||
$resourceName = substr($resourceName, (strrpos($resourceName, '\\') + 1));
|
||||
$resourceName = substr($resourceName, 0, strpos($resourceName, 'Controller'));
|
||||
$resourceName = strtolower($resourceName);
|
||||
}
|
||||
|
||||
$dataArray = [];
|
||||
if ($data instanceof Collection) {
|
||||
$dataArray = $data->toArray();
|
||||
} elseif (is_array($data) === true) {
|
||||
$dataArray = $data;
|
||||
} elseif ($data instanceof Model) {
|
||||
$is_multiple = false;
|
||||
$dataArray = $data->toArray();
|
||||
}
|
||||
|
||||
$resource = [];
|
||||
if ($isCollection === true) {
|
||||
$resource = [Str::plural($resourceName) => $dataArray];
|
||||
} else {
|
||||
$resource = [Str::singular($resourceName) => $dataArray];
|
||||
}
|
||||
|
||||
if ($appendData !== null) {
|
||||
$resource += $appendData;
|
||||
}
|
||||
|
||||
return response()->json($resource, $respondCode);
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Models\Attachment;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class AttachmentController extends ApiController
|
||||
{
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth:sanctum')
|
||||
->except(['store', 'destroyByEmail']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \App\Models\Attachment $attachment
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Attachment $attachment)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for editing the specified resource.
|
||||
*
|
||||
* @param \App\Models\Attachment $attachment
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function edit(Attachment $attachment)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \App\Models\Attachment $attachment
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, Attachment $attachment)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Attachment $attachment
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Attachment $attachment)
|
||||
{
|
||||
//
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Enum\HttpResponseCodes;
|
||||
use App\Http\Requests\AuthLoginRequest;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class AuthController extends ApiController
|
||||
{
|
||||
/**
|
||||
* Resource name
|
||||
* @var string
|
||||
*/
|
||||
protected $resourceName = 'user';
|
||||
|
||||
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// $this->middleware('auth:sanctum')
|
||||
// ->only(['me']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Current User details
|
||||
*
|
||||
* @param Request $request Current request data.
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function me(Request $request)
|
||||
{
|
||||
$user = $request->user()->makeVisible(['permissions']);
|
||||
return $this->respondAsResource($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Login user with supplied creditials
|
||||
*
|
||||
* @param App\Http\Controllers\Api\AuthLoginRequest $request Created request data.
|
||||
* @return JsonResponse|void
|
||||
*/
|
||||
public function login(AuthLoginRequest $request)
|
||||
{
|
||||
$user = User::where('username', '=', $request->input('username'))->first();
|
||||
|
||||
if ($user !== null && Hash::check($request->input('password'), $user->password) === true) {
|
||||
if ($user->email_verified_at === null) {
|
||||
return $this->respondWithErrors([
|
||||
'username' => 'Email address has not been verified.'
|
||||
]);
|
||||
}
|
||||
|
||||
if ($user->disabled === true) {
|
||||
return $this->respondWithErrors([
|
||||
'username' => 'Account has been disabled.'
|
||||
]);
|
||||
}
|
||||
|
||||
$token = $user->createToken('user_token')->plainTextToken;
|
||||
|
||||
$user->logins()->create([
|
||||
'token' => $token,
|
||||
'login' => now(),
|
||||
'ip_address' => $request->ip(),
|
||||
'user_agent' => $request->userAgent()
|
||||
]);
|
||||
|
||||
return $this->respondAsResource(
|
||||
$user->makeVisible(['permissions']),
|
||||
['appendData' => ['token' => $token]]
|
||||
);
|
||||
}//end if
|
||||
|
||||
return $this->respondWithErrors([
|
||||
'username' => 'Invalid username or password',
|
||||
'password' => 'Invalid username or password',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout current user
|
||||
*
|
||||
* @param Request $request Current request data.
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function logout(Request $request)
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
$user->logins()->where('token', $user->currentAccessToken())->update(['logout' => now()]);
|
||||
$user->currentAccessToken()->delete();
|
||||
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Requests\ContactSendRequest;
|
||||
use App\Jobs\SendEmailJob;
|
||||
use App\Mail\Contact;
|
||||
|
||||
class ContactController extends ApiController
|
||||
{
|
||||
/**
|
||||
* Send the request to the site admin by email
|
||||
*
|
||||
* @param \App\Http\Requests\User\ContactSendRequest $request Request data.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function send(ContactSendRequest $request)
|
||||
{
|
||||
dispatch((new SendEmailJob(
|
||||
config('contact.contact_address'),
|
||||
new Contact(
|
||||
$request->input('name'),
|
||||
$request->input('email'),
|
||||
$request->input('content')
|
||||
)
|
||||
)))->onQueue('mail');
|
||||
|
||||
return $this->respondCreated();
|
||||
}
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Enum\HttpResponseCodes;
|
||||
use App\Models\Event;
|
||||
use App\Conductors\EventConductor;
|
||||
use App\Conductors\MediaConductor;
|
||||
use App\Http\Requests\EventRequest;
|
||||
use App\Models\Media;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class EventController extends ApiController
|
||||
{
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth:sanctum')
|
||||
->only(['store','update','destroy']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
list($collection, $total) = EventConductor::request($request);
|
||||
|
||||
return $this->respondAsResource(
|
||||
$collection,
|
||||
['isCollection' => true,
|
||||
'appendData' => ['total' => $total]
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @param \App\Models\Event $event The specified event.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Request $request, Event $event)
|
||||
{
|
||||
if (EventConductor::viewable($event) === true) {
|
||||
return $this->respondAsResource(EventConductor::model($request, $event));
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\EventRequest $request The request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(EventRequest $request)
|
||||
{
|
||||
if (EventConductor::creatable() === true) {
|
||||
$event = Event::create($request->all());
|
||||
return $this->respondAsResource(
|
||||
EventConductor::model($request, $event),
|
||||
['respondCode' => HttpResponseCodes::HTTP_CREATED]
|
||||
);
|
||||
} else {
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\EventRequest $request The endpoint request.
|
||||
* @param \App\Models\Event $event The specified event.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(EventRequest $request, Event $event)
|
||||
{
|
||||
if (EventConductor::updatable($event) === true) {
|
||||
$event->update($request->all());
|
||||
return $this->respondAsResource(EventConductor::model($request, $event));
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Event $event The specified event.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Event $event)
|
||||
{
|
||||
if (EventConductor::destroyable($event) === true) {
|
||||
$event->delete();
|
||||
return $this->respondNoContent();
|
||||
} else {
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of attachments related to this model.
|
||||
*
|
||||
* @param Request $request The user request.
|
||||
* @param Post $post The post model.
|
||||
* @return JsonResponse Returns the post attachments.
|
||||
* @throws InvalidFormatException
|
||||
* @throws BindingResolutionException
|
||||
* @throws InvalidCastException
|
||||
*/
|
||||
public function getAttachments(Request $request, Event $event)
|
||||
{
|
||||
if (EventConductor::viewable($event) === true) {
|
||||
$medium = $event->attachments->map(function ($attachment) {
|
||||
return $attachment->media;
|
||||
});
|
||||
|
||||
return $this->respondAsResource(MediaConductor::collection($request, $medium), ['isCollection' => true, 'resourceName' => 'attachment']);
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an attachment related to this model.
|
||||
*
|
||||
* @param Request $request The user request.
|
||||
* @param Post $post The post model.
|
||||
* @return JsonResponse The response.
|
||||
* @throws BindingResolutionException
|
||||
* @throws MassAssignmentException
|
||||
*/
|
||||
public function storeAttachment(Request $request, Event $event)
|
||||
{
|
||||
if (EventConductor::updatable($event) === true) {
|
||||
if ($request->has("medium") && Media::find($request->medium)) {
|
||||
$event->attachments()->create(['media_id' => $request->medium]);
|
||||
return $this->respondCreated();
|
||||
}
|
||||
|
||||
return $this->respondWithErrors(['media' => 'The media ID was not found']);
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update/replace attachments related to this model.
|
||||
*
|
||||
* @param Request $request The user request.
|
||||
* @param Post $post The related model.
|
||||
* @return JsonResponse
|
||||
* @throws BindingResolutionException
|
||||
* @throws MassAssignmentException
|
||||
*/
|
||||
public function updateAttachments(Request $request, Event $event)
|
||||
{
|
||||
if (EventConductor::updatable($event) === true) {
|
||||
$mediaIds = $request->attachments;
|
||||
if (is_array($mediaIds) === false) {
|
||||
$mediaIds = explode(',', $request->attachments);
|
||||
}
|
||||
|
||||
$mediaIds = array_map('trim', $mediaIds); // trim each media ID
|
||||
$attachments = $event->attachments;
|
||||
|
||||
// Delete attachments that are not in $mediaIds
|
||||
foreach ($attachments as $attachment) {
|
||||
if (!in_array($attachment->media_id, $mediaIds)) {
|
||||
$attachment->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Create new attachments for media IDs that are not already in $post->attachments()
|
||||
foreach ($mediaIds as $mediaId) {
|
||||
$found = false;
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
if ($attachment->media_id == $mediaId) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
$event->attachments()->create(['media_id' => $mediaId]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->respondNoContent();
|
||||
}//end if
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a specific related attachment.
|
||||
* @param Request $request The user request.
|
||||
* @param Post $post The model.
|
||||
* @param Media $medium The attachment medium.
|
||||
* @return JsonResponse
|
||||
* @throws BindingResolutionException
|
||||
*/
|
||||
public function deleteAttachment(Request $request, Event $event, Media $medium)
|
||||
{
|
||||
if (EventConductor::updatable($event) === true) {
|
||||
$attachments = $event->attachments;
|
||||
$deleted = false;
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
if ($attachment->media_id === $medium->id) {
|
||||
$attachment->delete();
|
||||
$deleted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleted) {
|
||||
// Attachment was deleted successfully
|
||||
return $this->respondNoContent();
|
||||
} else {
|
||||
// Attachment with matching media ID was not found
|
||||
return $this->respondNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class LogController extends ApiController
|
||||
{
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth:sanctum')
|
||||
->only(['show']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Request $request The log request.
|
||||
* @param string $name The log name.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Request $request, string $name)
|
||||
{
|
||||
if ($request->user()?->hasPermission('logs/' . $name) === true) {
|
||||
switch (strtolower($name)) {
|
||||
case 'discord':
|
||||
$data = [];
|
||||
|
||||
$log = $request->get('log');
|
||||
if ($log === null) {
|
||||
$log = ['output', 'error'];
|
||||
} else {
|
||||
$log = explode(',', strtolower($log));
|
||||
}
|
||||
|
||||
$lines = intval($request->get('lines', 50));
|
||||
if ($lines > 100) {
|
||||
$lines = 100;
|
||||
} elseif ($lines < 0) {
|
||||
$lines = 1;
|
||||
}
|
||||
|
||||
$before = $request->get('before');
|
||||
if ($before !== null) {
|
||||
$before = preg_split("/([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/", $before, -1, (PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY));
|
||||
if (count($before) !== 6) {
|
||||
$before = null;
|
||||
}
|
||||
}
|
||||
|
||||
$after = $request->get('after');
|
||||
if ($after !== null) {
|
||||
$after = preg_split("/([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})/", $after, -1, (PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY));
|
||||
if (count($after) !== 6) {
|
||||
$after = null;
|
||||
}
|
||||
}
|
||||
|
||||
$logFiles = [
|
||||
[
|
||||
'name' => 'output',
|
||||
'path' => '/home/discordbot/.pm2/logs/stemmech-discordbot-out-0.log'
|
||||
],[
|
||||
'name' => 'error',
|
||||
'path' => '/home/discordbot/.pm2/logs/stemmech-discordbot-error-0.log'
|
||||
]
|
||||
];
|
||||
|
||||
foreach ($logFiles as $logFile) {
|
||||
if (in_array($logFile['name'], $log) === true) {
|
||||
$logContent = '';
|
||||
|
||||
if (file_exists($logFile['path']) === true) {
|
||||
$logContent = file_get_contents($logFile['path']);
|
||||
}
|
||||
|
||||
$logArray = preg_split("/(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}: (?:(?!\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}: )[\s\S])*)/", $logContent, -1, (PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY));
|
||||
|
||||
$logContent = '';
|
||||
$logLineCount = 0;
|
||||
$logLineSkip = false;
|
||||
foreach (array_reverse($logArray) as $logLine) {
|
||||
$lineDate = preg_split("/^([0-9]{4})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2}): /", $logLine, -1, (PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY));
|
||||
if (count($lineDate) >= 6) {
|
||||
$logLineSkip = false;
|
||||
|
||||
// Is line before
|
||||
if ($before !== null && ($lineDate[0] > $before[0] || $lineDate[1] > $before[1] || $lineDate[2] > $before[2] || $lineDate[3] > $before[3] || $lineDate[4] > $before[4] || $lineDate[5] > $before[5])) {
|
||||
$logLineSkip = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is line after
|
||||
if ($after !== null && ($after[0] > $lineDate[0] || $after[1] > $lineDate[1] || $after[2] > $lineDate[2] || $after[3] > $lineDate[3] || $after[4] > $lineDate[4] || $after[5] > $lineDate[5])) {
|
||||
$logLineSkip = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$logLineCount += 1;
|
||||
}
|
||||
|
||||
if ($logLineCount > $lines) {
|
||||
break;
|
||||
}
|
||||
|
||||
if ($logLineSkip === false) {
|
||||
$logContent .= $logLine;
|
||||
}
|
||||
}//end foreach
|
||||
|
||||
$data[$logFile['name']] = $logContent;
|
||||
}//end if
|
||||
}//end foreach
|
||||
|
||||
return $this->respondJson([
|
||||
'log' => $data
|
||||
]);
|
||||
}//end switch
|
||||
}//end if
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
@@ -1,257 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Conductors\MediaConductor;
|
||||
use App\Enum\HttpResponseCodes;
|
||||
use App\Http\Requests\MediaRequest;
|
||||
use App\Models\Media;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Laravel\Sanctum\PersonalAccessToken;
|
||||
|
||||
class MediaController extends ApiController
|
||||
{
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth:sanctum')
|
||||
->only(['store','update','destroy']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
list($collection, $total) = MediaConductor::request($request);
|
||||
|
||||
return $this->respondAsResource(
|
||||
$collection,
|
||||
['isCollection' => true,
|
||||
'appendData' => ['total' => $total]]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @param \App\Models\Media $medium The request media.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Request $request, Media $medium)
|
||||
{
|
||||
if (MediaConductor::viewable($medium) === true) {
|
||||
return $this->respondAsResource(MediaConductor::model($request, $medium));
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a new media resource
|
||||
*
|
||||
* @param \App\Http\Requests\MediaRequest $request The uploaded media.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(MediaRequest $request)
|
||||
{
|
||||
if (MediaConductor::creatable() === true) {
|
||||
$file = $request->file('file');
|
||||
if ($file === null) {
|
||||
return $this->respondWithErrors(['file' => 'The browser did not upload the file correctly to the server.']);
|
||||
}
|
||||
|
||||
if ($file->isValid() !== true) {
|
||||
switch ($file->getError()) {
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
return $this->respondTooLarge();
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
return $this->respondWithErrors(['file' => 'The file upload was interrupted.']);
|
||||
default:
|
||||
return $this->respondWithErrors(['file' => 'An error occurred uploading the file to the server.']);
|
||||
}
|
||||
}
|
||||
|
||||
if ($file->getSize() > Media::maxUploadSize()) {
|
||||
return $this->respondTooLarge();
|
||||
}
|
||||
|
||||
$title = $file->getClientOriginalName();
|
||||
$mime = $file->getMimeType();
|
||||
$fileInfo = Media::store($file, empty($request->input('permission')));
|
||||
if ($fileInfo === null) {
|
||||
return $this->respondWithErrors(
|
||||
['file' => 'The file could not be stored on the server'],
|
||||
HttpResponseCodes::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
$request->merge([
|
||||
'title' => $title,
|
||||
'mime' => $mime,
|
||||
'name' => $fileInfo['name'],
|
||||
'size' => filesize($fileInfo['path'])
|
||||
]);
|
||||
|
||||
$media = $request->user()->media()->create($request->all());
|
||||
return $this->respondAsResource(
|
||||
MediaConductor::model($request, $media),
|
||||
['respondCode' => HttpResponseCodes::HTTP_CREATED]
|
||||
);
|
||||
}//end if
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the media resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\MediaRequest $request The update request.
|
||||
* @param \App\Models\Media $medium The specified media.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(MediaRequest $request, Media $medium)
|
||||
{
|
||||
if (MediaConductor::updatable($medium) === true) {
|
||||
$file = $request->file('file');
|
||||
if ($file !== null) {
|
||||
if ($file->getSize() > Media::maxUploadSize()) {
|
||||
return $this->respondTooLarge();
|
||||
}
|
||||
|
||||
$oldPath = $medium->path();
|
||||
$fileInfo = Media::store($file, empty($request->input('permission')));
|
||||
if ($fileInfo === null) {
|
||||
return $this->respondWithErrors(
|
||||
['file' => 'The file could not be stored on the server'],
|
||||
HttpResponseCodes::HTTP_INTERNAL_SERVER_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
if (file_exists($oldPath) === true) {
|
||||
unlink($oldPath);
|
||||
}
|
||||
|
||||
$request->merge([
|
||||
'title' => $file->getClientOriginalName(),
|
||||
'mime' => $file->getMimeType(),
|
||||
'name' => $fileInfo['name'],
|
||||
'size' => filesize($fileInfo['path'])
|
||||
]);
|
||||
}//end if
|
||||
|
||||
$medium->update($request->all());
|
||||
return $this->respondAsResource(MediaConductor::model($request, $medium));
|
||||
}//end if
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Media $medium Specified media file.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Media $medium)
|
||||
{
|
||||
if (MediaConductor::destroyable($medium) === true) {
|
||||
if (file_exists($medium->path()) === true) {
|
||||
unlink($medium->path());
|
||||
}
|
||||
|
||||
$medium->delete();
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @param \App\Models\Media $medium Specified media.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function download(Request $request, Media $medium)
|
||||
{
|
||||
$respondJson = in_array('application/json', explode(',', $request->header('Accept', 'application/json')));
|
||||
|
||||
$headers = [];
|
||||
$path = $medium->path();
|
||||
|
||||
/* File exists */
|
||||
if (file_exists($path) === false) {
|
||||
if ($respondJson === false) {
|
||||
return redirect('/not-found');
|
||||
} else {
|
||||
return $this->respondNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
$updated_at = Carbon::parse(filemtime($path));
|
||||
|
||||
$headerPragma = 'no-cache';
|
||||
$headerCacheControl = 'max-age=0, must-revalidate';
|
||||
$headerExpires = $updated_at->toRfc2822String();
|
||||
|
||||
if (empty($medium->permission) === true) {
|
||||
if ($request->user() === null && $request->has('token') === true) {
|
||||
$accessToken = PersonalAccessToken::findToken(urldecode($request->input('token')));
|
||||
|
||||
if (
|
||||
$accessToken !== null && (config('sanctum.expiration') === null ||
|
||||
$accessToken->created_at->lte(now()->subMinutes(config('sanctum.expiration'))) === false)
|
||||
) {
|
||||
$user = $accessToken->tokenable;
|
||||
}
|
||||
}
|
||||
if ($request->user() === null || $user->hasPermission($medium->permission) === false) {
|
||||
if ($respondJson === false) {
|
||||
return redirect('/login?redirect=' . $request->path());
|
||||
} else {
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$headerPragma = 'public';
|
||||
$headerExpires = $updated_at->addMonth()->toRfc2822String();
|
||||
}//end if
|
||||
|
||||
// deepcode ignore InsecureHash: Browsers expect Etag to be a md5 hash
|
||||
$headerEtag = md5($updated_at->format('U'));
|
||||
$headerLastModified = $updated_at->toRfc2822String();
|
||||
|
||||
$headers = [
|
||||
'Cache-Control' => $headerCacheControl,
|
||||
'Content-Disposition' => sprintf('inline; filename="%s"', basename($path)),
|
||||
'Etag' => $headerEtag,
|
||||
'Expires' => $headerExpires,
|
||||
'Last-Modified' => $headerLastModified,
|
||||
'Pragma' => $headerPragma,
|
||||
];
|
||||
|
||||
$server = request()->server;
|
||||
|
||||
$requestModifiedSince = $server->has('HTTP_IF_MODIFIED_SINCE') &&
|
||||
$server->get('HTTP_IF_MODIFIED_SINCE') === $headerLastModified;
|
||||
|
||||
$requestNoneMatch = $server->has('HTTP_IF_NONE_MATCH') &&
|
||||
$server->get('HTTP_IF_NONE_MATCH') === $headerEtag;
|
||||
|
||||
if ($requestModifiedSince === true || $requestNoneMatch === true) {
|
||||
return response()->make('', 304, $headers);
|
||||
}
|
||||
|
||||
return response()->file($path, $headers);
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use thiagoalessio\TesseractOCR\TesseractOCR;
|
||||
use FFMpeg;
|
||||
use App\Enum\CurlErrorCodes;
|
||||
|
||||
class OCRController extends ApiController
|
||||
{
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
// $this->middleware('auth:sanctum')
|
||||
// ->only(['show']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param Request $request The log request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Request $request)
|
||||
{
|
||||
// if ($request->user()?->hasPermission('logs/' . $name) === true) {
|
||||
$url = $request->get('url');
|
||||
if ($url !== null) {
|
||||
$data = ['ocr' => []];
|
||||
|
||||
$filters = $request->get('filters', ['tesseract']);
|
||||
if(is_array($filters) === false) {
|
||||
$filters = explode(',', $filters);
|
||||
}
|
||||
|
||||
$tesseractOEM = $request->get('tesseract.oem');
|
||||
$tesseractDigits = $request->get('tesseract.digits');
|
||||
$tesseractAllowlist = $request->get('tesseract.allowlist');
|
||||
|
||||
// Download URL
|
||||
$urlDownloadFilePath = tempnam(sys_get_temp_dir(), 'download');
|
||||
$maxDownloadSize = (1024 * 1024); // 1MB
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
|
||||
|
||||
// We need progress updates to break the connection mid-way
|
||||
curl_setopt($ch, CURLOPT_BUFFERSIZE, 128); // more progress info
|
||||
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
|
||||
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function(
|
||||
$downloadSize, $downloaded, $uploadSize, $uploaded
|
||||
) use($maxDownloadSize) {
|
||||
return ($downloaded > $maxDownloadSize) ? 1 : 0;
|
||||
});
|
||||
|
||||
$curlResult = curl_exec($ch);
|
||||
$curlError = curl_errno($ch);
|
||||
$curlSize = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
|
||||
curl_close($ch);
|
||||
if($curlError !== 0) {
|
||||
$error = 'File size is larger then allowed';
|
||||
if($curlError !== CurlErrorCodes::CURLE_ABORTED_BY_CALLBACK) {
|
||||
$error = CurlErrorCodes::getMessage($curlError);
|
||||
}
|
||||
|
||||
return $this->respondWithErrors(['url' => $error]);
|
||||
}
|
||||
|
||||
// Save url file
|
||||
file_put_contents($urlDownloadFilePath, $curlResult);
|
||||
$urlDownloadFilePathBase = preg_replace('/\\.[^.\\s]{3,4}$/', '', $urlDownloadFilePath);
|
||||
|
||||
// tesseract (overall)
|
||||
$ocr = null;
|
||||
foreach($filters as $filterItem) {
|
||||
if(str_starts_with($filterItem, 'tesseract') === true) {
|
||||
$ocr = new TesseractOCR();
|
||||
$ocr->image($urlDownloadFilePath);
|
||||
if ($tesseractOEM !== null) {
|
||||
$ocr->oem($tesseractOEM);
|
||||
}
|
||||
if ($tesseractDigits !== null) {
|
||||
$ocr->digits();
|
||||
}
|
||||
if ($tesseractAllowlist !== null) {
|
||||
$ocr->allowlist($tesseractAllowlist);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Image Filter Function
|
||||
$tesseractImageFilterFunc = function($filter, $options = null) use($curlResult, $curlSize, $ocr) {
|
||||
$result = '';
|
||||
$img = imagecreatefromstring($curlResult);
|
||||
if ($img !== false && (($options !== null && imagefilter($img, $filter, $options) === true) || ($options === null && imagefilter($img, $filter) === true))) {
|
||||
|
||||
ob_start();
|
||||
imagepng($img);
|
||||
$imgData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$imgDataSize = strlen($imgData);
|
||||
|
||||
$ocr->imageData($imgData, $imgDataSize);
|
||||
imagedestroy($img);
|
||||
|
||||
$result = $ocr->run(500);
|
||||
}
|
||||
|
||||
return $result;
|
||||
};
|
||||
|
||||
// Image Scale Function
|
||||
$tesseractImageScaleFunc = function($scaleFunc) use ($curlResult, $ocr) {
|
||||
$result = '';
|
||||
$srcImage = imagecreatefromstring($curlResult);
|
||||
$srcWidth = imagesx($srcImage);
|
||||
$srcHeight = imagesy($srcImage);
|
||||
|
||||
$dstWidth = $scaleFunc($srcWidth);
|
||||
$dstHeight = $scaleFunc($srcHeight);
|
||||
$dstImage = imagecreatetruecolor($dstWidth, $dstHeight);
|
||||
|
||||
imagecopyresampled($dstImage, $srcImage, 0, 0, 0, 0, $dstWidth, $dstHeight, $srcWidth, $srcHeight);
|
||||
|
||||
ob_start();
|
||||
imagepng($dstImage);
|
||||
$imgData = ob_get_contents();
|
||||
ob_end_clean();
|
||||
$imgDataSize = strlen($imgData);
|
||||
|
||||
imagedestroy($srcImage);
|
||||
imagedestroy($dstImage);
|
||||
|
||||
$ocr->imageData($imgData, $imgDataSize);
|
||||
$result = $ocr->run(500);
|
||||
return $result;
|
||||
};
|
||||
|
||||
// filter: tesseract
|
||||
if(in_array('tesseract', $filters) === true) {
|
||||
$data['ocr']['tesseract'] = $ocr->run(500);
|
||||
}
|
||||
|
||||
// filter: tesseract.grayscale
|
||||
if (in_array('tesseract.grayscale', $filters) === true) {
|
||||
$data['ocr']['tesseract.grayscale'] = $tesseractImageFilterFunc(IMG_FILTER_GRAYSCALE);
|
||||
}
|
||||
|
||||
// filter: tesseract.double_scale
|
||||
if (in_array('tesseract.double_scale', $filters) === true) {
|
||||
$data['ocr']['tesseract.double_scale'] = $tesseractImageScaleFunc(function($size) {
|
||||
return $size * 2;
|
||||
});
|
||||
}
|
||||
|
||||
// filter: tesseract.half_scale
|
||||
if (in_array('tesseract.half_scale', $filters) === true) {
|
||||
$data['ocr']['tesseract.half_scale'] = $tesseractImageScaleFunc(function($size) {
|
||||
return $size / 2;
|
||||
});
|
||||
}
|
||||
|
||||
// filter: tesseract.edgedetect
|
||||
if (in_array('tesseract.edgedetect', $filters) === true) {
|
||||
$data['ocr']['tesseract.edgedetect'] = $tesseractImageFilterFunc(IMG_FILTER_EDGEDETECT);
|
||||
}
|
||||
|
||||
// filter: tesseract.mean_removal
|
||||
if (in_array('tesseract.mean_removal', $filters) === true) {
|
||||
$data['ocr']['tesseract.mean_removal'] = $tesseractImageFilterFunc(IMG_FILTER_MEAN_REMOVAL);
|
||||
}
|
||||
|
||||
// filter: tesseract.negate
|
||||
if (in_array('tesseract.negate', $filters) === true) {
|
||||
$data['ocr']['tesseract.negate'] = $tesseractImageFilterFunc(IMG_FILTER_NEGATE);
|
||||
}
|
||||
|
||||
// filter: tesseract.pixelate
|
||||
if (in_array('tesseract.pixelate', $filters) === true) {
|
||||
$data['ocr']['tesseract.pixelate'] = $tesseractImageFilterFunc(IMG_FILTER_PIXELATE, 3);
|
||||
}
|
||||
|
||||
// filter: keras
|
||||
if(in_array('keras', $filters) === true) {
|
||||
$cmd = '/usr/bin/python3 ' . base_path() . '/scripts/keras_oc.py ' . urlencode($url);
|
||||
$command = escapeshellcmd($cmd);
|
||||
$output = shell_exec($cmd);
|
||||
if ($output !== null && strlen($output) > 0) {
|
||||
$output = substr($output, strpos($output, '----------START----------') + 25);
|
||||
} else {
|
||||
$output = '';
|
||||
}
|
||||
$data['ocr']['keras'] = $output;
|
||||
}
|
||||
|
||||
unlink($urlDownloadFilePath);
|
||||
return $this->respondJson($data);
|
||||
}//end if
|
||||
|
||||
return $this->respondWithErrors(['url' => 'url is missing']);
|
||||
}
|
||||
|
||||
// $ffmpeg = FFMpeg\FFMpeg::create();
|
||||
|
||||
// // Load the input video
|
||||
// $inputFile = $ffmpeg->open('input.mp4');
|
||||
|
||||
// // Split the video into individual frames
|
||||
// $videoFrames = $inputFile->frames();
|
||||
// foreach ($videoFrames as $frame) {
|
||||
// // Save the frame as a PNG
|
||||
// $frame->save(new FFMpeg\Format\Video\PNG(), 'frame-' . $frame->getMetadata('pts') . '.png');
|
||||
|
||||
// // Pass the PNG to Tesseract for processing
|
||||
// exec("tesseract frame-" . $frame->getMetadata('pts') . ".png output");
|
||||
// }
|
||||
|
||||
// // Read the output from Tesseract
|
||||
// $text = file_get_contents("output.txt");
|
||||
|
||||
// // Do something with the text from Tesseract
|
||||
// echo $text;
|
||||
}
|
||||
@@ -1,246 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Conductors\MediaConductor;
|
||||
use App\Conductors\PostConductor;
|
||||
use App\Enum\HttpResponseCodes;
|
||||
use App\Http\Requests\PostRequest;
|
||||
use App\Models\Media;
|
||||
use App\Models\Post;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
||||
use Illuminate\Database\Eloquent\InvalidCastException;
|
||||
use Illuminate\Database\Eloquent\MassAssignmentException;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class PostController extends ApiController
|
||||
{
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth:sanctum')
|
||||
->only([
|
||||
'store',
|
||||
'update',
|
||||
'delete'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
list($collection, $total) = PostConductor::request($request);
|
||||
|
||||
return $this->respondAsResource(
|
||||
$collection,
|
||||
['isCollection' => true,
|
||||
'appendData' => ['total' => $total]]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @param \App\Models\Post $post The post model.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Request $request, Post $post)
|
||||
{
|
||||
if (PostConductor::viewable($post) === true) {
|
||||
return $this->respondAsResource(PostConductor::model($request, $post));
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\PostRequest $request The user request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(PostRequest $request)
|
||||
{
|
||||
if (PostConductor::creatable() === true) {
|
||||
$post = Post::create($request->all());
|
||||
return $this->respondAsResource(
|
||||
PostConductor::model($request, $post),
|
||||
['respondCode' => HttpResponseCodes::HTTP_CREATED]
|
||||
);
|
||||
} else {
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\PostRequest $request The post update request.
|
||||
* @param \App\Models\Post $post The specified post.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(PostRequest $request, Post $post)
|
||||
{
|
||||
if (PostConductor::updatable($post) === true) {
|
||||
$post->update($request->all());
|
||||
return $this->respondAsResource(PostConductor::model($request, $post));
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Models\Post $post The specified post.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Post $post)
|
||||
{
|
||||
if (PostConductor::destroyable($post) === true) {
|
||||
$post->delete();
|
||||
return $this->respondNoContent();
|
||||
} else {
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of attachments related to this model.
|
||||
*
|
||||
* @param Request $request The user request.
|
||||
* @param Post $post The post model.
|
||||
* @return JsonResponse Returns the post attachments.
|
||||
* @throws InvalidFormatException
|
||||
* @throws BindingResolutionException
|
||||
* @throws InvalidCastException
|
||||
*/
|
||||
public function getAttachments(Request $request, Post $post)
|
||||
{
|
||||
if (PostConductor::viewable($post) === true) {
|
||||
$medium = $post->attachments->map(function ($attachment) {
|
||||
return $attachment->media;
|
||||
});
|
||||
|
||||
return $this->respondAsResource(MediaConductor::collection($request, $medium), ['isCollection' => true, 'resourceName' => 'attachment']);
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store an attachment related to this model.
|
||||
*
|
||||
* @param Request $request The user request.
|
||||
* @param Post $post The post model.
|
||||
* @return JsonResponse The response.
|
||||
* @throws BindingResolutionException
|
||||
* @throws MassAssignmentException
|
||||
*/
|
||||
public function storeAttachment(Request $request, Post $post)
|
||||
{
|
||||
if (PostConductor::updatable($post) === true) {
|
||||
if($request->has("medium") && Media::find($request->medium)) {
|
||||
$post->attachments()->create(['media_id' => $request->medium]);
|
||||
return $this->respondCreated();
|
||||
}
|
||||
|
||||
return $this->respondWithErrors(['media' => 'The media ID was not found']);
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update/replace attachments related to this model.
|
||||
*
|
||||
* @param Request $request The user request.
|
||||
* @param Post $post The related model.
|
||||
* @return JsonResponse
|
||||
* @throws BindingResolutionException
|
||||
* @throws MassAssignmentException
|
||||
*/
|
||||
public function updateAttachments(Request $request, Post $post)
|
||||
{
|
||||
if (PostConductor::updatable($post) === true) {
|
||||
$mediaIds = $request->attachments;
|
||||
if(is_array($mediaIds) === false) {
|
||||
$mediaIds = explode(',', $request->attachments);
|
||||
}
|
||||
|
||||
$mediaIds = array_map('trim', $mediaIds); // trim each media ID
|
||||
$attachments = $post->attachments;
|
||||
|
||||
// Delete attachments that are not in $mediaIds
|
||||
foreach ($attachments as $attachment) {
|
||||
if (!in_array($attachment->media_id, $mediaIds)) {
|
||||
$attachment->delete();
|
||||
}
|
||||
}
|
||||
|
||||
// Create new attachments for media IDs that are not already in $post->attachments()
|
||||
foreach ($mediaIds as $mediaId) {
|
||||
$found = false;
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
if ($attachment->media_id == $mediaId) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$found) {
|
||||
$post->attachments()->create(['media_id' => $mediaId]);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a specific related attachment.
|
||||
* @param Request $request The user request.
|
||||
* @param Post $post The model.
|
||||
* @param Media $medium The attachment medium.
|
||||
* @return JsonResponse
|
||||
* @throws BindingResolutionException
|
||||
*/
|
||||
public function deleteAttachment(Request $request, Post $post, Media $medium)
|
||||
{
|
||||
if (PostConductor::updatable($post) === true) {
|
||||
$attachments = $post->attachments;
|
||||
$deleted = false;
|
||||
|
||||
foreach ($attachments as $attachment) {
|
||||
if ($attachment->media_id === $medium->id) {
|
||||
$attachment->delete();
|
||||
$deleted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($deleted) {
|
||||
// Attachment was deleted successfully
|
||||
return $this->respondNoContent();
|
||||
} else {
|
||||
// Attachment with matching media ID was not found
|
||||
return $this->respondNotFound();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
@@ -1,145 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Conductors\SubscriptionConductor;
|
||||
use App\Enum\HttpResponseCodes;
|
||||
use App\Models\Subscription;
|
||||
use App\Http\Requests\SubscriptionRequest;
|
||||
use App\Jobs\SendEmailJob;
|
||||
use App\Mail\SubscriptionConfirm;
|
||||
use App\Mail\SubscriptionUnsubscribed;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class SubscriptionController extends ApiController
|
||||
{
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth:sanctum')
|
||||
->except(['store', 'destroyByEmail']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of subscribers.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
list($collection, $total) = SubscriptionConductor::request($request);
|
||||
|
||||
return $this->respondAsResource(
|
||||
$collection,
|
||||
['isCollection' => true,
|
||||
'appendData' => ['total' => $total]]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @param \App\Models\Subscription $subscription The subscription model.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Request $request, Subscription $subscription)
|
||||
{
|
||||
if (SubscriptionConductor::viewable($subscription) === true) {
|
||||
return $this->respondAsResource(SubscriptionConductor::model($request, $subscription));
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a subscriber email in the database.
|
||||
*
|
||||
* @param \App\Http\Requests\SubscriptionRequest $request The subscriber update request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(SubscriptionRequest $request)
|
||||
{
|
||||
if (SubscriptionConductor::creatable() === true) {
|
||||
Subscription::create($request->all());
|
||||
dispatch((new SendEmailJob($request->email, new SubscriptionConfirm($request->email))))->onQueue('mail');
|
||||
|
||||
return $this->respondCreated();
|
||||
} else {
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\SubscriptionRequest $request The subscription update request.
|
||||
* @param \App\Models\Subscription $subscription The specified subscription.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(SubscriptionRequest $request, Subscription $subscription)
|
||||
{
|
||||
// if (EventConductor::updatable($event) === true) {
|
||||
// $event->update($request->all());
|
||||
// return $this->respondAsResource(EventConductor::model($request, $event));
|
||||
// }
|
||||
|
||||
// return $this->respondForbidden();
|
||||
|
||||
|
||||
// $input = [];
|
||||
// $updatable = ['username', 'first_name', 'last_name', 'email', 'phone', 'password'];
|
||||
|
||||
// if ($request->user()->hasPermission('admin/user') === true) {
|
||||
// $updatable = array_merge($updatable, ['email_verified_at']);
|
||||
// } elseif ($request->user()->is($user) !== true) {
|
||||
// return $this->respondForbidden();
|
||||
// }
|
||||
|
||||
// $input = $request->only($updatable);
|
||||
// if (array_key_exists('password', $input) === true) {
|
||||
// $input['password'] = Hash::make($request->input('password'));
|
||||
// }
|
||||
|
||||
// $user->update($input);
|
||||
|
||||
// return $this->respondAsResource((new UserFilter($request))->filter($user));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the user from the database.
|
||||
*
|
||||
* @param Subscription $subscription The specified subscription.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(Subscription $subscription)
|
||||
{
|
||||
if (SubscriptionConductor::destroyable($subscription) === true) {
|
||||
$subscription->delete();
|
||||
return $this->respondNoContent();
|
||||
} else {
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the user from the database.
|
||||
*
|
||||
* @param SubscriptionRequest $request The specified subscription.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroyByEmail(SubscriptionRequest $request)
|
||||
{
|
||||
$subscription = Subscription::where('email', $request->email)->first();
|
||||
if ($subscription !== null) {
|
||||
$subscription->delete();
|
||||
dispatch((new SendEmailJob($request->email, new SubscriptionUnsubscribed($request->email))))->onQueue('mail');
|
||||
}
|
||||
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
}
|
||||
@@ -1,342 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Enum\HttpResponseCodes;
|
||||
use App\Http\Requests\UserRequest;
|
||||
use App\Http\Requests\UserForgotPasswordRequest;
|
||||
use App\Http\Requests\UserForgotUsernameRequest;
|
||||
use App\Http\Requests\UserRegisterRequest;
|
||||
use App\Http\Requests\UserResendVerifyEmailRequest;
|
||||
use App\Http\Requests\UserResetPasswordRequest;
|
||||
use App\Http\Requests\UserVerifyEmailRequest;
|
||||
use App\Jobs\SendEmailJob;
|
||||
use App\Mail\ChangedEmail;
|
||||
use App\Mail\ChangedPassword;
|
||||
use App\Mail\ChangeEmailVerify;
|
||||
use App\Mail\ForgotUsername;
|
||||
use App\Mail\ForgotPassword;
|
||||
use App\Mail\EmailVerify;
|
||||
use App\Models\User;
|
||||
use App\Models\UserCode;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use App\Conductors\UserConductor;
|
||||
|
||||
class UserController extends ApiController
|
||||
{
|
||||
/**
|
||||
* ApplicationController constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('auth:sanctum')
|
||||
->except([
|
||||
'index',
|
||||
'show',
|
||||
'register',
|
||||
'exists',
|
||||
'forgotPassword',
|
||||
'forgotUsername',
|
||||
'resetPassword',
|
||||
'verifyEmail',
|
||||
'resendVerifyEmailCode'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
list($collection, $total) = UserConductor::request($request);
|
||||
|
||||
return $this->respondAsResource(
|
||||
$collection,
|
||||
['isCollection' => true,
|
||||
'appendData' => ['total' => $total]]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a newly created user in the database.
|
||||
*
|
||||
* @param \App\Http\Requests\UserRequest $request The endpoint request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(UserRequest $request)
|
||||
{
|
||||
if (UserConductor::creatable() === true) {
|
||||
$user = User::create($request->all());
|
||||
return $this->respondAsResource(UserConductor::model($request, $user), ['respondCode' => HttpResponseCodes::HTTP_CREATED]);
|
||||
} else {
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified user.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The endpoint request.
|
||||
* @param \App\Models\User $user The user model.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show(Request $request, User $user)
|
||||
{
|
||||
if (UserConductor::viewable($user) === true) {
|
||||
return $this->respondAsResource(UserConductor::model($request, $user));
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\UserRequest $request The user update request.
|
||||
* @param \App\Models\User $user The specified user.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(UserRequest $request, User $user)
|
||||
{
|
||||
if (UserConductor::updatable($user) === true) {
|
||||
$input = [];
|
||||
$updatable = ['username', 'first_name', 'last_name', 'email', 'phone', 'password'];
|
||||
|
||||
if ($request->user()->hasPermission('admin/user') === true) {
|
||||
$updatable = array_merge($updatable, ['email_verified_at']);
|
||||
}
|
||||
|
||||
$input = $request->only($updatable);
|
||||
if (array_key_exists('password', $input) === true) {
|
||||
$input['password'] = Hash::make($request->input('password'));
|
||||
}
|
||||
|
||||
$user->update($input);
|
||||
|
||||
return $this->respondAsResource(UserConductor::model($request, $user));
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the user from the database.
|
||||
*
|
||||
* @param \App\Models\User $user The specified user.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy(User $user)
|
||||
{
|
||||
if (UserConductor::destroyable($user) === true) {
|
||||
$user->delete();
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
|
||||
return $this->respondForbidden();
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new user
|
||||
*
|
||||
* @param \App\Http\Requests\UserRegisterRequest $request The register user request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function register(UserRegisterRequest $request)
|
||||
{
|
||||
try {
|
||||
$user = User::create([
|
||||
'first_name' => $request->input('first_name'),
|
||||
'last_name' => $request->input('last_name'),
|
||||
'username' => $request->input('username'),
|
||||
'email' => $request->input('email'),
|
||||
'phone' => $request->input('phone'),
|
||||
'password' => Hash::make($request->input('password'))
|
||||
]);
|
||||
|
||||
$code = $user->codes()->create([
|
||||
'action' => 'verify-email',
|
||||
]);
|
||||
|
||||
dispatch((new SendEmailJob($user->email, new EmailVerify($user, $code->code))))->onQueue('mail');
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Check your email for a welcome code.'
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return response()->json([
|
||||
'message' => 'A server error occurred. Please try again later' . $e
|
||||
], 500);
|
||||
}//end try
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email with all the usernames registered at that address
|
||||
*
|
||||
* @param \App\Http\Requests\UserForgotUsernameRequest $request The forgot username request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function forgotUsername(UserForgotUsernameRequest $request)
|
||||
{
|
||||
$users = User::where('email', $request->input('email'))->whereNotNull('email_verified_at')->get();
|
||||
if ($users->count() > 0) {
|
||||
dispatch((new SendEmailJob(
|
||||
$users->first()->email,
|
||||
new ForgotUsername($users->pluck('username')->toArray())
|
||||
)))->onQueue('mail');
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
|
||||
return $this->respondJson(['message' => 'Username send to the email address if registered']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new reset password code
|
||||
*
|
||||
* @param \App\Http\Requests\UserForgotPasswordRequest $request The reset password request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function forgotPassword(UserForgotPasswordRequest $request)
|
||||
{
|
||||
$user = User::where('username', $request->input('username'))->first();
|
||||
if ($user !== null) {
|
||||
$user->codes()->where('action', 'reset-password')->delete();
|
||||
$code = $user->codes()->create([
|
||||
'action' => 'reset-password'
|
||||
]);
|
||||
|
||||
dispatch((new SendEmailJob($user->email, new ForgotPassword($user, $code->code))))->onQueue('mail');
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
|
||||
return $this->respondNotFound();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets a user password
|
||||
*
|
||||
* @param \App\Http\Requests\UserResetPasswordRequest $request The reset password request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function resetPassword(UserResetPasswordRequest $request)
|
||||
{
|
||||
UserCode::clearExpired();
|
||||
|
||||
$code = UserCode::where('code', $request->input('code'))->where('action', 'reset-password')->first();
|
||||
if ($code !== null) {
|
||||
$user = $code->user()->first();
|
||||
|
||||
$code->delete();
|
||||
$user->codes()->where('action', 'verify-email')->delete();
|
||||
|
||||
$user->password = Hash::make($request->input('password'));
|
||||
|
||||
if ($user->email_verified_at === null) {
|
||||
$user->email_verified_at = now();
|
||||
}
|
||||
|
||||
$user->save();
|
||||
|
||||
dispatch((new SendEmailJob($user->email, new ChangedPassword($user))))->onQueue('mail');
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
|
||||
return $this->respondError([
|
||||
'code' => 'The code was not found or has expired.'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify an email code
|
||||
*
|
||||
* @param \App\Http\Requests\UserVerifyEmailRequest $request The verify email request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function verifyEmail(UserVerifyEmailRequest $request)
|
||||
{
|
||||
UserCode::clearExpired();
|
||||
|
||||
$code = UserCode::where('code', $request->input('code'))->where('action', 'verify-email')->first();
|
||||
if ($code !== null) {
|
||||
$user = $code->user()->first();
|
||||
$new_email = $code->data;
|
||||
|
||||
if ($new_email === null) {
|
||||
if ($user->email_verified_at === null) {
|
||||
$user->email_verified_at = now();
|
||||
}
|
||||
} else {
|
||||
dispatch((new SendEmailJob($user->email, new ChangedEmail($user, $user->email, $new_email))))
|
||||
->onQueue('mail');
|
||||
|
||||
$user->email = $new_email;
|
||||
$user->email_verified_at = now();
|
||||
}
|
||||
|
||||
$code->delete();
|
||||
$user->save();
|
||||
|
||||
return $this->respondNoContent();
|
||||
}//end if
|
||||
|
||||
return $this->respondWithErrors([
|
||||
'code' => 'The code was not found or has expired.'
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resend a new verify email
|
||||
*
|
||||
* @param \App\Http\Requests\UserResendVerifyEmailRequest $request The resend verify email request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function resendVerifyEmail(UserResendVerifyEmailRequest $request)
|
||||
{
|
||||
UserCode::clearExpired();
|
||||
|
||||
$user = User::where('username', $request->input('username'))->first();
|
||||
if ($user !== null) {
|
||||
$code = $user->codes()->where('action', 'verify-email')->first();
|
||||
$code->regenerate();
|
||||
$code->save();
|
||||
|
||||
if ($code->data === null) {
|
||||
dispatch((new SendEmailJob($user->email, new EmailVerify($user, $code->code))))->onQueue('mail');
|
||||
} else {
|
||||
dispatch((new SendEmailJob($user->email, new ChangeEmailVerify($user, $code->code, $code->data))))
|
||||
->onQueue('mail');
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(['message' => 'Verify email sent if user registered and required']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resend verification email
|
||||
*
|
||||
* @param \App\Http\Requests\UserResendVerifyEmailRequest $request The resend user request.
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function resendVerifyEmailCode(UserResendVerifyEmailRequest $request)
|
||||
{
|
||||
$user = User::where('username', $request->input('username'))->first();
|
||||
if ($user !== null) {
|
||||
$user->codes()->where('action', 'verify-email')->delete();
|
||||
|
||||
if ($user->email_verified_at === null) {
|
||||
$code = $user->codes()->create([
|
||||
'action' => 'verify-email'
|
||||
]);
|
||||
|
||||
dispatch((new SendEmailJob($user->email, new EmailVerify($user, $code->code))))->onQueue('mail');
|
||||
}
|
||||
|
||||
return $this->respondNoContent();
|
||||
}
|
||||
|
||||
return $this->respondNotFound();
|
||||
}
|
||||
}
|
||||
@@ -3,13 +3,10 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
use Illuminate\Foundation\Validation\ValidatesRequests;
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
|
||||
class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests;
|
||||
use DispatchesJobs;
|
||||
use ValidatesRequests;
|
||||
use AuthorizesRequests, ValidatesRequests;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ class Kernel extends HttpKernel
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
|
||||
// \App\Http\Middleware\TrimStrings::class,
|
||||
// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -40,22 +40,19 @@ class Kernel extends HttpKernel
|
||||
|
||||
'api' => [
|
||||
// \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
|
||||
'throttle:api',
|
||||
\Illuminate\Routing\Middleware\ThrottleRequests::class.':api',
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
// \App\Http\Middleware\ForceJsonResponse::class,
|
||||
'useSanctumGuard',
|
||||
\App\Http\Middleware\LogRequest::class,
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* The application's route middleware.
|
||||
* The application's middleware aliases.
|
||||
*
|
||||
* These middleware may be assigned to groups or used individually.
|
||||
* Aliases may be used instead of class names to conveniently assign middleware to routes and groups.
|
||||
*
|
||||
* @var array<string, class-string|string>
|
||||
*/
|
||||
protected $routeMiddleware = [
|
||||
protected $middlewareAliases = [
|
||||
'auth' => \App\Http\Middleware\Authenticate::class,
|
||||
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
|
||||
'auth.session' => \Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
@@ -63,9 +60,9 @@ class Kernel extends HttpKernel
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class,
|
||||
'precognitive' => \Illuminate\Foundation\Http\Middleware\HandlePrecognitiveRequests::class,
|
||||
'signed' => \App\Http\Middleware\ValidateSignature::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
|
||||
'useSanctumGuard' => \App\Http\Middleware\UseSanctumGuard::class
|
||||
];
|
||||
}
|
||||
|
||||
@@ -3,19 +3,15 @@
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Illuminate\Auth\Middleware\Authenticate as Middleware;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class Authenticate extends Middleware
|
||||
{
|
||||
/**
|
||||
* Get the path the user should be redirected to when they are not authenticated.
|
||||
*
|
||||
* @param mixed $request Request.
|
||||
* @return string|null
|
||||
*/
|
||||
protected function redirectTo(mixed $request)
|
||||
protected function redirectTo(Request $request): ?string
|
||||
{
|
||||
if ($request->expectsJson() === false) {
|
||||
return route('login');
|
||||
}
|
||||
return $request->expectsJson() ? null : route('login');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
class ForceJsonResponse
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
$request->headers->set('Accept', 'application/json');
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Analytics;
|
||||
|
||||
class LogRequest
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
// Make it an after middleware
|
||||
$response = $next($request);
|
||||
|
||||
try {
|
||||
Analytics::create([
|
||||
'type' => 'pageview',
|
||||
'attribute' => $request->path(),
|
||||
'useragent' => $request->userAgent(),
|
||||
'ip' => $request->ip(),
|
||||
]);
|
||||
|
||||
return $response;
|
||||
} catch (\Error $e) {
|
||||
report($e);
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,23 +6,21 @@ use App\Providers\RouteServiceProvider;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class RedirectIfAuthenticated
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param Request $request Request.
|
||||
* @param Closure(Request): (Response|RedirectResponse) $next Next.
|
||||
* @param string|null ...$guards Guards.
|
||||
* @return Response|RedirectResponse
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
|
||||
*/
|
||||
public function handle(Request $request, Closure $next, ...$guards)
|
||||
public function handle(Request $request, Closure $next, string ...$guards): Response
|
||||
{
|
||||
$guards = empty($guards) === true ? [null] : $guards;
|
||||
$guards = empty($guards) ? [null] : $guards;
|
||||
|
||||
foreach ($guards as $guard) {
|
||||
if (Auth::guard($guard)->check() === true) {
|
||||
if (Auth::guard($guard)->check()) {
|
||||
return redirect(RouteServiceProvider::HOME);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class TrustHosts extends Middleware
|
||||
*
|
||||
* @return array<int, string|null>
|
||||
*/
|
||||
public function hosts()
|
||||
public function hosts(): array
|
||||
{
|
||||
return [
|
||||
$this->allSubdomainsOfApplicationUrl(),
|
||||
|
||||
@@ -17,9 +17,12 @@ class TrustProxies extends Middleware
|
||||
/**
|
||||
* The headers that should be used to detect proxies.
|
||||
*
|
||||
* @var integer
|
||||
* @var int
|
||||
*/
|
||||
// @codingStandardsIgnoreStart
|
||||
protected $headers = (Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB);
|
||||
// @codingStandardsIgnoreEnd
|
||||
protected $headers =
|
||||
Request::HEADER_X_FORWARDED_FOR |
|
||||
Request::HEADER_X_FORWARDED_HOST |
|
||||
Request::HEADER_X_FORWARDED_PORT |
|
||||
Request::HEADER_X_FORWARDED_PROTO |
|
||||
Request::HEADER_X_FORWARDED_AWS_ELB;
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class UseSanctumGuard
|
||||
{
|
||||
/**
|
||||
* Handle an incoming request.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Closure(\Illuminate\Http\Request): (\Illuminate\Http\Response|\Illuminate\Http\RedirectResponse) $next
|
||||
* @return \Illuminate\Http\Response|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
Auth::shouldUse('sanctum');
|
||||
return $next($request);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class AuthLoginRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'username' => 'required|string|min:6|max:255',
|
||||
'password' => 'required|string|min:6',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class BaseRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
if (request()->isMethod('post') === true && method_exists($this, 'postAuthorize') === true) {
|
||||
return $this->postAuthorize();
|
||||
} elseif ((request()->isMethod('put') === true || request()->isMethod('patch') === true) && method_exists($this, 'putAuthorize') === true) {
|
||||
return $this->putAuthorize();
|
||||
} elseif (request()->isMethod('delete') === true && method_exists($this, 'destroyAuthorize') === true) {
|
||||
return $this->deleteAuthorize();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
if (method_exists($this, 'baseRules') === true) {
|
||||
$rules = $this->baseRules();
|
||||
}
|
||||
|
||||
if (method_exists($this, 'postRules') === true && request()->isMethod('post') === true) {
|
||||
$rules = $this->mergeRules($rules, $this->postRules());
|
||||
} elseif (method_exists($this, 'putRules') === true && (request()->isMethod('put') === true || request()->isMethod('patch') === true)) {
|
||||
$rules = $this->mergeRules($rules, $this->putRules());
|
||||
} elseif (method_exists($this, 'destroyRules') === true && request()->isMethod('delete') === true) {
|
||||
$rules = $this->mergeRules($rules, $this->destroyRules());
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two collections of rules.
|
||||
*
|
||||
* @param array $collection1 The first collection of rules.
|
||||
* @param array $collection2 The second collection of rules to merge.
|
||||
* @return array
|
||||
*/
|
||||
private function mergeRules(array $collection1, array $collection2)
|
||||
{
|
||||
$rules = [];
|
||||
|
||||
foreach ($collection1 as $key => $ruleset) {
|
||||
if (array_key_exists($key, $collection2) === true) {
|
||||
if (is_string($collection1[$key]) === true && is_string($collection2[$key]) === true) {
|
||||
$rules[$key] = $collection1[$key] . '|' . $collection2[$key];
|
||||
} else {
|
||||
$key_ruleset = [];
|
||||
|
||||
if (is_array($collection1[$key]) === true) {
|
||||
$key_ruleset = $collection1[$key];
|
||||
} elseif (is_string($collection1[$key]) === true) {
|
||||
$key_ruleset = explode('|', $collection1[$key]);
|
||||
}
|
||||
|
||||
if (is_array($collection2[$key]) === true) {
|
||||
$key_ruleset = array_merge($key_ruleset, $collection2[$key]);
|
||||
} elseif (is_string($collection2[$key]) === true) {
|
||||
$key_ruleset = array_merge($key_ruleset, explode('|', $collection2[$key]));
|
||||
}
|
||||
|
||||
if (count($key_ruleset) > 0) {
|
||||
$rules[$key] = $key_ruleset;
|
||||
}
|
||||
}//end if
|
||||
} else {
|
||||
$rules[$key] = $ruleset;
|
||||
}//end if
|
||||
}//end foreach
|
||||
|
||||
foreach ($collection2 as $key => $ruleset) {
|
||||
if (array_key_exists($key, $rules) === false) {
|
||||
$rules[$key] = $collection2[$key];
|
||||
}
|
||||
}
|
||||
|
||||
return $rules;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Rules\Recaptcha;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class ContactSendRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'name' => 'required|max:255',
|
||||
'email' => 'required|email|max:255',
|
||||
'content' => 'required|max:2000',
|
||||
'captcha_token' => [new Recaptcha()],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class EventRequest extends BaseRequest
|
||||
{
|
||||
/**
|
||||
* Apply the base rules to this request
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function baseRules()
|
||||
{
|
||||
return [
|
||||
'title' => 'min:6',
|
||||
'location' => [
|
||||
Rule::in(['online', 'physical']),
|
||||
],
|
||||
'address' => 'string|nullable',
|
||||
'start_at' => 'date',
|
||||
'end_at' => 'date|after:start_date',
|
||||
'publish_at' => 'date|nullable',
|
||||
'status' => [
|
||||
Rule::in(['draft', 'soon', 'open', 'closed', 'cancelled']),
|
||||
],
|
||||
'registration_type' => [
|
||||
Rule::in(['none', 'email', 'link', 'message']),
|
||||
],
|
||||
'registration_data' => [
|
||||
Rule::when(strcasecmp('email', $this->attributes->get('registration_type')) == 0, 'required|email'),
|
||||
Rule::when(strcasecmp('link', $this->attributes->get('registration_type')) == 0, 'required|url'),
|
||||
Rule::when(strcasecmp('message', $this->attributes->get('registration_type')) == 0, 'required|message'),
|
||||
],
|
||||
'hero' => 'uuid|exists:media,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the additional POST base rules to this request
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function postRules()
|
||||
{
|
||||
return [
|
||||
'title' => 'required',
|
||||
'location' => 'required',
|
||||
'address' => 'required_if:location,physical',
|
||||
'start_at' => 'required',
|
||||
'end_at' => 'required',
|
||||
'status' => 'required',
|
||||
'registration_type' => 'required',
|
||||
'hero' => 'required',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
class MediaRequest extends BaseRequest
|
||||
{
|
||||
/* empty */
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class PostRequest extends BaseRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to POST requests.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function postRules()
|
||||
{
|
||||
return [
|
||||
'slug' => 'required|string|min:6|unique:posts',
|
||||
'title' => 'required|string|min:6|max:255',
|
||||
'publish_at' => 'required|date',
|
||||
'user_id' => 'required|uuid|exists:users,id',
|
||||
'content' => 'required|string|min:6',
|
||||
'hero' => 'required|uuid|exists:media,id',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to PUT request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function putRules()
|
||||
{
|
||||
return [
|
||||
'slug' => [
|
||||
'string',
|
||||
'min:6',
|
||||
Rule::unique('posts')->ignoreModel($this->post),
|
||||
],
|
||||
'title' => 'string|min:6|max:255',
|
||||
'publish_at' => 'date',
|
||||
'user_id' => 'uuid|exists:users,id',
|
||||
'content' => 'string|min:6',
|
||||
'hero' => 'uuid|exists:media,id',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Rules\Recaptcha;
|
||||
|
||||
class SubscriptionRequest extends BaseRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function postRules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email|unique:subscriptions',
|
||||
'captcha_token' => [new Recaptcha()],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function destroyRules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email',
|
||||
'captcha_token' => [new Recaptcha()],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the custom error messages.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function messages()
|
||||
{
|
||||
return [
|
||||
'email.unique' => 'This email address has already subscribed',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Rules\Recaptcha;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UserForgotPasswordRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'username' => 'required|exists:users,username',
|
||||
'captcha_token' => [new Recaptcha()],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Rules\Recaptcha;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UserForgotUsernameRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'email' => 'required|email|max:255',
|
||||
'captcha_token' => [new Recaptcha()],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UserRegisterRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'first_name' => 'required|string|max:255',
|
||||
'last_name' => 'required|string|max:255',
|
||||
'email' => 'required|string|email|max:255',
|
||||
'username' => 'required|string|min:4|max:255|unique:users',
|
||||
'password' => 'required|string|min:8',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class UserRequest extends BaseRequest
|
||||
{
|
||||
/**
|
||||
* Apply the additional POST base rules to this request
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function postRules()
|
||||
{
|
||||
return [
|
||||
'username' => 'required|string|max:255|min:4|unique:users',
|
||||
'first_name' => 'required|string|max:255|min:2',
|
||||
'last_name' => 'required|string|max:255|min:2',
|
||||
'email' => 'required|string|email|max:255',
|
||||
'phone' => ['string', 'regex:/^(\+|00)?[0-9][0-9 \-\(\)\.]{7,32}$/'],
|
||||
'email_verified_at' => 'date'
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to PUT request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function putRules()
|
||||
{
|
||||
$user = $this->route('user');
|
||||
|
||||
return [
|
||||
'username' => [
|
||||
'string',
|
||||
'max:255',
|
||||
'min:4',
|
||||
Rule::unique('users')->ignore($user->id)->when(
|
||||
$this->username !== $user->username,
|
||||
function ($query) {
|
||||
return $query->where('username', $this->username);
|
||||
}
|
||||
),
|
||||
],
|
||||
'first_name' => 'string|max:255|min:2',
|
||||
'last_name' => 'string|max:255|min:2',
|
||||
'email' => 'string|email|max:255',
|
||||
'phone' => ['nullable','regex:/^(\+|00)?[0-9][0-9 \-\(\)\.]{7,32}$/'],
|
||||
'password' => 'string|min:8'
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Rules\Recaptcha;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UserResendVerifyEmailRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'username' => 'required|exists:users,username',
|
||||
'captcha_token' => [new Recaptcha()],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Rules\Recaptcha;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UserResetPasswordRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'code' => 'required|digits:6',
|
||||
'password' => 'required|string|min:8',
|
||||
'captcha_token' => [new Recaptcha()],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Rules\Recaptcha;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class UserVerifyEmailRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'code' => 'required|digits:6',
|
||||
'captcha_token' => [new Recaptcha()],
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class SendEmailJob implements ShouldQueue
|
||||
{
|
||||
use Dispatchable;
|
||||
use InteractsWithQueue;
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* Mail to receipt
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $to;
|
||||
|
||||
/**
|
||||
* Mailable item
|
||||
*
|
||||
* @var Mailable
|
||||
*/
|
||||
public $mailable;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new job instance.
|
||||
*
|
||||
* @param string $to The email receipient.
|
||||
* @param Mailable $mailable The mailable.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $to, Mailable $mailable)
|
||||
{
|
||||
$this->to = $to;
|
||||
$this->mailable = $mailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the job.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
Mail::to($this->to)->send($this->mailable);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ChangeEmailVerify extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The user instance.
|
||||
*
|
||||
* @var \App\Models\User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The registration code.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $code;
|
||||
|
||||
/**
|
||||
* The new email address.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $new_email;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param User $user The user the email applies to.
|
||||
* @param integer $code The action code.
|
||||
* @param string $new_email The new email address.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user, int $code, string $new_email)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->code = $code;
|
||||
$this->new_email = $new_email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: '👋🏻 Lets change your email!',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.change_email_verify',
|
||||
text: 'emails.user.change_email_verify_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ChangedEmail extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The user instance.
|
||||
*
|
||||
* @var \App\Models\User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The old email.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $old_email;
|
||||
|
||||
/**
|
||||
* The new email.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $new_email;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param User $user The user the email applies to.
|
||||
* @param string $old_email The previous email address.
|
||||
* @param string $new_email The new email address.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user, string $old_email, string $new_email)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->old_email = $old_email;
|
||||
$this->new_email = $new_email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: '👍 Your email has been changed!',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.changed_email',
|
||||
text: 'emails.user.changed_email_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ChangedPassword extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The user instance.
|
||||
*
|
||||
* @var \App\Models\User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param User $user The user the email applies to.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: '👍 Your password has been changed!',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.changed_password',
|
||||
text: 'emails.user.changed_password_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class Contact extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The contact name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The contact email.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $email;
|
||||
|
||||
/**
|
||||
* The contact content.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $content;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param string $name The contact name.
|
||||
* @param string $email The contact email.
|
||||
* @param string $content The contact content.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $name, string $email, string $content)
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->email = $email;
|
||||
$this->content = $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: config('contact.contact_subject'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.contact',
|
||||
text: 'emails.user.contact_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class EmailVerify extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The user instance.
|
||||
*
|
||||
* @var \App\Models\User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The registration code.
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $code;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param User $user The user the email applies to.
|
||||
* @param integer $code The action code.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user, int $code)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: '👋🏻 Welcome to STEMMechanics!',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.email_verify',
|
||||
text: 'emails.user.email_verify_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ForgotPassword extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The user
|
||||
*
|
||||
* @var \App\Models\User
|
||||
*/
|
||||
public $user;
|
||||
|
||||
/**
|
||||
* The reset code
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
public $code;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param User $user The user the email applies to.
|
||||
* @param integer $code The action code.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $user, int $code)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: '🤦 Forgot your password?',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.forgot_password',
|
||||
text: 'emails.user.forgot_password_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ForgotUsername extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The list of usernames
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
public $usernames;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param array $usernames The usernames.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(array $usernames)
|
||||
{
|
||||
$this->usernames = $usernames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: '🤦 Forgot your username?',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.forgot_username',
|
||||
text: 'emails.user.forgot_username_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SubscriptionConfirm extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The email address.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $email;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param string $email The email address.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $email)
|
||||
{
|
||||
$this->email = $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: '🗞️ You\'re on the mailing list!',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.subscription_confirm',
|
||||
text: 'emails.user.subscription_confirm_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SubscriptionUnsubscribed extends Mailable
|
||||
{
|
||||
use Queueable;
|
||||
use SerializesModels;
|
||||
|
||||
/**
|
||||
* The email address.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $email;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*
|
||||
* @param string $email The email address.
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(string $email)
|
||||
{
|
||||
$this->email = $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Envelope
|
||||
*/
|
||||
public function envelope()
|
||||
{
|
||||
return new Envelope(
|
||||
subject: 'You have been unsubscribed',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*
|
||||
* @return \Illuminate\Mail\Mailables\Content
|
||||
*/
|
||||
public function content()
|
||||
{
|
||||
return new Content(
|
||||
view: 'emails.user.subscription_unsubscribed',
|
||||
text: 'emails.user.subscription_unsubscribed_plain',
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Analytics extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $guarded = [];
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Attachment extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'media_id',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Get attachments attachable
|
||||
*/
|
||||
public function attachable()
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the media for this attachment.
|
||||
*/
|
||||
public function media()
|
||||
{
|
||||
return $this->belongsTo(Media::class);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Uuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Event extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Uuids;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'location',
|
||||
'address',
|
||||
'start_at',
|
||||
'end_at',
|
||||
'publish_at',
|
||||
'status',
|
||||
'registration_type',
|
||||
'registration_data',
|
||||
'hero',
|
||||
'content',
|
||||
'price',
|
||||
'ages',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Get all of the post's attachments.
|
||||
*/
|
||||
public function attachments()
|
||||
{
|
||||
return $this->morphMany('App\Models\Attachment', 'attachable');
|
||||
}
|
||||
}
|
||||
@@ -1,306 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Uuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Intervention\Image\Facades\Image;
|
||||
use Spatie\ImageOptimizer\OptimizerChainFactory;
|
||||
|
||||
class Media extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Uuids;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'name',
|
||||
'mime',
|
||||
'user_id',
|
||||
'size',
|
||||
'permission'
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that are hidden.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $hidden = [
|
||||
'path',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that are appended.
|
||||
*
|
||||
* @var array<string>
|
||||
*/
|
||||
protected $appends = [
|
||||
'url',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Model Boot
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::updating(function ($media) {
|
||||
if (array_key_exists('permission', $media->getChanges()) === true) {
|
||||
$origPermission = $media->getOriginal()['permission'];
|
||||
$newPermission = $media->permission;
|
||||
|
||||
$origPath = Storage::disk(Media::getStorageId(empty($origPermission)))->path($media->name);
|
||||
$newPath = Storage::disk(Media::getStorageId(empty($newPermission)))->path($media->name);
|
||||
|
||||
if ($origPath !== $newPath) {
|
||||
if (file_exists($origPath) === true) {
|
||||
if (file_exists($newPath) === true) {
|
||||
$fileParts = pathinfo($newPath);
|
||||
$newName = '';
|
||||
|
||||
// need a new name!
|
||||
$tmpPath = $newPath;
|
||||
while (file_exists($tmpPath) === true) {
|
||||
$newName = uniqid('', true) . $fileParts['extension'];
|
||||
$tmpPath = $fileParts['dirname'] . '/' . $newName;
|
||||
}
|
||||
|
||||
$media->name = $newName;
|
||||
}
|
||||
|
||||
rename($origPath, $newPath);
|
||||
}//end if
|
||||
}//end if
|
||||
}//end if
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the file URL
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrlAttribute()
|
||||
{
|
||||
$url = config('filesystems.disks.' . Media::getStorageId($this) . '.url');
|
||||
if (empty($url) === false) {
|
||||
$replace = [
|
||||
'id' => $this->id,
|
||||
'name' => $this->name
|
||||
];
|
||||
|
||||
$url = str_ireplace(array_map(function ($item) {
|
||||
return '%' . $item . '%';
|
||||
}, array_keys($replace)), array_values($replace), $url);
|
||||
|
||||
return $url;
|
||||
}//end if
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the file owner
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file full local path
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function path()
|
||||
{
|
||||
return Storage::disk(Media::getStorageId($this))->path($this->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Storage ID
|
||||
*
|
||||
* @param mixed $mediaOrPublic Media object or if file is public.
|
||||
* @return string
|
||||
*/
|
||||
public static function getStorageId(mixed $mediaOrPublic)
|
||||
{
|
||||
$isPublic = true;
|
||||
|
||||
if ($mediaOrPublic instanceof Media) {
|
||||
$isPublic = empty($mediaOrPublic->permission);
|
||||
} else {
|
||||
$isPublic = boolval($mediaOrPublic);
|
||||
}
|
||||
|
||||
return $isPublic === true ? 'public' : 'local';
|
||||
}
|
||||
|
||||
/**
|
||||
* Place uploaded file into storage. Return full path or null
|
||||
*
|
||||
* @param UploadedFile $file File to put into storage.
|
||||
* @param boolean $public Is the file available to the public.
|
||||
* @return array|null
|
||||
*/
|
||||
public static function store(UploadedFile $file, bool $public = true)
|
||||
{
|
||||
$storage = Media::getStorageId($public);
|
||||
$name = $file->store('', ['disk' => $storage]);
|
||||
|
||||
if ($name === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$path = Storage::disk($storage)->path($name);
|
||||
if (in_array($file->getClientOriginalExtension(), ['jpg', 'jpeg', 'png', 'gif']) === true) {
|
||||
// Generate additional image sizes
|
||||
$sizes = [
|
||||
'thumb' => [150, 150],
|
||||
'small' => [300, 300],
|
||||
'medium' => [640, 640],
|
||||
'large' => [1024, 1024],
|
||||
'xlarge' => [1536, 1536],
|
||||
'xxlarge' => [2560, 2560],
|
||||
];
|
||||
$images = ['full' => $path];
|
||||
foreach ($sizes as $sizeName => $size) {
|
||||
$image = Image::make($path);
|
||||
$image->resize($size[0], $size[1], function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
});
|
||||
$newPath = pathinfo($path, PATHINFO_DIRNAME) . '/' . pathinfo($path, PATHINFO_FILENAME) . "-$sizeName." . pathinfo($path, PATHINFO_EXTENSION);
|
||||
$image->save($newPath);
|
||||
$images[$sizeName] = $newPath;
|
||||
}
|
||||
|
||||
// Optimize all images
|
||||
$optimizerChain = OptimizerChainFactory::create();
|
||||
foreach ($images as $imagePath) {
|
||||
$optimizerChain->optimize($imagePath);
|
||||
}
|
||||
}//end if
|
||||
|
||||
return [
|
||||
'name' => $name,
|
||||
'path' => $path
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the server maximum upload size
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public static function maxUploadSize()
|
||||
{
|
||||
$sizes = [
|
||||
ini_get('upload_max_filesize'),
|
||||
ini_get('post_max_size'),
|
||||
ini_get('memory_limit')
|
||||
];
|
||||
|
||||
foreach ($sizes as &$size) {
|
||||
$size = trim($size);
|
||||
$last = strtolower($size[(strlen($size) - 1)]);
|
||||
switch ($last) {
|
||||
case 'g':
|
||||
$size = (intval($size) * 1024);
|
||||
// Size is in MB - fallthrough
|
||||
case 'm':
|
||||
$size = (intval($size) * 1024);
|
||||
// Size is in KB - fallthrough
|
||||
case 'k':
|
||||
$size = (intval($size) * 1024);
|
||||
// Size is in B - fallthrough
|
||||
}
|
||||
}
|
||||
|
||||
return min($sizes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize filename for upload
|
||||
*
|
||||
* @param string $filename Filename to sanitize.
|
||||
* @return string
|
||||
*/
|
||||
public static function sanitizeFilename(string $filename)
|
||||
{
|
||||
/*
|
||||
# file system reserved https://en.wikipedia.org/wiki/Filename#Reserved_characters_and_words
|
||||
[<>:"/\\\|?*]|
|
||||
|
||||
# control characters http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx
|
||||
[\x00-\x1F]|
|
||||
|
||||
# non-printing characters DEL, NO-BREAK SPACE, SOFT HYPHEN
|
||||
[\x7F\xA0\xAD]|
|
||||
|
||||
# URI reserved https://www.rfc-editor.org/rfc/rfc3986#section-2.2
|
||||
[#\[\]@!$&\'()+,;=]|
|
||||
|
||||
# URL unsafe characters https://www.ietf.org/rfc/rfc1738.txt
|
||||
[{}^\~`]
|
||||
*/
|
||||
|
||||
$filename = preg_replace(
|
||||
'~
|
||||
[<>:"/\\\|?*]|
|
||||
[\x00-\x1F]|
|
||||
[\x7F\xA0\xAD]|
|
||||
[#\[\]@!$&\'()+,;=]|
|
||||
[{}^\~`]
|
||||
~x',
|
||||
'-',
|
||||
$filename
|
||||
);
|
||||
|
||||
$filename = ltrim($filename, '.-');
|
||||
|
||||
$filename = preg_replace([
|
||||
// "file name.zip" becomes "file-name.zip"
|
||||
'/ +/',
|
||||
// "file___name.zip" becomes "file-name.zip"
|
||||
'/_+/',
|
||||
// "file---name.zip" becomes "file-name.zip"
|
||||
'/-+/'
|
||||
], '-', $filename);
|
||||
$filename = preg_replace([
|
||||
// "file--.--.-.--name.zip" becomes "file.name.zip"
|
||||
'/-*\.-*/',
|
||||
// "file...name..zip" becomes "file.name.zip"
|
||||
'/\.{2,}/'
|
||||
], '.', $filename);
|
||||
// lowercase for windows/unix interoperability http://support.microsoft.com/kb/100625
|
||||
$filename = mb_strtolower($filename, mb_detect_encoding($filename));
|
||||
// ".file-name.-" becomes "file-name"
|
||||
$filename = trim($filename, '.-');
|
||||
|
||||
$ext = pathinfo($filename, PATHINFO_EXTENSION);
|
||||
$filename = mb_strcut(
|
||||
pathinfo($filename, PATHINFO_FILENAME),
|
||||
0,
|
||||
(255 - ($ext !== '' ? strlen($ext) + 1 : 0)),
|
||||
mb_detect_encoding($filename)
|
||||
) . ($ext !== '' ? '.' . $ext : '');
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Uuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Permission extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Uuids;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'permission',
|
||||
'user',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Get the User associated with this model
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Uuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Post extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Uuids;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'title',
|
||||
'slug',
|
||||
'publish_at',
|
||||
'content',
|
||||
'user_id',
|
||||
'hero'
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Get the post user
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the post's attachments.
|
||||
*/
|
||||
public function attachments()
|
||||
{
|
||||
return $this->morphMany('App\Models\Attachment', 'attachable');
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Uuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class Subscription extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Uuids;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'email',
|
||||
];
|
||||
}
|
||||
@@ -3,21 +3,14 @@
|
||||
namespace App\Models;
|
||||
|
||||
// use Illuminate\Contracts\Auth\MustVerifyEmail;
|
||||
|
||||
use App\Traits\Uuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
use Laravel\Sanctum\HasApiTokens;
|
||||
use OwenIt\Auditing\Contracts\Auditable;
|
||||
|
||||
class User extends Authenticatable implements Auditable
|
||||
class User extends Authenticatable
|
||||
{
|
||||
use HasApiTokens;
|
||||
use HasFactory;
|
||||
use Notifiable;
|
||||
use Uuids;
|
||||
use \OwenIt\Auditing\Auditable;
|
||||
use HasApiTokens, HasFactory, Notifiable;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@@ -25,11 +18,8 @@ class User extends Authenticatable implements Auditable
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'username',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'name',
|
||||
'email',
|
||||
'phone',
|
||||
'password',
|
||||
];
|
||||
|
||||
@@ -41,7 +31,6 @@ class User extends Authenticatable implements Auditable
|
||||
protected $hidden = [
|
||||
'password',
|
||||
'remember_token',
|
||||
'permissions'
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -51,137 +40,6 @@ class User extends Authenticatable implements Auditable
|
||||
*/
|
||||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
'password' => 'hashed',
|
||||
];
|
||||
|
||||
// protected $hidden = [
|
||||
// 'permissions'
|
||||
// ];
|
||||
|
||||
/**
|
||||
* The attributes to append.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $appends = [
|
||||
'permissions'
|
||||
];
|
||||
|
||||
|
||||
// public function getPermissionsAttribute() {
|
||||
// return $this->permissions()->pluck('permission')->toArray();
|
||||
// }
|
||||
|
||||
|
||||
/**
|
||||
* Get the list of files of the user
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function permissions()
|
||||
{
|
||||
return $this->hasMany(Permission::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the permission attribute
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPermissionsAttribute()
|
||||
{
|
||||
return $this->permissions()->pluck('permission')->toArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if user has permission
|
||||
*
|
||||
* @param string $permission Permission to test.
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasPermission(string $permission)
|
||||
{
|
||||
return ($this->permissions()->where('permission', $permission)->first() !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Give permissions to the user
|
||||
*
|
||||
* @param string|array $permissions The permission(s) to give.
|
||||
* @return Collection
|
||||
*/
|
||||
public function givePermission($permissions)
|
||||
{
|
||||
if (!is_array($permissions)) {
|
||||
$permissions = [$permissions];
|
||||
}
|
||||
|
||||
$permissions = collect($permissions)->map(function ($permission) {
|
||||
return ['permission' => $permission];
|
||||
});
|
||||
|
||||
$existingPermissions = $this->permissions()->whereIn('permission', $permissions->pluck('permission'))->get();
|
||||
$newPermissions = $permissions->reject(function ($permission) use ($existingPermissions) {
|
||||
return $existingPermissions->contains('permission', $permission['permission']);
|
||||
});
|
||||
|
||||
return $this->permissions()->createMany($newPermissions->toArray());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Revoke permissions from the user
|
||||
*
|
||||
* @param string|array $permissions The permission(s) to revoke.
|
||||
* @return int
|
||||
*/
|
||||
public function revokePermission($permissions)
|
||||
{
|
||||
if (!is_array($permissions)) {
|
||||
$permissions = [$permissions];
|
||||
}
|
||||
|
||||
return $this->permissions()
|
||||
->whereIn('permission', $permissions)
|
||||
->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of files of the user
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function media()
|
||||
{
|
||||
return $this->hasMany(Media::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of files of the user
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function posts()
|
||||
{
|
||||
return $this->hasMany(Post::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get associated user codes
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function codes()
|
||||
{
|
||||
return $this->hasMany(UserCode::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of logins of the user
|
||||
*
|
||||
* @return HasMany
|
||||
*/
|
||||
public function logins()
|
||||
{
|
||||
return $this->hasMany(UserLogins::class);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UserCode extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'action',
|
||||
'user_id',
|
||||
'data',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Boot function from Laravel.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function boot()
|
||||
{
|
||||
parent::boot();
|
||||
static::creating(function ($model) {
|
||||
UserCode::clearExpired();
|
||||
|
||||
if (empty($model->{'code'}) === true) {
|
||||
while (true) {
|
||||
$code = random_int(100000, 999999);
|
||||
if (UserCode::where('code', $code)->count() === 0) {
|
||||
$model->{'code'} = $code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate new code
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function regenerate()
|
||||
{
|
||||
while (true) {
|
||||
$code = random_int(100000, 999999);
|
||||
if (UserCode::where('code', $code)->count() === 0) {
|
||||
$this->code = $code;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear expired user codes
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function clearExpired()
|
||||
{
|
||||
UserCode::where('updated_at', '<=', now()->subDays(5))->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get associated user
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Uuids;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class UserLogins extends Model
|
||||
{
|
||||
use HasFactory;
|
||||
use Uuids;
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
*
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $fillable = [
|
||||
'user_id',
|
||||
'token',
|
||||
'login',
|
||||
'logout',
|
||||
'ip_address',
|
||||
'user_agent',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Get the file user
|
||||
*
|
||||
* @return BelongsTo
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
}
|
||||
@@ -3,28 +3,21 @@
|
||||
namespace App\Providers;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use PDOException;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Register any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
public function boot(): void
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
@@ -13,19 +13,14 @@ class AuthServiceProvider extends ServiceProvider
|
||||
* @var array<class-string, class-string>
|
||||
*/
|
||||
protected $policies = [
|
||||
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
|
||||
//
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Register any authentication / authorization services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
public function boot(): void
|
||||
{
|
||||
$this->registerPolicies();
|
||||
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,8 @@ class BroadcastServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap any application services.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
public function boot(): void
|
||||
{
|
||||
Broadcast::routes();
|
||||
|
||||
|
||||
@@ -5,10 +5,7 @@ namespace App\Providers;
|
||||
use Illuminate\Auth\Events\Registered;
|
||||
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
|
||||
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
|
||||
use Illuminate\Queue\Events\JobProcessed;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class EventServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -23,38 +20,18 @@ class EventServiceProvider extends ServiceProvider
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Register any events for your application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
public function boot(): void
|
||||
{
|
||||
Queue::after(function (JobProcessed $event) {
|
||||
// Log::info($event->connectionName);
|
||||
// Log::info('ID: ' . $event->job->getJobId());
|
||||
// Log::info('Attempts: ' . $event->job->attempts());
|
||||
// Log::info('Name: ' . $event->job->getName());
|
||||
// Log::info('ResolveNAme: ' . $event->job->resolveName());
|
||||
// Log::info('Queue: ' . $event->job->getQueue());
|
||||
// Log::info('Body: ' . $event->job->getRawBody());
|
||||
// Log::info(print_r($event->job->payload(), true));
|
||||
|
||||
// $payload = $event->job->payload();
|
||||
// $data = unserialize($payload['data']['command']);
|
||||
|
||||
// Log::info('MAIL: ' . $data->to);
|
||||
// Log::info('MAIL: ' . get_class($data->mailable));
|
||||
});
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if events and listeners should be automatically discovered.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function shouldDiscoverEvents()
|
||||
public function shouldDiscoverEvents(): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ use Illuminate\Support\Facades\Route;
|
||||
class RouteServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* The path to the "home" route for your application.
|
||||
* The path to your application's "home" route.
|
||||
*
|
||||
* Typically, users are redirected here after authentication.
|
||||
*
|
||||
@@ -19,15 +19,14 @@ class RouteServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public const HOME = '/home';
|
||||
|
||||
|
||||
/**
|
||||
* Define your route model bindings, pattern filters, and other route configuration.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
public function boot(): void
|
||||
{
|
||||
$this->configureRateLimiting();
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(60)->by($request->user()?->id ?: $request->ip());
|
||||
});
|
||||
|
||||
$this->routes(function () {
|
||||
Route::middleware('api')
|
||||
@@ -38,36 +37,4 @@ class RouteServiceProvider extends ServiceProvider
|
||||
->group(base_path('routes/web.php'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the rate limiters for the application.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function configureRateLimiting()
|
||||
{
|
||||
// RateLimiter::for('api', function (Request $request) {
|
||||
// return Limit::perMinute(60)->by($request->user()?->id !== null ?: $request->ip());
|
||||
// });
|
||||
|
||||
$rateLimitEnabled = true;
|
||||
$user = auth()->user();
|
||||
|
||||
if (app()->environment('testing')) {
|
||||
$rateLimitEnabled = false;
|
||||
} elseif ($user !== null && $user->hasPermission('admin/ratelimit') === true) {
|
||||
// Admin users with the "admin/ratelimit" permission are not rate limited
|
||||
$rateLimitEnabled = false;
|
||||
}
|
||||
|
||||
if ($rateLimitEnabled === true) {
|
||||
RateLimiter::for('api', function (Request $request) {
|
||||
return Limit::perMinute(180)->by($request->user()?->id ?: $request->ip());
|
||||
});
|
||||
} else {
|
||||
RateLimiter::for('api', function () {
|
||||
return Limit::none();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Rules;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Contracts\Validation\Rule;
|
||||
|
||||
class Recaptcha implements Rule
|
||||
{
|
||||
/**
|
||||
* Create a new rule instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the validation rule passes.
|
||||
*
|
||||
* @param mixed $attribute Attribute name.
|
||||
* @param mixed $value Attribute value.
|
||||
* @return boolean
|
||||
*/
|
||||
public function passes(mixed $attribute, mixed $value)
|
||||
{
|
||||
$endpoint = config('services.google_recaptcha');
|
||||
|
||||
$response = Http::asForm()->post($endpoint['url'], [
|
||||
'secret' => $endpoint['secret_key'],
|
||||
'response' => $value,
|
||||
])->json();
|
||||
|
||||
if ($response['success'] === true && $response['score'] > 0.5) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation error message.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function message()
|
||||
{
|
||||
return 'Captcha failed. Refresh the page and try again';
|
||||
}
|
||||
}
|
||||
@@ -1,698 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
class AnimatedGifService
|
||||
{
|
||||
/**
|
||||
* Check if a GIF file at a path is animated or not
|
||||
*
|
||||
* @param string $filenameOrBlob GIF file path or data blob if dataSize > 0.
|
||||
* @param integer $dataSize GIF blob size.
|
||||
* @return boolean GIF file/blob is animated.
|
||||
*/
|
||||
public static function isAnimatedGif(string $filenameOrBlob, int $dataSize = 0)
|
||||
{
|
||||
$regex = '#\x00\x21\xF9\x04.{4}\x00(\x2C|\x21)#s';
|
||||
$count = 0;
|
||||
|
||||
if ($dataSize > 0) {
|
||||
if (($fh = @fopen($filenameOrBlob, 'rb')) === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$chunk = false;
|
||||
while (feof($fh) === false && $count < 2) {
|
||||
$chunk = ($chunk !== '' ? substr($chunk, -20) : "") . fread($fh, (1024 * 100)); //read 100kb at a time
|
||||
$count += preg_match_all($regex, $chunk, $matches);
|
||||
}
|
||||
|
||||
fclose($fh);
|
||||
} else {
|
||||
$count = preg_match_all($regex, $filenameOrBlob, $matches);
|
||||
}
|
||||
|
||||
return $count > 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract frames of a GIF
|
||||
*
|
||||
* @param string $filenameOrBlob GIF filename path
|
||||
* @param integer $dataSize GIF blob size.
|
||||
* @param boolean $originalFrames Get original frames (with transparent background)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function extract(string $filenameOrBlob, int $dataSize = 0, $originalFrames = false)
|
||||
{
|
||||
if (self::isAnimatedGif($filenameOrBlob) === false) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$this->reset();
|
||||
$this->parseFramesInfo($filename);
|
||||
$prevImg = null;
|
||||
|
||||
for ($i = 0; $i < count($this->frameSources); $i++) {
|
||||
$this->frames[$i] = [];
|
||||
$this->frameDurations[$i] = $this->frames[$i]['duration'] = $this->frameSources[$i]['delay_time'];
|
||||
|
||||
$img = imagecreatefromstring($this->fileHeader["gifheader"] . $this->frameSources[$i]["graphicsextension"] . $this->frameSources[$i]["imagedata"] . chr(0x3b));
|
||||
|
||||
if (!$originalFrames) {
|
||||
if ($i > 0) {
|
||||
$prevImg = $this->frames[($i - 1)]['image'];
|
||||
} else {
|
||||
$prevImg = $img;
|
||||
}
|
||||
|
||||
$sprite = imagecreate($this->gifMaxWidth, $this->gifMaxHeight);
|
||||
imagesavealpha($sprite, true);
|
||||
|
||||
$transparent = imagecolortransparent($prevImg);
|
||||
|
||||
if ($transparent > -1 && imagecolorstotal($prevImg) > $transparent) {
|
||||
$actualTrans = imagecolorsforindex($prevImg, $transparent);
|
||||
imagecolortransparent($sprite, imagecolorallocate($sprite, $actualTrans['red'], $actualTrans['green'], $actualTrans['blue']));
|
||||
}
|
||||
|
||||
if ((int) $this->frameSources[$i]['disposal_method'] == 1 && $i > 0) {
|
||||
imagecopy($sprite, $prevImg, 0, 0, 0, 0, $this->gifMaxWidth, $this->gifMaxHeight);
|
||||
}
|
||||
|
||||
imagecopyresampled($sprite, $img, $this->frameSources[$i]["offset_left"], $this->frameSources[$i]["offset_top"], 0, 0, $this->gifMaxWidth, $this->gifMaxHeight, $this->gifMaxWidth, $this->gifMaxHeight);
|
||||
$img = $sprite;
|
||||
}//end if
|
||||
|
||||
$this->frameImages[$i] = $this->frames[$i]['image'] = $img;
|
||||
}//end for
|
||||
|
||||
return $this->frames;
|
||||
}
|
||||
}
|
||||
|
||||
class GifFrameExtractor
|
||||
{
|
||||
// Properties
|
||||
// ===================================================================================
|
||||
|
||||
/**
|
||||
* @var resource
|
||||
*/
|
||||
private $gif;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $frames;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $frameDurations;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $frameImages;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $framePositions;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $frameDimensions;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*
|
||||
* (old: $this->index)
|
||||
*/
|
||||
private $frameNumber;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* (old: $this->imagedata)
|
||||
*/
|
||||
private $frameSources;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* (old: $this->fileHeader)
|
||||
*/
|
||||
private $fileHeader;
|
||||
|
||||
/**
|
||||
* @var integer The reader pointer in the file source
|
||||
*
|
||||
* (old: $this->pointer)
|
||||
*/
|
||||
private $pointer;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
private $gifMaxWidth;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
private $gifMaxHeight;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
private $totalDuration;
|
||||
|
||||
/**
|
||||
* @var integer
|
||||
*/
|
||||
private $handle;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* (old: globaldata)
|
||||
*/
|
||||
private $globaldata;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* (old: orgvars)
|
||||
*/
|
||||
private $orgvars;
|
||||
|
||||
// Methods
|
||||
// ===================================================================================
|
||||
|
||||
|
||||
/**
|
||||
* Parse the frame informations contained in the GIF file
|
||||
*
|
||||
* @param string $filename GIF filename path
|
||||
*/
|
||||
private function parseFramesInfo($filename)
|
||||
{
|
||||
$this->openFile($filename);
|
||||
$this->parseGifHeader();
|
||||
$this->parseGraphicsExtension(0);
|
||||
$this->getApplicationData();
|
||||
$this->getApplicationData();
|
||||
$this->getFrameString(0);
|
||||
$this->parseGraphicsExtension(1);
|
||||
$this->getCommentData();
|
||||
$this->getApplicationData();
|
||||
$this->getFrameString(1);
|
||||
|
||||
while (!$this->checkByte(0x3b) && !$this->checkEOF()) {
|
||||
$this->getCommentData(1);
|
||||
$this->parseGraphicsExtension(2);
|
||||
$this->getFrameString(2);
|
||||
$this->getApplicationData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the gif header (old: get_gif_header)
|
||||
*/
|
||||
private function parseGifHeader()
|
||||
{
|
||||
$this->pointerForward(10);
|
||||
|
||||
if ($this->readBits(($mybyte = $this->readByteInt()), 0, 1) == 1) {
|
||||
$this->pointerForward(2);
|
||||
$this->pointerForward(pow(2, ($this->readBits($mybyte, 5, 3) + 1)) * 3);
|
||||
} else {
|
||||
$this->pointerForward(2);
|
||||
}
|
||||
|
||||
$this->fileHeader["gifheader"] = $this->dataPart(0, $this->pointer);
|
||||
|
||||
// Decoding
|
||||
$this->orgvars["gifheader"] = $this->fileHeader["gifheader"];
|
||||
$this->orgvars["background_color"] = $this->orgvars["gifheader"][11];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the application data of the frames (old: get_application_data)
|
||||
*/
|
||||
private function getApplicationData()
|
||||
{
|
||||
$startdata = $this->readByte(2);
|
||||
|
||||
if ($startdata == chr(0x21) . chr(0xff)) {
|
||||
$start = ($this->pointer - 2);
|
||||
$this->pointerForward($this->readByteInt());
|
||||
$this->readDataStream($this->readByteInt());
|
||||
$this->fileHeader["applicationdata"] = $this->dataPart($start, ($this->pointer - $start));
|
||||
} else {
|
||||
$this->pointerRewind(2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the comment data of the frames (old: get_comment_data)
|
||||
*/
|
||||
private function getCommentData()
|
||||
{
|
||||
$startdata = $this->readByte(2);
|
||||
|
||||
if ($startdata == chr(0x21) . chr(0xfe)) {
|
||||
$start = ($this->pointer - 2);
|
||||
$this->readDataStream($this->readByteInt());
|
||||
$this->fileHeader["commentdata"] = $this->dataPart($start, ($this->pointer - $start));
|
||||
} else {
|
||||
$this->pointerRewind(2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the graphic extension of the frames (old: get_graphics_extension)
|
||||
*
|
||||
* @param integer $type
|
||||
*/
|
||||
private function parseGraphicsExtension($type)
|
||||
{
|
||||
$startdata = $this->readByte(2);
|
||||
|
||||
if ($startdata == chr(0x21) . chr(0xf9)) {
|
||||
$start = ($this->pointer - 2);
|
||||
$this->pointerForward($this->readByteInt());
|
||||
$this->pointerForward(1);
|
||||
|
||||
if ($type == 2) {
|
||||
$this->frameSources[$this->frameNumber]["graphicsextension"] = $this->dataPart($start, ($this->pointer - $start));
|
||||
} elseif ($type == 1) {
|
||||
$this->orgvars["hasgx_type_1"] = 1;
|
||||
$this->globaldata["graphicsextension"] = $this->dataPart($start, ($this->pointer - $start));
|
||||
} elseif ($type == 0) {
|
||||
$this->orgvars["hasgx_type_0"] = 1;
|
||||
$this->globaldata["graphicsextension_0"] = $this->dataPart($start, ($this->pointer - $start));
|
||||
}
|
||||
} else {
|
||||
$this->pointerRewind(2);
|
||||
}//end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the full frame string block (old: get_image_block)
|
||||
*
|
||||
* @param integer $type
|
||||
*/
|
||||
private function getFrameString($type)
|
||||
{
|
||||
if ($this->checkByte(0x2c)) {
|
||||
$start = $this->pointer;
|
||||
$this->pointerForward(9);
|
||||
|
||||
if ($this->readBits(($mybyte = $this->readByteInt()), 0, 1) == 1) {
|
||||
$this->pointerForward(pow(2, ($this->readBits($mybyte, 5, 3) + 1)) * 3);
|
||||
}
|
||||
|
||||
$this->pointerForward(1);
|
||||
$this->readDataStream($this->readByteInt());
|
||||
$this->frameSources[$this->frameNumber]["imagedata"] = $this->dataPart($start, ($this->pointer - $start));
|
||||
|
||||
if ($type == 0) {
|
||||
$this->orgvars["hasgx_type_0"] = 0;
|
||||
|
||||
if (isset($this->globaldata["graphicsextension_0"])) {
|
||||
$this->frameSources[$this->frameNumber]["graphicsextension"] = $this->globaldata["graphicsextension_0"];
|
||||
} else {
|
||||
$this->frameSources[$this->frameNumber]["graphicsextension"] = null;
|
||||
}
|
||||
|
||||
unset($this->globaldata["graphicsextension_0"]);
|
||||
} elseif ($type == 1) {
|
||||
if (isset($this->orgvars["hasgx_type_1"]) && $this->orgvars["hasgx_type_1"] == 1) {
|
||||
$this->orgvars["hasgx_type_1"] = 0;
|
||||
$this->frameSources[$this->frameNumber]["graphicsextension"] = $this->globaldata["graphicsextension"];
|
||||
unset($this->globaldata["graphicsextension"]);
|
||||
} else {
|
||||
$this->orgvars["hasgx_type_0"] = 0;
|
||||
$this->frameSources[$this->frameNumber]["graphicsextension"] = $this->globaldata["graphicsextension_0"];
|
||||
unset($this->globaldata["graphicsextension_0"]);
|
||||
}
|
||||
}//end if
|
||||
|
||||
$this->parseFrameData();
|
||||
$this->frameNumber++;
|
||||
}//end if
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse frame data string into an array (old: parse_image_data)
|
||||
*/
|
||||
private function parseFrameData()
|
||||
{
|
||||
$this->frameSources[$this->frameNumber]["disposal_method"] = $this->getImageDataBit("ext", 3, 3, 3);
|
||||
$this->frameSources[$this->frameNumber]["user_input_flag"] = $this->getImageDataBit("ext", 3, 6, 1);
|
||||
$this->frameSources[$this->frameNumber]["transparent_color_flag"] = $this->getImageDataBit("ext", 3, 7, 1);
|
||||
$this->frameSources[$this->frameNumber]["delay_time"] = $this->dualByteVal($this->getImageDataByte("ext", 4, 2));
|
||||
$this->totalDuration += (int) $this->frameSources[$this->frameNumber]["delay_time"];
|
||||
$this->frameSources[$this->frameNumber]["transparent_color_index"] = ord($this->getImageDataByte("ext", 6, 1));
|
||||
$this->frameSources[$this->frameNumber]["offset_left"] = $this->dualByteVal($this->getImageDataByte("dat", 1, 2));
|
||||
$this->frameSources[$this->frameNumber]["offset_top"] = $this->dualByteVal($this->getImageDataByte("dat", 3, 2));
|
||||
$this->frameSources[$this->frameNumber]["width"] = $this->dualByteVal($this->getImageDataByte("dat", 5, 2));
|
||||
$this->frameSources[$this->frameNumber]["height"] = $this->dualByteVal($this->getImageDataByte("dat", 7, 2));
|
||||
$this->frameSources[$this->frameNumber]["local_color_table_flag"] = $this->getImageDataBit("dat", 9, 0, 1);
|
||||
$this->frameSources[$this->frameNumber]["interlace_flag"] = $this->getImageDataBit("dat", 9, 1, 1);
|
||||
$this->frameSources[$this->frameNumber]["sort_flag"] = $this->getImageDataBit("dat", 9, 2, 1);
|
||||
$this->frameSources[$this->frameNumber]["color_table_size"] = (pow(2, ($this->getImageDataBit("dat", 9, 5, 3) + 1)) * 3);
|
||||
$this->frameSources[$this->frameNumber]["color_table"] = substr($this->frameSources[$this->frameNumber]["imagedata"], 10, $this->frameSources[$this->frameNumber]["color_table_size"]);
|
||||
$this->frameSources[$this->frameNumber]["lzw_code_size"] = ord($this->getImageDataByte("dat", 10, 1));
|
||||
|
||||
$this->framePositions[$this->frameNumber] = [
|
||||
'x' => $this->frameSources[$this->frameNumber]["offset_left"],
|
||||
'y' => $this->frameSources[$this->frameNumber]["offset_top"],
|
||||
];
|
||||
|
||||
$this->frameDimensions[$this->frameNumber] = [
|
||||
'width' => $this->frameSources[$this->frameNumber]["width"],
|
||||
'height' => $this->frameSources[$this->frameNumber]["height"],
|
||||
];
|
||||
|
||||
// Decoding
|
||||
$this->orgvars[$this->frameNumber]["transparent_color_flag"] = $this->frameSources[$this->frameNumber]["transparent_color_flag"];
|
||||
$this->orgvars[$this->frameNumber]["transparent_color_index"] = $this->frameSources[$this->frameNumber]["transparent_color_index"];
|
||||
$this->orgvars[$this->frameNumber]["delay_time"] = $this->frameSources[$this->frameNumber]["delay_time"];
|
||||
$this->orgvars[$this->frameNumber]["disposal_method"] = $this->frameSources[$this->frameNumber]["disposal_method"];
|
||||
$this->orgvars[$this->frameNumber]["offset_left"] = $this->frameSources[$this->frameNumber]["offset_left"];
|
||||
$this->orgvars[$this->frameNumber]["offset_top"] = $this->frameSources[$this->frameNumber]["offset_top"];
|
||||
|
||||
// Updating the max width
|
||||
if ($this->gifMaxWidth < $this->frameSources[$this->frameNumber]["width"]) {
|
||||
$this->gifMaxWidth = $this->frameSources[$this->frameNumber]["width"];
|
||||
}
|
||||
|
||||
// Updating the max height
|
||||
if ($this->gifMaxHeight < $this->frameSources[$this->frameNumber]["height"]) {
|
||||
$this->gifMaxHeight = $this->frameSources[$this->frameNumber]["height"];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image data byte (old: get_imagedata_byte)
|
||||
*
|
||||
* @param string $type
|
||||
* @param integer $start
|
||||
* @param integer $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getImageDataByte($type, $start, $length)
|
||||
{
|
||||
if ($type == "ext") {
|
||||
return substr($this->frameSources[$this->frameNumber]["graphicsextension"], $start, $length);
|
||||
}
|
||||
|
||||
// "dat"
|
||||
return substr($this->frameSources[$this->frameNumber]["imagedata"], $start, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the image data bit (old: get_imagedata_bit)
|
||||
*
|
||||
* @param string $type
|
||||
* @param integer $byteIndex
|
||||
* @param integer $bitStart
|
||||
* @param integer $bitLength
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
private function getImageDataBit($type, $byteIndex, $bitStart, $bitLength)
|
||||
{
|
||||
if ($type == "ext") {
|
||||
return $this->readBits(ord(substr($this->frameSources[$this->frameNumber]["graphicsextension"], $byteIndex, 1)), $bitStart, $bitLength);
|
||||
}
|
||||
|
||||
// "dat"
|
||||
return $this->readBits(ord(substr($this->frameSources[$this->frameNumber]["imagedata"], $byteIndex, 1)), $bitStart, $bitLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the value of 2 ASCII chars (old: dualbyteval)
|
||||
*
|
||||
* @param string $s
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
private function dualByteVal($s)
|
||||
{
|
||||
$i = (ord($s[1]) * 256 + ord($s[0]));
|
||||
|
||||
return $i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the data stream (old: read_data_stream)
|
||||
*
|
||||
* @param integer $firstLength
|
||||
*/
|
||||
private function readDataStream($firstLength)
|
||||
{
|
||||
$this->pointerForward($firstLength);
|
||||
$length = $this->readByteInt();
|
||||
|
||||
if ($length != 0) {
|
||||
while ($length != 0) {
|
||||
$this->pointerForward($length);
|
||||
$length = $this->readByteInt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open the gif file (old: loadfile)
|
||||
*
|
||||
* @param string $filename
|
||||
*/
|
||||
private function openFile($filename)
|
||||
{
|
||||
$this->handle = fopen($filename, "rb");
|
||||
$this->pointer = 0;
|
||||
|
||||
$imageSize = getimagesize($filename);
|
||||
$this->gifWidth = $imageSize[0];
|
||||
$this->gifHeight = $imageSize[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the read gif file (old: closefile)
|
||||
*/
|
||||
private function closeFile()
|
||||
{
|
||||
fclose($this->handle);
|
||||
$this->handle = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the file from the beginning to $byteCount in binary (old: readbyte)
|
||||
*
|
||||
* @param integer $byteCount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function readByte($byteCount)
|
||||
{
|
||||
$data = fread($this->handle, $byteCount);
|
||||
$this->pointer += $byteCount;
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a byte and return ASCII value (old: readbyte_int)
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
private function readByteInt()
|
||||
{
|
||||
$data = fread($this->handle, 1);
|
||||
$this->pointer++;
|
||||
|
||||
return ord($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a $byte to decimal (old: readbits)
|
||||
*
|
||||
* @param string $byte
|
||||
* @param integer $start
|
||||
* @param integer $length
|
||||
*
|
||||
* @return number
|
||||
*/
|
||||
private function readBits($byte, $start, $length)
|
||||
{
|
||||
$bin = str_pad(decbin($byte), 8, "0", STR_PAD_LEFT);
|
||||
$data = substr($bin, $start, $length);
|
||||
|
||||
return bindec($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the file pointer reader (old: p_rewind)
|
||||
*
|
||||
* @param integer $length
|
||||
*/
|
||||
private function pointerRewind($length)
|
||||
{
|
||||
$this->pointer -= $length;
|
||||
fseek($this->handle, $this->pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Forward the file pointer reader (old: p_forward)
|
||||
*
|
||||
* @param integer $length
|
||||
*/
|
||||
private function pointerForward($length)
|
||||
{
|
||||
$this->pointer += $length;
|
||||
fseek($this->handle, $this->pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a section of the data from $start to $start + $length (old: datapart)
|
||||
*
|
||||
* @param integer $start
|
||||
* @param integer $length
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function dataPart($start, $length)
|
||||
{
|
||||
fseek($this->handle, $start);
|
||||
$data = fread($this->handle, $length);
|
||||
fseek($this->handle, $this->pointer);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a character if a byte (old: checkbyte)
|
||||
*
|
||||
* @param integer $byte
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function checkByte($byte)
|
||||
{
|
||||
if (fgetc($this->handle) == chr($byte)) {
|
||||
fseek($this->handle, $this->pointer);
|
||||
return true;
|
||||
}
|
||||
|
||||
fseek($this->handle, $this->pointer);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the end of the file (old: checkEOF)
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function checkEOF()
|
||||
{
|
||||
if (fgetc($this->handle) === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
fseek($this->handle, $this->pointer);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset and clear this current object
|
||||
*/
|
||||
private function reset()
|
||||
{
|
||||
$this->gif = null;
|
||||
$this->totalDuration = $this->gifMaxHeight = $this->gifMaxWidth = $this->handle = $this->pointer = $this->frameNumber = 0;
|
||||
$this->frameDimensions = $this->framePositions = $this->frameImages = $this->frameDurations = $this->globaldata = $this->orgvars = $this->frames = $this->fileHeader = $this->frameSources = [];
|
||||
}
|
||||
|
||||
// Getter / Setter
|
||||
// ===================================================================================
|
||||
|
||||
|
||||
/**
|
||||
* Get the total of all added frame duration
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getTotalDuration()
|
||||
{
|
||||
return $this->totalDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of extracted frames
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getFrameNumber()
|
||||
{
|
||||
return $this->frameNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extracted frames (images and durations)
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFrames()
|
||||
{
|
||||
return $this->frames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extracted frame positions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFramePositions()
|
||||
{
|
||||
return $this->framePositions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extracted frame dimensions
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFrameDimensions()
|
||||
{
|
||||
return $this->frameDimensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extracted frame images
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFrameImages()
|
||||
{
|
||||
return $this->frameImages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the extracted frame durations
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFrameDurations()
|
||||
{
|
||||
return $this->frameDurations;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
trait Uuids
|
||||
{
|
||||
/**
|
||||
* Boot function from Laravel.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected static function bootUuids()
|
||||
{
|
||||
static::creating(function ($model) {
|
||||
if (empty($model->{$model->getKeyName()}) === true) {
|
||||
$model->{$model->getKeyName()} = Str::uuid()->toString();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value indicating whether the IDs are incrementing.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function getIncrementing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the auto-incrementing key type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKeyType()
|
||||
{
|
||||
return 'string';
|
||||
}
|
||||
}
|
||||
@@ -1,49 +1,36 @@
|
||||
{
|
||||
"name": "laravel/laravel",
|
||||
"type": "project",
|
||||
"description": "The Laravel Framework.",
|
||||
"keywords": [
|
||||
"framework",
|
||||
"laravel"
|
||||
],
|
||||
"description": "The skeleton application for the Laravel framework.",
|
||||
"keywords": ["laravel", "framework"],
|
||||
"license": "MIT",
|
||||
"require": {
|
||||
"php": "^8.0.2",
|
||||
"doctrine/dbal": "^3.5",
|
||||
"php": "^8.1",
|
||||
"guzzlehttp/guzzle": "^7.2",
|
||||
"intervention/image": "^2.7",
|
||||
"laravel/framework": "^9.19",
|
||||
"laravel/sanctum": "^3.0",
|
||||
"laravel/tinker": "^2.7",
|
||||
"owen-it/laravel-auditing": "^13.0",
|
||||
"php-ffmpeg/php-ffmpeg": "^1.1",
|
||||
"spatie/image-optimizer": "^1.6",
|
||||
"thiagoalessio/tesseract_ocr": "^2.12"
|
||||
"itsgoingd/clockwork": "^5.1",
|
||||
"laravel/framework": "^10.10",
|
||||
"laravel/sanctum": "^3.3",
|
||||
"laravel/tinker": "^2.8"
|
||||
},
|
||||
"require-dev": {
|
||||
"fakerphp/faker": "^1.9.1",
|
||||
"laravel/pint": "^1.0",
|
||||
"laravel/sail": "^1.0.1",
|
||||
"laravel/sail": "^1.18",
|
||||
"mockery/mockery": "^1.4.4",
|
||||
"nunomaduro/collision": "^6.1",
|
||||
"phpunit/phpunit": "^9.5.10",
|
||||
"spatie/laravel-ignition": "^1.0"
|
||||
"nunomaduro/collision": "^7.0",
|
||||
"phpunit/phpunit": "^10.1",
|
||||
"spatie/laravel-ignition": "^2.0"
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"app/Helpers/Array.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"App\\": "app/",
|
||||
"Database\\Factories\\": "database/factories/",
|
||||
"Database\\Seeders\\": "database/seeders/",
|
||||
"Faker\\Provider\\": "faker/provider/"
|
||||
"Database\\Seeders\\": "database/seeders/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\": "tests/",
|
||||
"Faker\\Provider\\": "faker/provider/"
|
||||
"Tests\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
@@ -71,9 +58,10 @@
|
||||
"preferred-install": "dist",
|
||||
"sort-packages": true,
|
||||
"allow-plugins": {
|
||||
"pestphp/pest-plugin": true
|
||||
"pestphp/pest-plugin": true,
|
||||
"php-http/discovery": true
|
||||
}
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"minimum-stability": "stable",
|
||||
"prefer-stable": true
|
||||
}
|
||||
|
||||
3385
composer.lock
generated
3385
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Facade;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
|
||||
return [
|
||||
|
||||
@@ -69,7 +70,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'timezone' => env('APP_TIMEZONE', 'UTC'),
|
||||
'timezone' => 'UTC',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -140,7 +141,7 @@ return [
|
||||
|
||||
'maintenance' => [
|
||||
'driver' => 'file',
|
||||
// 'store' => 'redis',
|
||||
// 'store' => 'redis',
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -154,39 +155,10 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'providers' => [
|
||||
|
||||
/*
|
||||
* Laravel Framework Service Providers...
|
||||
*/
|
||||
Illuminate\Auth\AuthServiceProvider::class,
|
||||
Illuminate\Broadcasting\BroadcastServiceProvider::class,
|
||||
Illuminate\Bus\BusServiceProvider::class,
|
||||
Illuminate\Cache\CacheServiceProvider::class,
|
||||
Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
|
||||
Illuminate\Cookie\CookieServiceProvider::class,
|
||||
Illuminate\Database\DatabaseServiceProvider::class,
|
||||
Illuminate\Encryption\EncryptionServiceProvider::class,
|
||||
Illuminate\Filesystem\FilesystemServiceProvider::class,
|
||||
Illuminate\Foundation\Providers\FoundationServiceProvider::class,
|
||||
Illuminate\Hashing\HashServiceProvider::class,
|
||||
Illuminate\Mail\MailServiceProvider::class,
|
||||
Illuminate\Notifications\NotificationServiceProvider::class,
|
||||
Illuminate\Pagination\PaginationServiceProvider::class,
|
||||
Illuminate\Pipeline\PipelineServiceProvider::class,
|
||||
Illuminate\Queue\QueueServiceProvider::class,
|
||||
Illuminate\Redis\RedisServiceProvider::class,
|
||||
Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
|
||||
Illuminate\Session\SessionServiceProvider::class,
|
||||
Illuminate\Translation\TranslationServiceProvider::class,
|
||||
Illuminate\Validation\ValidationServiceProvider::class,
|
||||
Illuminate\View\ViewServiceProvider::class,
|
||||
|
||||
'providers' => ServiceProvider::defaultProviders()->merge([
|
||||
/*
|
||||
* Package Service Providers...
|
||||
*/
|
||||
Intervention\Image\ImageServiceProvider::class,
|
||||
OwenIt\Auditing\AuditingServiceProvider::class,
|
||||
|
||||
/*
|
||||
* Application Service Providers...
|
||||
@@ -196,8 +168,7 @@ return [
|
||||
// App\Providers\BroadcastServiceProvider::class,
|
||||
App\Providers\EventServiceProvider::class,
|
||||
App\Providers\RouteServiceProvider::class,
|
||||
|
||||
],
|
||||
])->toArray(),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -211,7 +182,7 @@ return [
|
||||
*/
|
||||
|
||||
'aliases' => Facade::defaultAliases()->merge([
|
||||
'ImageIntervention' => Intervention\Image\Facades\Image::class,
|
||||
// 'Example' => App\Facades\Example::class,
|
||||
])->toArray(),
|
||||
|
||||
];
|
||||
|
||||
169
config/audit.php
169
config/audit.php
@@ -1,169 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
'enabled' => env('AUDITING_ENABLED', true),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Audit Implementation
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define which Audit model implementation should be used.
|
||||
|
|
||||
*/
|
||||
|
||||
'implementation' => OwenIt\Auditing\Models\Audit::class,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| User Morph prefix & Guards
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define the morph prefix and authentication guards for the User resolver.
|
||||
|
|
||||
*/
|
||||
|
||||
'user' => [
|
||||
'morph_prefix' => 'user',
|
||||
'guards' => [
|
||||
'web',
|
||||
'api'
|
||||
],
|
||||
'resolver' => OwenIt\Auditing\Resolvers\UserResolver::class
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Audit Resolvers
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Define the User, IP Address, User Agent and URL resolver implementations.
|
||||
|
|
||||
*/
|
||||
'resolvers' => [
|
||||
'ip_address' => OwenIt\Auditing\Resolvers\IpAddressResolver::class,
|
||||
'user_agent' => OwenIt\Auditing\Resolvers\UserAgentResolver::class,
|
||||
'url' => OwenIt\Auditing\Resolvers\UrlResolver::class,
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Audit Events
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The Eloquent events that trigger an Audit.
|
||||
|
|
||||
*/
|
||||
|
||||
'events' => [
|
||||
'created',
|
||||
'updated',
|
||||
'deleted',
|
||||
'restored'
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Strict Mode
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Enable the strict mode when auditing?
|
||||
|
|
||||
*/
|
||||
|
||||
'strict' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Global exclude
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Have something you always want to exclude by default? - add it here.
|
||||
| Note that this is overwritten (not merged) with local exclude
|
||||
|
|
||||
*/
|
||||
|
||||
'exclude' => [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Empty Values
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Should Audit records be stored when the recorded old_values & new_values
|
||||
| are both empty?
|
||||
|
|
||||
| Some events may be empty on purpose. Use allowed_empty_values to exclude
|
||||
| those from the empty values check. For example when auditing
|
||||
| model retrieved events which will never have new and old values.
|
||||
|
|
||||
|
|
||||
*/
|
||||
|
||||
'empty_values' => true,
|
||||
'allowed_empty_values' => [
|
||||
'retrieved'
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Audit Timestamps
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Should the created_at, updated_at and deleted_at timestamps be audited?
|
||||
|
|
||||
*/
|
||||
|
||||
'timestamps' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Audit Threshold
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Specify a threshold for the amount of Audit records a model can have.
|
||||
| Zero means no limit.
|
||||
|
|
||||
*/
|
||||
|
||||
'threshold' => 0,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Audit Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The default audit driver used to keep track of changes.
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => 'database',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Audit Driver Configurations
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Available audit drivers and respective configurations.
|
||||
|
|
||||
*/
|
||||
|
||||
'drivers' => [
|
||||
'database' => [
|
||||
'table' => 'audits',
|
||||
'connection' => null,
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Audit Console
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Whether console events should be audited (eg. php artisan db:seed).
|
||||
|
|
||||
*/
|
||||
|
||||
'console' => false,
|
||||
];
|
||||
@@ -80,16 +80,20 @@ return [
|
||||
| than one user table or model in the application and you want to have
|
||||
| separate password reset settings based on the specific user types.
|
||||
|
|
||||
| The expire time is the number of minutes that each reset token will be
|
||||
| The expiry time is the number of minutes that each reset token will be
|
||||
| considered valid. This security feature keeps tokens short-lived so
|
||||
| they have less time to be guessed. You may change this as needed.
|
||||
|
|
||||
| The throttle setting is the number of seconds a user must wait before
|
||||
| generating more password reset tokens. This prevents the user from
|
||||
| quickly generating a very large amount of password reset tokens.
|
||||
|
|
||||
*/
|
||||
|
||||
'passwords' => [
|
||||
'users' => [
|
||||
'provider' => 'users',
|
||||
'table' => 'password_resets',
|
||||
'table' => 'password_reset_tokens',
|
||||
'expire' => 60,
|
||||
'throttle' => 60,
|
||||
],
|
||||
|
||||
@@ -36,7 +36,8 @@ return [
|
||||
'secret' => env('PUSHER_APP_SECRET'),
|
||||
'app_id' => env('PUSHER_APP_ID'),
|
||||
'options' => [
|
||||
'host' => env('PUSHER_HOST') === true ?: 'api-' . env('PUSHER_APP_CLUSTER', 'mt1') . '.pusher.com',
|
||||
'cluster' => env('PUSHER_APP_CLUSTER'),
|
||||
'host' => env('PUSHER_HOST') ?: 'api-'.env('PUSHER_APP_CLUSTER', 'mt1').'.pusher.com',
|
||||
'port' => env('PUSHER_PORT', 443),
|
||||
'scheme' => env('PUSHER_SCHEME', 'https'),
|
||||
'encrypted' => true,
|
||||
|
||||
@@ -52,6 +52,7 @@ return [
|
||||
'file' => [
|
||||
'driver' => 'file',
|
||||
'path' => storage_path('framework/cache/data'),
|
||||
'lock_path' => storage_path('framework/cache/data'),
|
||||
],
|
||||
|
||||
'memcached' => [
|
||||
@@ -105,6 +106,6 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_cache_'),
|
||||
'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache_'),
|
||||
|
||||
];
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'contact_address' => env('CONTACT_ADDRESS'),
|
||||
'contact_subject' => env('CONTACT_SUBJECT'),
|
||||
];
|
||||
@@ -58,9 +58,8 @@ return [
|
||||
'prefix_indexes' => true,
|
||||
'strict' => true,
|
||||
'engine' => null,
|
||||
'options' => extension_loaded('pdo_mysql') === true ? array_filter([
|
||||
'options' => extension_loaded('pdo_mysql') ? array_filter([
|
||||
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
|
||||
PDO::ATTR_TIMEOUT => env('DB_TIMEOUT', 30),
|
||||
]) : [],
|
||||
],
|
||||
|
||||
@@ -126,7 +125,7 @@ return [
|
||||
|
||||
'options' => [
|
||||
'cluster' => env('REDIS_CLUSTER', 'redis'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'),
|
||||
'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'),
|
||||
],
|
||||
|
||||
'default' => [
|
||||
|
||||
@@ -32,16 +32,16 @@ return [
|
||||
|
||||
'local' => [
|
||||
'driver' => 'local',
|
||||
'root' => storage_path('app/uploads'),
|
||||
'root' => storage_path('app'),
|
||||
'throw' => false,
|
||||
'url' => env('STORAGE_LOCAL_URL'),
|
||||
],
|
||||
|
||||
'public' => [
|
||||
'driver' => 'local',
|
||||
'root' => public_path('uploads'),
|
||||
'root' => storage_path('app/public'),
|
||||
'url' => env('APP_URL').'/storage',
|
||||
'visibility' => 'public',
|
||||
'throw' => false,
|
||||
'url' => env('STORAGE_PUBLIC_URL'),
|
||||
],
|
||||
|
||||
's3' => [
|
||||
|
||||
@@ -29,7 +29,8 @@ return [
|
||||
*/
|
||||
|
||||
'bcrypt' => [
|
||||
'rounds' => env('BCRYPT_ROUNDS', 10),
|
||||
'rounds' => env('BCRYPT_ROUNDS', 12),
|
||||
'verify' => true,
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -47,6 +48,7 @@ return [
|
||||
'memory' => 65536,
|
||||
'threads' => 1,
|
||||
'time' => 4,
|
||||
'verify' => true,
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Image Driver
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Intervention Image supports "GD Library" and "Imagick" to process images
|
||||
| internally. You may choose one of them according to your PHP
|
||||
| configuration. By default PHP's "GD Library" implementation is used.
|
||||
|
|
||||
| Supported: "gd", "imagick"
|
||||
|
|
||||
*/
|
||||
|
||||
'driver' => 'gd'
|
||||
|
||||
];
|
||||
@@ -3,6 +3,7 @@
|
||||
use Monolog\Handler\NullHandler;
|
||||
use Monolog\Handler\StreamHandler;
|
||||
use Monolog\Handler\SyslogUdpHandler;
|
||||
use Monolog\Processor\PsrLogMessageProcessor;
|
||||
|
||||
return [
|
||||
|
||||
@@ -61,6 +62,7 @@ return [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'daily' => [
|
||||
@@ -68,6 +70,7 @@ return [
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'days' => 14,
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'slack' => [
|
||||
@@ -76,6 +79,7 @@ return [
|
||||
'username' => 'Laravel Log',
|
||||
'emoji' => ':boom:',
|
||||
'level' => env('LOG_LEVEL', 'critical'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'papertrail' => [
|
||||
@@ -85,8 +89,9 @@ return [
|
||||
'handler_with' => [
|
||||
'host' => env('PAPERTRAIL_URL'),
|
||||
'port' => env('PAPERTRAIL_PORT'),
|
||||
'connectionString' => 'tls://' . env('PAPERTRAIL_URL') . ':' . env('PAPERTRAIL_PORT'),
|
||||
'connectionString' => 'tls://'.env('PAPERTRAIL_URL').':'.env('PAPERTRAIL_PORT'),
|
||||
],
|
||||
'processors' => [PsrLogMessageProcessor::class],
|
||||
],
|
||||
|
||||
'stderr' => [
|
||||
@@ -97,16 +102,20 @@ return [
|
||||
'with' => [
|
||||
'stream' => 'php://stderr',
|
||||
],
|
||||
'processors' => [PsrLogMessageProcessor::class],
|
||||
],
|
||||
|
||||
'syslog' => [
|
||||
'driver' => 'syslog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'facility' => LOG_USER,
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'errorlog' => [
|
||||
'driver' => 'errorlog',
|
||||
'level' => env('LOG_LEVEL', 'debug'),
|
||||
'replace_placeholders' => true,
|
||||
],
|
||||
|
||||
'null' => [
|
||||
|
||||
@@ -28,7 +28,7 @@ return [
|
||||
| sending an e-mail. You will specify which one you are using for your
|
||||
| mailers below. You are free to add additional mailers as required.
|
||||
|
|
||||
| Supported: "smtp", "sendmail", "mailgun", "ses",
|
||||
| Supported: "smtp", "sendmail", "mailgun", "ses", "ses-v2",
|
||||
| "postmark", "log", "array", "failover"
|
||||
|
|
||||
*/
|
||||
@@ -36,6 +36,7 @@ return [
|
||||
'mailers' => [
|
||||
'smtp' => [
|
||||
'transport' => 'smtp',
|
||||
'url' => env('MAIL_URL'),
|
||||
'host' => env('MAIL_HOST', 'smtp.mailgun.org'),
|
||||
'port' => env('MAIL_PORT', 587),
|
||||
'encryption' => env('MAIL_ENCRYPTION', 'tls'),
|
||||
@@ -51,10 +52,17 @@ return [
|
||||
|
||||
'mailgun' => [
|
||||
'transport' => 'mailgun',
|
||||
// 'client' => [
|
||||
// 'timeout' => 5,
|
||||
// ],
|
||||
],
|
||||
|
||||
'postmark' => [
|
||||
'transport' => 'postmark',
|
||||
// 'message_stream_id' => null,
|
||||
// 'client' => [
|
||||
// 'timeout' => 5,
|
||||
// ],
|
||||
],
|
||||
|
||||
'sendmail' => [
|
||||
@@ -78,10 +86,6 @@ return [
|
||||
'log',
|
||||
],
|
||||
],
|
||||
|
||||
'office365mail' => [
|
||||
'transport' => 'office365mail',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
<?php
|
||||
|
||||
use Stevebauman\Purify\Definitions\Html5Definition;
|
||||
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Config
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This option defines the default config that are provided to HTMLPurifier.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => 'default',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Config sets
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may configure various sets of configuration for differentiated use of HTMLPurifier.
|
||||
| A specific set of configuration can be applied by calling the "config($name)" method on
|
||||
| a Purify instance. Feel free to add/remove/customize these attributes as you wish.
|
||||
|
|
||||
| Documentation: http://htmlpurifier.org/live/configdoc/plain.html
|
||||
|
|
||||
| Core.Encoding The encoding to convert input to.
|
||||
| HTML.Doctype Doctype to use during filtering.
|
||||
| HTML.Allowed The allowed HTML Elements with their allowed attributes.
|
||||
| HTML.ForbiddenElements The forbidden HTML elements. Elements that are listed in this
|
||||
| string will be removed, however their content will remain.
|
||||
| CSS.AllowedProperties The Allowed CSS properties.
|
||||
| AutoFormat.AutoParagraph Newlines are converted in to paragraphs whenever possible.
|
||||
| AutoFormat.RemoveEmpty Remove empty elements that contribute no semantic information to the document.
|
||||
|
|
||||
*/
|
||||
|
||||
'configs' => [
|
||||
// @codingStandardsIgnoreStart
|
||||
'default' => [
|
||||
'Core.Encoding' => 'utf-8',
|
||||
'HTML.Doctype' => 'HTML 4.01 Transitional',
|
||||
'HTML.Allowed' => 'h1,h2,h3,h4,h5,h6,b,strong,i,em,s,del,a[href|title],ul,ol,li,p[style],br,span,img[width|height|alt|src]',
|
||||
'HTML.ForbiddenElements' => '',
|
||||
'CSS.AllowedProperties' => 'font,font-size,font-weight,font-style,font-family,text-decoration,padding-left,color,background-color,text-align',
|
||||
'AutoFormat.AutoParagraph' => false,
|
||||
'AutoFormat.RemoveEmpty' => false,
|
||||
],
|
||||
// @codingStandardsIgnoreEnd
|
||||
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| HTMLPurifier definitions
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify a class that augments the HTML definitions used by
|
||||
| HTMLPurifier. Additional HTML5 definitions are provided out of the box.
|
||||
| When specifying a custom class, make sure it implements the interface:
|
||||
|
|
||||
| \Stevebauman\Purify\Definitions\Definition
|
||||
|
|
||||
| Note that these definitions are applied to every Purifier instance.
|
||||
|
|
||||
| Documentation: http://htmlpurifier.org/docs/enduser-customize.html
|
||||
|
|
||||
*/
|
||||
|
||||
'definitions' => Html5Definition::class,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Serializer location
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| The location where HTMLPurifier can store its temporary serializer files.
|
||||
| The filepath should be accessible and writable by the web server.
|
||||
| A good place for this is in the framework's own storage path.
|
||||
|
|
||||
*/
|
||||
|
||||
'serializer' => storage_path('app/purify'),
|
||||
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user