mirror of
				https://github.com/firefly-iii/firefly-iii.git
				synced 2025-10-31 18:54:58 +00:00 
			
		
		
		
	Compare commits
	
		
			1438 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ecdf59ee3e | ||
|  | cc1f3bba7e | ||
|  | b501c47187 | ||
|  | 791b028dc4 | ||
|  | ab5b7f7893 | ||
|  | 4b1aa29269 | ||
|  | de34538d96 | ||
|  | 53eb93fc4d | ||
|  | a3841855e4 | ||
|  | b1e742c26c | ||
|  | 2c2814c998 | ||
|  | 214c7a6f3e | ||
|  | 6c4f967c39 | ||
|  | e0152d3df4 | ||
|  | 989ffc2f07 | ||
|  | f87a4c1e7c | ||
|  | fea5510700 | ||
|  | aa1ae18dbb | ||
|  | b5efd38ded | ||
|  | 2a457c40db | ||
|  | e38b64547f | ||
|  | bafa96b9c0 | ||
|  | d49a13b091 | ||
|  | 0bd818956f | ||
|  | c119b9cc7b | ||
|  | 958c7e7939 | ||
|  | 254a46b54c | ||
|  | 6ed31dc4c9 | ||
|  | fe8f5573d2 | ||
|  | 51dfb8ebf1 | ||
|  | 8fd64791d6 | ||
|  | 82e7202ad2 | ||
|  | 1f70782f7e | ||
|  | eefb1c4a47 | ||
|  | 069015c9b1 | ||
|  | c1583d19fb | ||
|  | 0556433ce4 | ||
|  | ec072cee23 | ||
|  | e29e6c147c | ||
|  | 972721b183 | ||
|  | 9bf43ce80d | ||
|  | 5941b5c07e | ||
|  | 3d91a186d5 | ||
|  | 744d45fb04 | ||
|  | f76fdedd25 | ||
|  | 93ca07d812 | ||
|  | d69042daee | ||
|  | d9f515900c | ||
|  | 57b4a5be08 | ||
|  | fa347f5f75 | ||
|  | 35e3404ced | ||
|  | f7344ec6c9 | ||
|  | 63a1e560ee | ||
|  | 98463f8258 | ||
|  | 2c95bfa701 | ||
|  | 2de3a2c98e | ||
|  | 314c0c9e3f | ||
|  | 4377627332 | ||
|  | 71d3f452ed | ||
|  | e117222dc2 | ||
|  | 6286daa881 | ||
|  | 0b3b9af623 | ||
|  | 1492f5611e | ||
|  | efeffaa49f | ||
|  | d77112955d | ||
|  | 9a34bb7e7a | ||
|  | b30445a5f3 | ||
|  | 0bf5c6ee3d | ||
|  | 155480b335 | ||
|  | 34202dea1d | ||
|  | 38d58f0354 | ||
|  | d4b82a33c5 | ||
|  | 06f3463dbc | ||
|  | 9df2d86ac2 | ||
|  | c83d93971f | ||
|  | 7e3ba3c27f | ||
|  | c7043dffc2 | ||
|  | d2c1e30979 | ||
|  | d5679c372f | ||
|  | b33f8b70d4 | ||
|  | d5773ab5d0 | ||
|  | 1903292202 | ||
|  | c3a9415208 | ||
|  | 9ece209c72 | ||
|  | 03956af88a | ||
|  | 013c8707ac | ||
|  | 32ed9c59ea | ||
|  | 4ef663669c | ||
|  | b855c54e81 | ||
|  | 8b65c8b909 | ||
|  | 28e7440726 | ||
|  | 7bca2298a0 | ||
|  | b1cc17d96e | ||
|  | 2afbef63aa | ||
|  | f0d2caec67 | ||
|  | ac2a317fd2 | ||
|  | bc4ac303e2 | ||
|  | 0e9fbecbe4 | ||
|  | 226b3cfdd8 | ||
|  | d43fa3790d | ||
|  | ca04113aa7 | ||
|  | 817c157db4 | ||
|  | 07edbe758a | ||
|  | 46ba0a5a5a | ||
|  | 480b636c7e | ||
|  | 20340dff7b | ||
|  | cfbabb500f | ||
|  | a4cb2c1cb1 | ||
|  | bd31b7e943 | ||
|  | b2e7c767df | ||
|  | bb9f763729 | ||
|  | fb61229bf3 | ||
|  | fc30d41ee5 | ||
|  | 7666147f3c | ||
|  | 52f8b24041 | ||
|  | eaf2667abb | ||
|  | de754ca4e0 | ||
|  | 96dd89fbeb | ||
|  | bae40e2cbc | ||
|  | 6a647dab8b | ||
|  | ebcf5b71d2 | ||
|  | 02370fb65d | ||
|  | 1e4f4907e3 | ||
|  | 13f72c73fb | ||
|  | 69b4632ef6 | ||
|  | ede8c293fc | ||
|  | 0cfe991482 | ||
|  | 6377459e2f | ||
|  | 33fe6dbfa3 | ||
|  | e158b9b64e | ||
|  | dfa9e537b3 | ||
|  | 6d28ece616 | ||
|  | 59f4ecdaa6 | ||
|  | 10d953f336 | ||
|  | 5b771f7def | ||
|  | 4a8e3ee845 | ||
|  | 9a1f559dd2 | ||
|  | 62321a03ca | ||
|  | 40ca72c656 | ||
|  | 34fcff7a9d | ||
|  | e1c829f4fa | ||
|  | 46136d94e9 | ||
|  | 0e2e8d1be5 | ||
|  | 1d1aa5dd3a | ||
|  | 0d82589916 | ||
|  | 4fc13037d2 | ||
|  | 3764499714 | ||
|  | c4bbbc49b4 | ||
|  | 503158ab97 | ||
|  | 8c1d1d1db0 | ||
|  | 7dc72a2894 | ||
|  | 07cfba1b3a | ||
|  | c55b80f467 | ||
|  | 2099da7142 | ||
|  | ea125936e7 | ||
|  | 5de01628a6 | ||
|  | 2834aca597 | ||
|  | 88bab888d8 | ||
|  | dfdbace298 | ||
|  | a9590d2bb6 | ||
|  | 29a81eb05e | ||
|  | 20490fcd80 | ||
|  | e775927f60 | ||
|  | 835a421909 | ||
|  | 850a0ae17e | ||
|  | 2b54363dd7 | ||
|  | b174a06b86 | ||
|  | d4096103cb | ||
|  | 3f493aceb2 | ||
|  | 05309da76d | ||
|  | 179f720806 | ||
|  | 7c34144ccd | ||
|  | cc234b594d | ||
|  | 024cf610a8 | ||
|  | a1896a6336 | ||
|  | d30da7bf5d | ||
|  | f8e914416d | ||
|  | 433da921bb | ||
|  | 4876053018 | ||
|  | 0c3a580b33 | ||
|  | 7689b7b4b0 | ||
|  | 21bff39e31 | ||
|  | ba09901228 | ||
|  | 90bf2e58b2 | ||
|  | 004807aa32 | ||
|  | 35bacf2ad0 | ||
|  | 81d17409d4 | ||
|  | a8080f55f0 | ||
|  | 379c540bd8 | ||
|  | f319005357 | ||
|  | df0e2dd2a2 | ||
|  | 219a0cd612 | ||
|  | 3ca3ce0726 | ||
|  | 566be8dc63 | ||
|  | 6bd4fa1c0a | ||
|  | c767ee04f4 | ||
|  | a5f89e0967 | ||
|  | 7355d14159 | ||
|  | efd5ceb405 | ||
|  | 035dc8ceb4 | ||
|  | 11be33e942 | ||
|  | e125254687 | ||
|  | a2b997ba20 | ||
|  | 7327941c77 | ||
|  | 6c9eb1b699 | ||
|  | 60e262dece | ||
|  | 9c5463e515 | ||
|  | 6941176519 | ||
|  | cb2c52cddb | ||
|  | dd95776144 | ||
|  | b95ca98be9 | ||
|  | 67b090b4d8 | ||
|  | 54b76a03ce | ||
|  | cd6c727730 | ||
|  | a35c6e29b6 | ||
|  | 95ce72fce7 | ||
|  | a803dfc7fa | ||
|  | c465d1c059 | ||
|  | 9914c0791e | ||
|  | 96baf5d3c7 | ||
|  | a205367b62 | ||
|  | 6218fa90de | ||
|  | 51a770cfdc | ||
|  | 16fba15b5c | ||
|  | ec2463a3ba | ||
|  | b605ede74e | ||
|  | b1b13d3696 | ||
|  | 51b11e5188 | ||
|  | eefa84a77b | ||
|  | 5908b4b000 | ||
|  | 2ed433c96d | ||
|  | 9865800e39 | ||
|  | 4f697e77d5 | ||
|  | c957aded98 | ||
|  | aa0758cd2b | ||
|  | 0c2093753d | ||
|  | 136f983353 | ||
|  | 7943164375 | ||
|  | 32e58d0a60 | ||
|  | bc807965ab | ||
|  | 477788658b | ||
|  | 723abf44bd | ||
|  | fd1298d4d2 | ||
|  | 42f39536a1 | ||
|  | 6f0ac91bd2 | ||
|  | 6dea9156ab | ||
|  | c5051b3e46 | ||
|  | 229d033e1a | ||
|  | f494ba7065 | ||
|  | 201bc7db53 | ||
|  | cd2a251f22 | ||
|  | ff44ad4994 | ||
|  | b496ca6a2c | ||
|  | 5908c0ce8c | ||
|  | f7eef25fed | ||
|  | 049c93465a | ||
|  | 33294dd9f0 | ||
|  | 0a89f4000d | ||
|  | 422e80530b | ||
|  | 07a8c69ba8 | ||
|  | 5449879a7d | ||
|  | 8dbc846314 | ||
|  | f0d3ca5d53 | ||
|  | 5af026674f | ||
|  | 2ebb4778cd | ||
|  | bf3c57d26b | ||
|  | cb9c87102f | ||
|  | c73b003de4 | ||
|  | 771d448a7b | ||
|  | de12db5f05 | ||
|  | dd49926cc2 | ||
|  | 7a9ab190eb | ||
|  | 2290fcde22 | ||
|  | ae85876965 | ||
|  | f07d8e958f | ||
|  | 610af45dee | ||
|  | 138a5bc3fe | ||
|  | 427e9c5637 | ||
|  | e3e8336602 | ||
|  | 194073e49a | ||
|  | 1af45aff73 | ||
|  | 56518ea028 | ||
|  | c1ac2bb156 | ||
|  | a004f27361 | ||
|  | 7843c55409 | ||
|  | 41da7d9f9a | ||
|  | 2add644706 | ||
|  | dfd9cf0874 | ||
|  | 7ad09da4e9 | ||
|  | 8efbeb14d2 | ||
|  | a1005d91df | ||
|  | a681f1ce3c | ||
|  | 5a0714ca1a | ||
|  | bd5c790043 | ||
|  | 2ae3cf79e4 | ||
|  | fb122ba097 | ||
|  | 0c104cd86c | ||
|  | a687f4ad68 | ||
|  | 228f42cf04 | ||
|  | 6d4956b574 | ||
|  | 0c7b652a70 | ||
|  | d35470a79e | ||
|  | 719d610be3 | ||
|  | 07ae64693e | ||
|  | 0ccc1271a6 | ||
|  | 26fa2b0b74 | ||
|  | 6f64c19c32 | ||
|  | e3e0e12fef | ||
|  | 0312ba8ad7 | ||
|  | 2ad8e7f343 | ||
|  | d6298d9f05 | ||
|  | 89be30c4b9 | ||
|  | 6bcfea1de4 | ||
|  | e8c9554dd6 | ||
|  | 02272f7db0 | ||
|  | 5a73e79475 | ||
|  | 7f4ecd40ce | ||
|  | 7c950c3022 | ||
|  | dbf019135a | ||
|  | e504ee82e5 | ||
|  | 780a15fe4f | ||
|  | abb249643f | ||
|  | 086eccaf4a | ||
|  | 871033501a | ||
|  | ccd727488f | ||
|  | aa59d0f082 | ||
|  | 5d12f53283 | ||
|  | 59c005875a | ||
|  | 06d22e843a | ||
|  | 4fa5f4e5a3 | ||
|  | 67ea825d4a | ||
|  | a616e06f9d | ||
|  | b7752928a4 | ||
|  | ca096852a5 | ||
|  | ea2c48bca5 | ||
|  | a722dc4235 | ||
|  | dbbf0ff5e4 | ||
|  | a941519db5 | ||
|  | d4ba014a8a | ||
|  | d193a6aec4 | ||
|  | 1f0fdf3da7 | ||
|  | b705240faa | ||
|  | 662b832274 | ||
|  | aed7e6d289 | ||
|  | f7a1201d02 | ||
|  | 4d5bdd25a8 | ||
|  | 4a90ce35f2 | ||
|  | 02f5eddd14 | ||
|  | 5ca4f1b181 | ||
|  | ec7ef3a813 | ||
|  | 49ff6febe5 | ||
|  | 2d66a9212f | ||
|  | 44fb307da4 | ||
|  | cfc2181a48 | ||
|  | cf4a846312 | ||
|  | 633b357d7b | ||
|  | b96d67a54e | ||
|  | 5b83931b01 | ||
|  | f22b54de30 | ||
|  | a3306bb26f | ||
|  | 0adacac269 | ||
|  | 7359ed2ba2 | ||
|  | 5a5f4e8161 | ||
|  | b886cc1333 | ||
|  | 9299efd086 | ||
|  | 1502aa3b20 | ||
|  | 73e32ecdcb | ||
|  | ac8776aea4 | ||
|  | 7b41c5b301 | ||
|  | 369839e012 | ||
|  | 8fde16422e | ||
|  | f1462dbd3d | ||
|  | 5dad569d62 | ||
|  | c424bb097d | ||
|  | e4b1760b20 | ||
|  | 780e365a78 | ||
|  | 3d1523a060 | ||
|  | ff403dfa2e | ||
|  | 89834baf01 | ||
|  | b8699422c8 | ||
|  | 6bc772d640 | ||
|  | 0712f30a51 | ||
|  | 9116796d90 | ||
|  | a95fdb903b | ||
|  | 2ca6421206 | ||
|  | cd076cc069 | ||
|  | 46482bdae1 | ||
|  | 5189c897be | ||
|  | 2c7d25d472 | ||
|  | 0da370c42d | ||
|  | 6f036d9120 | ||
|  | 260bbd79fd | ||
|  | 37ad6a3a62 | ||
|  | aa25007431 | ||
|  | 8b33ec1339 | ||
|  | cede11ecea | ||
|  | 2b4088c5f7 | ||
|  | d872484607 | ||
|  | f3f2160d96 | ||
|  | bcdb849b46 | ||
|  | 5846431b34 | ||
|  | 0217d9396a | ||
|  | c99e233026 | ||
|  | f670d930f3 | ||
|  | 0237d78f61 | ||
|  | 5665f127aa | ||
|  | 76386dad7d | ||
|  | 42072fdda4 | ||
|  | fc80f828be | ||
|  | d05a1e0260 | ||
|  | b315882f58 | ||
|  | 2f2f907ffe | ||
|  | 10492e3b2f | ||
|  | 8e08ff2d39 | ||
|  | e78a59a8a8 | ||
|  | cbe47a9dcc | ||
|  | a1056147d8 | ||
|  | 8692590600 | ||
|  | 57345113b5 | ||
|  | 52f02cb9eb | ||
|  | 5d4dcd7e4b | ||
|  | 7d1f4d8907 | ||
|  | a76241c7ba | ||
|  | bdc6678341 | ||
|  | c99b7e927d | ||
|  | 1675a0d442 | ||
|  | c0d2cd8962 | ||
|  | 146c9fd947 | ||
|  | 666e9897ea | ||
|  | 81d70bd811 | ||
|  | f6f8bb7fd1 | ||
|  | 7c3aaf7b7c | ||
|  | 32ea28f783 | ||
|  | 17f365941b | ||
|  | c2216843d8 | ||
|  | 339fb5099f | ||
|  | cf56707b02 | ||
|  | 19f38aa6ed | ||
|  | 9f69e112d0 | ||
|  | 8eb4259be0 | ||
|  | d3a1f43cbb | ||
|  | 18b06ff283 | ||
|  | 53addcf99a | ||
|  | 0fa4d75a47 | ||
|  | 2ef86c3339 | ||
|  | d48c3a6d2f | ||
|  | 2260ede559 | ||
|  | 5690a44c38 | ||
|  | e36a9fda1b | ||
|  | 10f195d334 | ||
|  | 54afc6ca8c | ||
|  | 2e67bd3b78 | ||
|  | f27eb084c7 | ||
|  | 7629dfd54a | ||
|  | f62fd18b72 | ||
|  | c6b60ff6b4 | ||
|  | e9655e6d86 | ||
|  | 3bca9b06f8 | ||
|  | d97fdc3393 | ||
|  | 7dc72f98bf | ||
|  | da00179066 | ||
|  | 89910031cd | ||
|  | 5676aeac80 | ||
|  | b0b9055e2e | ||
|  | c0aefed764 | ||
|  | e2ec9ca5fb | ||
|  | 8e38f5c2c0 | ||
|  | 99b2858863 | ||
|  | b43669e731 | ||
|  | 3bc9905715 | ||
|  | c55aebd005 | ||
|  | 55c331f536 | ||
|  | ce236284f4 | ||
|  | c24cac68f6 | ||
|  | db149ca6e1 | ||
|  | 0502f2a4a5 | ||
|  | f13df7e605 | ||
|  | 36a6981329 | ||
|  | 7abcdea816 | ||
|  | 0509e54a95 | ||
|  | b8893bcad7 | ||
|  | c9356c1237 | ||
|  | 2d7b7c2f3f | ||
|  | d0db1117f7 | ||
|  | e287e76db5 | ||
|  | 8c28c4b5ac | ||
|  | f048e943f8 | ||
|  | 12a84572e2 | ||
|  | c8de1d3372 | ||
|  | 234e3f4ca5 | ||
|  | 7749fb1a0b | ||
|  | f55d4e32c0 | ||
|  | cfd98a33fe | ||
|  | 7bdf20fee5 | ||
|  | e906fa3653 | ||
|  | 57cf7f6f0d | ||
|  | d378e7e897 | ||
|  | a8e666db34 | ||
|  | 7b46339a5d | ||
|  | 20aa6e429b | ||
|  | 7ba11a57a8 | ||
|  | 49de4f2200 | ||
|  | 5d01955133 | ||
|  | 7591f3fa29 | ||
|  | 89f8f9b45b | ||
|  | 59f5b38dca | ||
|  | 5b0e61033c | ||
|  | 096af00a72 | ||
|  | dca2dc4600 | ||
|  | 96b482dac5 | ||
|  | e05664f34f | ||
|  | 72cca5ccbf | ||
|  | 0b9be029ac | ||
|  | 91701473af | ||
|  | ad6a9a7df7 | ||
|  | 32b6ded008 | ||
|  | 4f2d0a0322 | ||
|  | 793cfcb2c5 | ||
|  | 3a71bd01fb | ||
|  | a1d99c1954 | ||
|  | 19a874b274 | ||
|  | b95dd5c238 | ||
|  | 7c84af2370 | ||
|  | db1c27d833 | ||
|  | 636cd84f4f | ||
|  | f2d4fae813 | ||
|  | 986c9ab20a | ||
|  | cd7e222b72 | ||
|  | 50b599b1a9 | ||
|  | 1d162edb59 | ||
|  | 7bdd4ddeab | ||
|  | ae6e5a5599 | ||
|  | 1222184b68 | ||
|  | 18f779c6de | ||
|  | 138f67581c | ||
|  | 597d6ac513 | ||
|  | 3ab25c2e8c | ||
|  | b11d97ba4e | ||
|  | 080c810131 | ||
|  | 56bc79d64e | ||
|  | 72d2c9d600 | ||
|  | 0374c32236 | ||
|  | d73cd4b515 | ||
|  | 54e3e3f051 | ||
|  | abf218fc21 | ||
|  | dcf90b6159 | ||
|  | 1cf91c78f8 | ||
|  | 968abd26e8 | ||
|  | aa05f7a2d2 | ||
|  | 181c23b07c | ||
|  | 955cde3ed9 | ||
|  | 477a3c7eb2 | ||
|  | f4b66b980b | ||
|  | 281de63e0d | ||
|  | c19a700662 | ||
|  | fc011ba1d9 | ||
|  | b941f590e0 | ||
|  | 8f4db78ff2 | ||
|  | 4b4dc2e298 | ||
|  | 2de19547ca | ||
|  | 5a058491b0 | ||
|  | 6743d99d9b | ||
|  | 35a5ec78c3 | ||
|  | 3440c3e77a | ||
|  | dd17f06362 | ||
|  | 8a15cb3a34 | ||
|  | 4a548ac282 | ||
|  | d22353b13d | ||
|  | c18046c25d | ||
|  | 4a12d4d156 | ||
|  | 20044427b4 | ||
|  | 073dedd483 | ||
|  | 06c25c913c | ||
|  | 08d06cf465 | ||
|  | 1e9eb843c0 | ||
|  | 78a5dae2a0 | ||
|  | 19443a5b34 | ||
|  | 74acc90702 | ||
|  | 349f580371 | ||
|  | f019d33a03 | ||
|  | c7af25ac38 | ||
|  | b52bd59cea | ||
|  | 332d32c319 | ||
|  | 2f824ba1a8 | ||
|  | a6b09acd5e | ||
|  | d4779c8c8f | ||
|  | ba01c4bbe8 | ||
|  | ddc1d81665 | ||
|  | 790aeb3c46 | ||
|  | 6ed5be10b1 | ||
|  | a7b8470d9e | ||
|  | 2a05cc382f | ||
|  | 1e10a6ce1b | ||
|  | 7645ef55c2 | ||
|  | 6ce200b60d | ||
|  | d782e28906 | ||
|  | da3bd31fb8 | ||
|  | aa3ed40430 | ||
|  | ad7e564f14 | ||
|  | f23ee2dac5 | ||
|  | 1962f74439 | ||
|  | 0064d060ea | ||
|  | e47e6b1958 | ||
|  | 4c04415e80 | ||
|  | 3654e75b8c | ||
|  | 66fa73aea4 | ||
|  | df87d03f32 | ||
|  | 3fbe851a0b | ||
|  | d1b2e63950 | ||
|  | 34fd8cf751 | ||
|  | f1fe90fce0 | ||
|  | 2ba6fa0dda | ||
|  | f2928e3d7d | ||
|  | 895ab9c5d8 | ||
|  | fb07c68132 | ||
|  | 68e7d45f63 | ||
|  | 49e302e1bc | ||
|  | b33ca786ae | ||
|  | dc77d8edda | ||
|  | c339a183b9 | ||
|  | f263795a99 | ||
|  | e9e771e57b | ||
|  | fbb9d7c6b4 | ||
|  | 10abd7b0ae | ||
|  | 3de36901b8 | ||
|  | 5b4967acb9 | ||
|  | 0a007b1e6e | ||
|  | 4ad68b7dfa | ||
|  | 73aef1b9a4 | ||
|  | dcfea20973 | ||
|  | 9b6766d3b2 | ||
|  | b8bc8e2c47 | ||
|  | 039e3aa34c | ||
|  | 551ff109c9 | ||
|  | 664451d0c6 | ||
|  | 4031057bc0 | ||
|  | fcf9b782c1 | ||
|  | d693d382b9 | ||
|  | 0a1b6c7793 | ||
|  | 5acba2bddf | ||
|  | 883b16fad1 | ||
|  | ef48b3e751 | ||
|  | 3c956e7e98 | ||
|  | 519ea271a9 | ||
|  | 09d5160404 | ||
|  | 97dcf03334 | ||
|  | 896a804a72 | ||
|  | 656bb5043d | ||
|  | e953becbae | ||
|  | 6c9901b919 | ||
|  | ff45c94106 | ||
|  | a8a3fbeef4 | ||
|  | dae8092ecd | ||
|  | 70110208fc | ||
|  | 217ca98933 | ||
|  | c2945c532e | ||
|  | ea750576b3 | ||
|  | 82538ba4fc | ||
|  | 2b2f37a8c9 | ||
|  | 4db2ec60e0 | ||
|  | 7d88d35556 | ||
|  | 3c3e91ff48 | ||
|  | 039e8d6e17 | ||
|  | 50bf79ab18 | ||
|  | 467c6762fa | ||
|  | 740f4e403f | ||
|  | 5664d51695 | ||
|  | b195a61498 | ||
|  | 94e6816bf6 | ||
|  | ebf97f710f | ||
|  | 714b54ed06 | ||
|  | 620c5f515e | ||
|  | c06fd12b07 | ||
|  | 2c206bba64 | ||
|  | 04953b5645 | ||
|  | 1732ce63f3 | ||
|  | 1e212c6da2 | ||
|  | 7d8fc54351 | ||
|  | dd44a1e517 | ||
|  | 9f26757e8a | ||
|  | a9c8c8384d | ||
|  | a826b0e0fb | ||
|  | 4aaec0e379 | ||
|  | 69019d5215 | ||
|  | 96411b17e9 | ||
|  | 5a093b58d8 | ||
|  | 470b3e0973 | ||
|  | dc251c216c | ||
|  | ae9ef61f80 | ||
|  | d9ca7b7277 | ||
|  | 0c99248deb | ||
|  | 1aae84a4d0 | ||
|  | 528da3f08e | ||
|  | 9c507f7f62 | ||
|  | 07da2fdda3 | ||
|  | ca3366544e | ||
|  | ccee7b483c | ||
|  | 5903133e3b | ||
|  | 5bf520b6ed | ||
|  | a47da92d81 | ||
|  | 63f84ae7b1 | ||
|  | 4d6bc55723 | ||
|  | 9bb4df4cc3 | ||
|  | c47a5379ae | ||
|  | cde9c4a2bc | ||
|  | 5a560b42ef | ||
|  | 50874c9cf7 | ||
|  | 6f984aa591 | ||
|  | 274162afcd | ||
|  | 6bd23d897f | ||
|  | 73f29ebf69 | ||
|  | cabcb9c6d0 | ||
|  | 116f7ed613 | ||
|  | 6ef0eb73d0 | ||
|  | 7f4feb0cfc | ||
|  | 626f7357bb | ||
|  | 690c9203c8 | ||
|  | 1209f3b39a | ||
|  | a4524b3c2c | ||
|  | a3cbdadb39 | ||
|  | 9e3c5fd984 | ||
|  | 7d80ac37a6 | ||
|  | f74b9ba7ab | ||
|  | 3ac240dc1c | ||
|  | d233b3f24f | ||
|  | 19fff681d2 | ||
|  | bc7c3bb9b3 | ||
|  | 57be7f2905 | ||
|  | 1c0da454db | ||
|  | b541f7b944 | ||
|  | 6e84326583 | ||
|  | ca14496e4e | ||
|  | 480d65fc1f | ||
|  | 6bddb63b45 | ||
|  | c5142aeba5 | ||
|  | 38d9f10672 | ||
|  | 937394af7a | ||
|  | fe10955eb9 | ||
|  | ccda71ff8e | ||
|  | cd75224cdd | ||
|  | 1c2089b8a3 | ||
|  | 3ead4d4587 | ||
|  | f2b71bc280 | ||
|  | f027d71136 | ||
|  | fa41d6df04 | ||
|  | d2bb65bf04 | ||
|  | b5be1b11d1 | ||
|  | 9fb049991f | ||
|  | fba847dd28 | ||
|  | b33883b334 | ||
|  | f74a6dffca | ||
|  | 7390e20218 | ||
|  | 9646dc439e | ||
|  | 554c63b9c7 | ||
|  | 24d8640e9b | ||
|  | ea151d069c | ||
|  | f140d2f37a | ||
|  | 4e163c4bda | ||
|  | ddcf8b892b | ||
|  | 49138eb03a | ||
|  | 71b63bd33b | ||
|  | 88348f59c2 | ||
|  | 7eb5643204 | ||
|  | 565cb6d79e | ||
|  | c0d715c78a | ||
|  | a3d0355ddd | ||
|  | bc4e06568d | ||
|  | 8acb9f4056 | ||
|  | 9cbbd581ee | ||
|  | fdc9467218 | ||
|  | 84ac3df580 | ||
|  | 7f459df9e9 | ||
|  | 3625f3293a | ||
|  | 0a2308592f | ||
|  | 8ef3f18da7 | ||
|  | e126427809 | ||
|  | 7b39828980 | ||
|  | d03de52735 | ||
|  | cabe90b2dd | ||
|  | 13b78bdc20 | ||
|  | 6f0e1c79ac | ||
|  | b66daad3d3 | ||
|  | 9c5523252d | ||
|  | bc8bcf7a1a | ||
|  | 85d655d3e2 | ||
|  | ac419e01d3 | ||
|  | 5d4467a6c0 | ||
|  | 81da7f3667 | ||
|  | 9734196eb9 | ||
|  | 7e0f9b9b8e | ||
|  | bb25132865 | ||
|  | 28bcff99f6 | ||
|  | 246cb36836 | ||
|  | 9a0c0f6d21 | ||
|  | a9dd8eb9e7 | ||
|  | 9026c9d6f1 | ||
|  | d5f7430723 | ||
|  | 5a53249fbb | ||
|  | d2848cf569 | ||
|  | 71f39f55f2 | ||
|  | 490c817fc1 | ||
|  | 2e1a777811 | ||
|  | 48357d1cc9 | ||
|  | 846df21764 | ||
|  | f78b8f9267 | ||
|  | 798d9ee876 | ||
|  | 1eea81e9dd | ||
|  | 4fcdfd41fa | ||
|  | 36a5f17af2 | ||
|  | 8032684ad0 | ||
|  | f7d3d4a010 | ||
|  | 9975e0b3f3 | ||
|  | ea484a7787 | ||
|  | c2e8a67330 | ||
|  | 8f3e4a2dee | ||
|  | 07768a43c8 | ||
|  | 01c10e320c | ||
|  | f16b2257c6 | ||
|  | e005fe7ce1 | ||
|  | c682e69ee7 | ||
|  | 49421f50ac | ||
|  | 529dd490b7 | ||
|  | 36329e596e | ||
|  | fb75e2ef02 | ||
|  | 352171e339 | ||
|  | 592901b143 | ||
|  | 769b4819b2 | ||
|  | 77fa2bcc39 | ||
|  | 1129001bc6 | ||
|  | 8dd765ee89 | ||
|  | 479648e7c1 | ||
|  | 45cd19d1e3 | ||
|  | f8718e0b7b | ||
|  | dcc45631da | ||
|  | c6d3a5bedc | ||
|  | 7cc8539298 | ||
|  | 900e8202e6 | ||
|  | eb6ac7d1d1 | ||
|  | 178f917a49 | ||
|  | 1a8293d9ef | ||
|  | ecdc00dcb7 | ||
|  | 147e04ecd2 | ||
|  | 49e48725a5 | ||
|  | b3af744041 | ||
|  | 58a6a95d90 | ||
|  | 1aa9461370 | ||
|  | 1f78b9d4bc | ||
|  | 6f974fe285 | ||
|  | f4f3c8798e | ||
|  | ce1614f4e7 | ||
|  | 91494584c2 | ||
|  | a85ebb49b2 | ||
|  | ae273f8320 | ||
|  | ef62e31b61 | ||
|  | 0c2c5d5344 | ||
|  | 11e93eac3d | ||
|  | dbe17debb4 | ||
|  | 6c12337317 | ||
|  | b2aa73b31e | ||
|  | 38b1fc7aa6 | ||
|  | f4afcb4d50 | ||
|  | 4b019fe38b | ||
|  | 191401f32b | ||
|  | 62b68c6a21 | ||
|  | 15a22f0bfc | ||
|  | 926c03986c | ||
|  | d8a00f4314 | ||
|  | 5862b832d9 | ||
|  | 67fa4a0fc7 | ||
|  | 90cf7a3bf5 | ||
|  | 0847040017 | ||
|  | 69b577048e | ||
|  | 3fbd2f93c8 | ||
|  | 8f0e36a8e4 | ||
|  | 7583698ee5 | ||
|  | b561e79a6c | ||
|  | 5850ad06b1 | ||
|  | e597f04b0d | ||
|  | 7b715925cf | ||
|  | d3701837e3 | ||
|  | 7af10aca9e | ||
|  | b54e99642b | ||
|  | b1ad0668cc | ||
|  | 6583d0f69b | ||
|  | cee6bbf134 | ||
|  | 43e49bf14a | ||
|  | 371b58a807 | ||
|  | 7812a1bb51 | ||
|  | 538e045e4c | ||
|  | 91fe1493a7 | ||
|  | 4650a2ea52 | ||
|  | 7cd51a7747 | ||
|  | b55545b959 | ||
|  | 2685256c93 | ||
|  | 3819de4e74 | ||
|  | 73fee4eb6b | ||
|  | 609c193b88 | ||
|  | 03a42976b1 | ||
|  | 6db0efdfbc | ||
|  | ebbbe1a620 | ||
|  | 5d1c77cb16 | ||
|  | d48fb3ba55 | ||
|  | 8c024a1ae9 | ||
|  | a3c34e6b3c | ||
|  | fa7ab45a40 | ||
|  | 379b104778 | ||
|  | d956c795a4 | ||
|  | 7d02d0f762 | ||
|  | f96f38b172 | ||
|  | 4cea5d65a6 | ||
|  | 40d94e7a62 | ||
|  | 66019fdbbf | ||
|  | 37b02e3d5b | ||
|  | 093bdd6090 | ||
|  | 52656b25da | ||
|  | 1386c9d915 | ||
|  | 02c9441727 | ||
|  | b1e926f2cb | ||
|  | df9dcb395b | ||
|  | ad59dad921 | ||
|  | 46e75968f5 | ||
|  | 0df5c5121d | ||
|  | 16f04b45ac | ||
|  | 5ce35a50c2 | ||
|  | 7110c1178a | ||
|  | 220f5e2913 | ||
|  | 9f8c75efc6 | ||
|  | 8f3e84df4d | ||
|  | 08ff3d8ad0 | ||
|  | 5c4d7734ac | ||
|  | 15f8cd49d3 | ||
|  | 62b3986fcd | ||
|  | 55b6d711f3 | ||
|  | 7e51d57d21 | ||
|  | 170d23d768 | ||
|  | 40266c6821 | ||
|  | 0a71077513 | ||
|  | be5c44af61 | ||
|  | 720dcb0fe5 | ||
|  | c86b207b1c | ||
|  | 413c1bc2fe | ||
|  | 5ca31ea3dd | ||
|  | dd5d2d1616 | ||
|  | 5f08790f12 | ||
|  | d5ef5ee5a7 | ||
|  | f641c70172 | ||
|  | 992657b942 | ||
|  | 41e468b507 | ||
|  | 6660306ac4 | ||
|  | dd9694890a | ||
|  | 0b8654d865 | ||
|  | f07dc7bd81 | ||
|  | 6a6482dc7f | ||
|  | 3c9b7c07af | ||
|  | 796ab4bf2c | ||
|  | 55602d632d | ||
|  | 310ed9f504 | ||
|  | dafddfa39a | ||
|  | 3e22c9860e | ||
|  | fb0a0c3fb5 | ||
|  | 3b735c7533 | ||
|  | 1645490f5c | ||
|  | aecffe10d9 | ||
|  | 4e69bc0e32 | ||
|  | 909f72e6be | ||
|  | 6a1d39d5f8 | ||
|  | c5d4ec17c3 | ||
|  | ed33a72945 | ||
|  | d8c0091680 | ||
|  | 6419d68626 | ||
|  | e2ecaf5bcf | ||
|  | 31146954d1 | ||
|  | 601ca9ec80 | ||
|  | 082b5ba895 | ||
|  | e06361d5d7 | ||
|  | 552a8e130c | ||
|  | 40787bc29a | ||
|  | 6ab03bb228 | ||
|  | 3fdb782321 | ||
|  | c8f52a1c40 | ||
|  | eb63090387 | ||
|  | 5bc8f31c31 | ||
|  | 5776de7745 | ||
|  | f45d0bb317 | ||
|  | 93aa5b7753 | ||
|  | dd6a6a565f | ||
|  | aba8025645 | ||
|  | b12872e5de | ||
|  | 5a7b1ba292 | ||
|  | 24715c72a2 | ||
|  | ed3a4e4663 | ||
|  | e97283b34b | ||
|  | c2dfbcba10 | ||
|  | a9870b35be | ||
|  | ed5cd2b9ca | ||
|  | a9356ca1e2 | ||
|  | cfba11e9ca | ||
|  | 4304a3c916 | ||
|  | 9e6194bfdc | ||
|  | 7d6c8aa9dc | ||
|  | aad0864018 | ||
|  | a55d18709c | ||
|  | dd2f3c861b | ||
|  | da1dc67e1c | ||
|  | 0c2b35e542 | ||
|  | 85dc1263ea | ||
|  | c8ecb3e0ee | ||
|  | ce10036a27 | ||
|  | 30e49846e0 | ||
|  | be97dd1c57 | ||
|  | 648a6dca42 | ||
|  | 0566d0d198 | ||
|  | dfc25722c9 | ||
|  | a436c55c50 | ||
|  | 0d58530f55 | ||
|  | 04b2eaf535 | ||
|  | ace2ed8bd0 | ||
|  | dff2d716a1 | ||
|  | ad18b9b81b | ||
|  | eabfe0769b | ||
|  | 19f7027718 | ||
|  | f537945351 | ||
|  | d02372ab90 | ||
|  | 1b020c522f | ||
|  | 79d0450c77 | ||
|  | bc32bc8831 | ||
|  | f68a307eeb | ||
|  | 82e7479cfe | ||
|  | 462fe5d89f | ||
|  | b0d8ac83ae | ||
|  | d8ac817c91 | ||
|  | 5105bc6f64 | ||
|  | 47c9f1e9b8 | ||
|  | 49d0ed0c1b | ||
|  | 99f5151aab | ||
|  | 0a056ad02d | ||
|  | c76b634d0b | ||
|  | a81698d50f | ||
|  | bae79063e1 | ||
|  | fb5323c283 | ||
|  | e2d1de94b7 | ||
|  | 7109fd8196 | ||
|  | a5fd821e0c | ||
|  | 6c63583e49 | ||
|  | dd16e1b784 | ||
|  | d52d8d7970 | ||
|  | f349aa47ce | ||
|  | ef4018934c | ||
|  | 951aa9535e | ||
|  | de1fe36226 | ||
|  | 64fd36d437 | ||
|  | 6f9ecc0ffa | ||
|  | a97bfc92e1 | ||
|  | 0d72fcdf02 | ||
|  | 0e84ca1df5 | ||
|  | b28bdda510 | ||
|  | 72314e2d9f | ||
|  | d22fb9f438 | ||
|  | 04b8552d27 | ||
|  | 5d6f44cd91 | ||
|  | afc8ad7ff5 | ||
|  | ae039bf1c7 | ||
|  | 8fa25e9d37 | ||
|  | 0daab491ec | ||
|  | 4f825bac1a | ||
|  | 39c8b79ebb | ||
|  | 7d66c90beb | ||
|  | 1b8b65582a | ||
|  | d25971cb44 | ||
|  | 89a56e661d | ||
|  | 3482746d7c | ||
|  | d5aeca6222 | ||
|  | 03f46638e1 | ||
|  | c2b000d910 | ||
|  | 88eb702d7b | ||
|  | b1d98f026f | ||
|  | 28dfe7b02c | ||
|  | 84f0ee183c | ||
|  | 7eedd6c2fc | ||
|  | e7b80c6d10 | ||
|  | d165609476 | ||
|  | 2f17521c06 | ||
|  | 8b52006959 | ||
|  | 8eb3d43123 | ||
|  | a511368229 | ||
|  | f0006a0743 | ||
|  | 7171e69715 | ||
|  | 2ab44fb33a | ||
|  | 7542175258 | ||
|  | 9dc4c50527 | ||
|  | 99d116f4ce | ||
|  | 9475fef8f6 | ||
|  | 60339a0f6a | ||
|  | 36113f84be | ||
|  | 139c2284b8 | ||
|  | 91909a70d7 | ||
|  | a23d97563f | ||
|  | bf538e2514 | ||
|  | 149b62f486 | ||
|  | 06dc8a499b | ||
|  | 5b8479f3a4 | ||
|  | e803a5e26e | ||
|  | 959f798a7f | ||
|  | 5b8adbfd0c | ||
|  | 54ba18975a | ||
|  | fdd2dedfc6 | ||
|  | 46f4fa1a7d | ||
|  | 28debb46be | ||
|  | 5f132be94d | ||
|  | 9f9feea159 | ||
|  | 3bd9e0bcd4 | ||
|  | c80a76f8c0 | ||
|  | c71f498587 | ||
|  | e658d447ca | ||
|  | 33def5b45d | ||
|  | 9fc26a8ee0 | ||
|  | 1b304bf85e | ||
|  | 99983a5c8f | ||
|  | d01b370cd7 | ||
|  | 1a643e2042 | ||
|  | 1aaf5fd288 | ||
|  | 8a758b8df0 | ||
|  | 211caa07dc | ||
|  | ac66e89edb | ||
|  | 6fe5b50410 | ||
|  | 166cdad58b | ||
|  | 1a721ac6b5 | ||
|  | 6591fa9fb4 | ||
|  | d804093f8b | ||
|  | 5261b784b0 | ||
|  | 5a188ceca3 | ||
|  | ce56cc538d | ||
|  | 269433bf00 | ||
|  | dae3371c69 | ||
|  | 38c1d332e2 | ||
|  | b627d42160 | ||
|  | 4e923057ae | ||
|  | 35d0bd1985 | ||
|  | 085eb650e7 | ||
|  | b4157e8ce0 | ||
|  | 81221038f0 | ||
|  | 9f37bf5875 | ||
|  | 140a5b20db | ||
|  | e9b6b45fc4 | ||
|  | f16760d607 | ||
|  | 9d457787f7 | ||
|  | 4e6afd5afc | ||
|  | 36354c3846 | ||
|  | 9f63dfb9cb | ||
|  | cae4faad0a | ||
|  | e389d0f7fa | ||
|  | 6b32213735 | ||
|  | b3fe24b713 | ||
|  | 5bb7530642 | ||
|  | 0b61c16eb0 | ||
|  | 77aced6734 | ||
|  | 94a7b6b9bd | ||
|  | f8bf6c163f | ||
|  | eb0da038fb | ||
|  | 6cda9f2900 | ||
|  | ecd4a862ff | ||
|  | 632d50a0d0 | ||
|  | 0f1cc46b71 | ||
|  | 60b225d61c | ||
|  | 23e540a57a | ||
|  | 1998412a3c | ||
|  | 7bbfb692de | ||
|  | c6da990748 | ||
|  | 049e57d578 | ||
|  | 78ba0f749c | ||
|  | 9cc1bfb4b5 | ||
|  | 278b7ac52b | ||
|  | 645a29e22b | ||
|  | b22d30bc65 | ||
|  | 2ee0490141 | ||
|  | 1fd783de69 | ||
|  | 8073896965 | ||
|  | 8a26e43c40 | ||
|  | a302aba3ab | ||
|  | 0458058cb1 | ||
|  | 999bb5ed49 | ||
|  | c9f4a1eb7b | ||
|  | 45aa76afce | ||
|  | e89a77efb1 | ||
|  | 8f930d6dd5 | ||
|  | 9d62b4c70d | ||
|  | 834032f58e | ||
|  | 33db99ffd3 | ||
|  | 28b00f6507 | ||
|  | 6559076c48 | ||
|  | 60f6311e00 | ||
|  | 574a5630e0 | ||
|  | d3294be1bc | ||
|  | 22fdc81de2 | ||
|  | 370e9b25d1 | ||
|  | 30f821af3e | ||
|  | 7a5aa1c39b | ||
|  | f674df4422 | ||
|  | c2da5931ec | ||
|  | 94f6bd34c7 | ||
|  | e066a6421c | ||
|  | ef338e2515 | ||
|  | dcf549261c | ||
|  | 8b868b426a | ||
|  | 2ef1022c92 | ||
|  | 9b3abd3b19 | ||
|  | db02fefcf4 | ||
|  | 523ae83811 | ||
|  | 4eb010f807 | ||
|  | 4958f28052 | ||
|  | 7e727b63ed | ||
|  | 138c38fbb5 | ||
|  | 2e61bb7375 | ||
|  | fce4c9174d | ||
|  | 2220963899 | ||
|  | e69e6c1ce8 | ||
|  | 0f09a9db4d | ||
|  | 53a6c10ada | ||
|  | 14772469ed | ||
|  | 55f13ef121 | ||
|  | 95648c37b3 | ||
|  | ac98822a55 | ||
|  | c460419166 | ||
|  | d2a8819dd4 | ||
|  | d393c693de | ||
|  | d4a84ed198 | ||
|  | e8c7986a58 | ||
|  | 809e40c5ce | ||
|  | f445a95c26 | ||
|  | 909dc212fb | ||
|  | eacc1da157 | ||
|  | 587ad1298d | ||
|  | fae7dabbc2 | ||
|  | 3a813c30b4 | ||
|  | 3de46f55fa | ||
|  | 3aa922341c | ||
|  | e94043edc2 | ||
|  | da91645ec0 | ||
|  | 178072d3af | ||
|  | 811d8e330f | ||
|  | d3c8d06114 | ||
|  | 82dc0045ba | ||
|  | 3d06f0ac14 | ||
|  | b5c0ef01d9 | ||
|  | 3a5d3016c7 | ||
|  | 20690b4d5b | ||
|  | 2816a4a325 | ||
|  | 2f4f37778c | ||
|  | c4507a7f75 | ||
|  | 9a0672e359 | ||
|  | f128db35c6 | ||
|  | a2cfaa0867 | ||
|  | 5850c5e20a | ||
|  | e77a1e403f | ||
|  | b72e8db7b1 | ||
|  | 07506784f4 | ||
|  | 0435e42b3d | ||
|  | 31884bbba6 | ||
|  | 6b38faf84e | ||
|  | 2f95f99890 | ||
|  | 9b78069f41 | ||
|  | 559c2042ac | ||
|  | ae3b369e9a | ||
|  | 31a6565e17 | ||
|  | f488bbde02 | ||
|  | e668b88fb5 | ||
|  | 2d0aa4af96 | ||
|  | 6e67416c83 | ||
|  | 1ef28cbc02 | ||
|  | 58bdf14f6b | ||
|  | 9f4ecb0963 | ||
|  | b1259a014f | ||
|  | 142d0b5af2 | ||
|  | 450e2bad1c | ||
|  | 089300d57e | ||
|  | 36f67793cb | ||
|  | c335a9bbc8 | ||
|  | 029688a594 | ||
|  | 6f2eb33fd0 | ||
|  | 8351020913 | ||
|  | 220efca8d7 | ||
|  | 28579f7b80 | ||
|  | f1d77bdb50 | ||
|  | ca8b4cb11a | ||
|  | 31dbb7b111 | ||
|  | 352cdf75c8 | ||
|  | d81c99bcda | ||
|  | 1e2c979341 | ||
|  | d8664096f9 | ||
|  | 0d9a221b00 | ||
|  | de85f17cac | ||
|  | e3d6f4f00f | ||
|  | d0e0054b00 | ||
|  | 735222a8ed | ||
|  | 66f299cd06 | ||
|  | e3c5268143 | ||
|  | df32493d77 | ||
|  | 86faf44153 | ||
|  | e2f3e4b555 | ||
|  | e57ed6015c | ||
|  | 9c34ca7fc4 | ||
|  | 7b94f4a441 | ||
|  | 693f8d0738 | ||
|  | d6ecbc06bf | ||
|  | c31674fffc | ||
|  | b08de8cc00 | ||
|  | 4c503e4c7c | ||
|  | dd4158c6b4 | ||
|  | 5fd7ea2b96 | ||
|  | b9ff80eb5a | ||
|  | afc725bbc8 | ||
|  | 0342c371cc | ||
|  | 2da4e6b048 | ||
|  | f50550d79c | ||
|  | 3fa39a6805 | ||
|  | 3dbe6d4870 | ||
|  | 59c48268ab | ||
|  | 1f83c5195d | ||
|  | 49a95a08fe | ||
|  | c86c5ccfe9 | ||
|  | 8a2497fc67 | ||
|  | 7c70732247 | ||
|  | 53fc4f2740 | ||
|  | f3ade5621e | ||
|  | ec2e08e33a | ||
|  | b9a26faa4d | ||
|  | 1a434d0c83 | ||
|  | 9a2c6c2967 | ||
|  | 602b35d589 | ||
|  | f42cd0c7c3 | ||
|  | cb81855a17 | ||
|  | 89cf351ad0 | ||
|  | 3f70a3f06c | ||
|  | 9df360f010 | ||
|  | 9a26d6d49f | ||
|  | bc4d801c12 | ||
|  | f2d8e13576 | ||
|  | ec0b5db973 | ||
|  | 46a0d1ce35 | ||
|  | cb81446ca6 | ||
|  | 9350b4939c | ||
|  | 33e8c8c415 | ||
|  | 48fa86cc54 | ||
|  | d5e6d1c578 | ||
|  | 0bc688795a | ||
|  | eb76ed5591 | ||
|  | 839cbaf37a | ||
|  | 788fc9204d | ||
|  | 3e3e304ef3 | ||
|  | 447d453fdc | ||
|  | 36fd7884f3 | ||
|  | 54da08b2f2 | ||
|  | 3f02072ae9 | ||
|  | a9c117703b | ||
|  | c137255155 | ||
|  | e7829ecc38 | ||
|  | 529bdafa31 | ||
|  | e2af0caa41 | ||
|  | 80f96abf08 | ||
|  | 70da38193f | ||
|  | 13df973873 | ||
|  | 3ccb791674 | ||
|  | ccf1a6c182 | ||
|  | 493543c1f5 | ||
|  | 5f5725e0e3 | ||
|  | 107dd42957 | ||
|  | a9f3fe4d3a | ||
|  | 3e62e17b9e | ||
|  | 57855b1930 | ||
|  | aa9e8227bb | ||
|  | a80f083b6e | ||
|  | 474e066d4a | ||
|  | 4428ccefbf | ||
|  | d568a6c8a9 | ||
|  | 97e9ad6cb2 | ||
|  | 00607d2a6d | ||
|  | c2a425121d | ||
|  | 435694e9ea | ||
|  | f59135a9ca | ||
|  | 102b106402 | ||
|  | 5c27c8e633 | ||
|  | edd5215b21 | ||
|  | 94b173ae6b | ||
|  | 7d96b281b6 | ||
|  | a5515ac89f | ||
|  | fb863b0bf2 | ||
|  | 50882f309b | ||
|  | ce854fbb43 | ||
|  | 6799268ec4 | ||
|  | 6fe5ce0485 | ||
|  | cbeaf8e16a | ||
|  | 04de4c9b36 | ||
|  | 517731cb59 | ||
|  | e34e43173c | ||
|  | 79d6055a78 | ||
|  | 7ac4d2a2f4 | ||
|  | 4984eda320 | ||
|  | 89e0791e2f | ||
|  | 922d487821 | ||
|  | 4b789979ac | ||
|  | 554b38ccff | ||
|  | 9614310208 | ||
|  | d9ec3ac354 | ||
|  | f326f08f7b | ||
|  | 0ae8418f32 | ||
|  | 309f9cd076 | ||
|  | 61f5ed3874 | ||
|  | 91178d2604 | ||
|  | 87dae6ea18 | ||
|  | 2e495c38d1 | ||
|  | c2987aaf4c | ||
|  | f4f4eecb7b | ||
|  | 84d9287251 | ||
|  | b71f334744 | ||
|  | ad306e4d01 | ||
|  | e40d4ef829 | ||
|  | 48c16c3dcc | ||
|  | c045193246 | ||
|  | a816e59a97 | ||
|  | 892074eaf2 | ||
|  | 3e501e429d | ||
|  | 0f40accb4c | ||
|  | 3dae6c99a4 | ||
|  | b185c83597 | ||
|  | ef6b4120f1 | ||
|  | a43eef01fc | ||
|  | 2cb9aa537f | ||
|  | 2edd49a8b4 | ||
|  | a57554d380 | ||
|  | c89486b6d9 | ||
|  | f737cb7235 | ||
|  | f1fe169553 | ||
|  | 2fc760780e | ||
|  | 8c3290bf6f | ||
|  | 495158b9c9 | ||
|  | f9fc9b1889 | ||
|  | 11ff2ab9d1 | ||
|  | 52b138e6b2 | 
							
								
								
									
										12
									
								
								.codeclimate.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								.codeclimate.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| ---  | ||||
| exclude_patterns:  | ||||
|   - public/lib/ | ||||
|   - public/js/lib/ | ||||
|   - public/fonts/ | ||||
|   - public/css/jquery-ui/ | ||||
|   - public/css/bootstrap-multiselect.css | ||||
|   - public/css/bootstrap-sortable.css | ||||
|   - public/css/bootstrap-tagsinput.css | ||||
|   - public/css/daterangepicker.css | ||||
|   - public/css/google-fonts.css | ||||
|   - .sandstorm/ | ||||
							
								
								
									
										11
									
								
								.deploy/docker/cronjob.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								.deploy/docker/cronjob.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| [program:cron] | ||||
| command=/usr/sbin/cron -f -L 15 | ||||
| user=root | ||||
| autostart=true | ||||
| autorestart=true | ||||
| stdout_events_enabled=true | ||||
| stderr_events_enabled=true | ||||
| stdout_logfile=/dev/stdout | ||||
| stdout_logfile_maxbytes=0 | ||||
| startsecs=10 | ||||
| startretries=3 | ||||
							
								
								
									
										29
									
								
								.deploy/docker/entrypoint.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										29
									
								
								.deploy/docker/entrypoint.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # make sure the correct directories exists (suggested by @chrif): | ||||
| mkdir -p $FIREFLY_PATH/storage/app | ||||
| mkdir -p $FIREFLY_PATH/storage/app/public | ||||
| mkdir -p $FIREFLY_PATH/storage/build | ||||
| mkdir -p $FIREFLY_PATH/storage/database | ||||
| mkdir -p $FIREFLY_PATH/storage/debugbar | ||||
| mkdir -p $FIREFLY_PATH/storage/export | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/cache | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/sessions | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/testing | ||||
| mkdir -p $FIREFLY_PATH/storage/framework/views | ||||
| mkdir -p $FIREFLY_PATH/storage/logs | ||||
| mkdir -p $FIREFLY_PATH/storage/upload | ||||
|  | ||||
|  | ||||
| # make sure we own the volumes: | ||||
| chown -R www-data:www-data -R $FIREFLY_PATH/storage | ||||
| chmod -R 775 $FIREFLY_PATH/storage | ||||
|  | ||||
| # remove any lingering files that may break upgrades: | ||||
| rm -f $FIREFLY_PATH/storage/logs/laravel.log | ||||
|  | ||||
| cat .env.docker | envsubst > .env | ||||
| composer dump-autoload | ||||
| php artisan package:discover | ||||
| php artisan firefly:instructions install | ||||
| exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf --nodaemon | ||||
							
								
								
									
										6
									
								
								.deploy/docker/firefly-iii.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								.deploy/docker/firefly-iii.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| [program:apache2] | ||||
| command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND" | ||||
| stdout_events_enabled=true | ||||
| stderr_events_enabled=true | ||||
| stdout_logfile=/dev/stdout | ||||
| stdout_logfile_maxbytes=0 | ||||
							
								
								
									
										30
									
								
								.deploy/docker/supervisord.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								.deploy/docker/supervisord.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| # supervisor config file | ||||
| # Adapted from the config file distributed with the supervisor package on Debian | ||||
| # Jessie | ||||
|  | ||||
| # Enable supervisord in non-daemon mode. Disable the logfile as we receive | ||||
| # log messages via stdout/err. Set up the child process log directory in case | ||||
| # the user doesn't set logging to stdout/err. | ||||
| [supervisord] | ||||
| nodaemon = true | ||||
| logfile = NONE | ||||
| pidfile = /var/run/supervisord.pid | ||||
| childlogdir = /var/log/supervisor | ||||
| loglevel=debug | ||||
|  | ||||
| # Enable supervisorctl via RPC interface over Unix socket | ||||
| [unix_http_server] | ||||
| file = /var/run/supervisor.sock | ||||
| chmod = 0700 | ||||
|  | ||||
| [rpcinterface:supervisor] | ||||
| supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface | ||||
|  | ||||
| [supervisorctl] | ||||
| serverurl = unix:///var/run/supervisor.sock | ||||
|  | ||||
|  | ||||
| # Include conf files for child processes | ||||
| # Debian/Ubuntu packages use /etc/supervisor/conf.d | ||||
| [include] | ||||
| files = /etc/supervisor/conf.d/*.conf | ||||
							
								
								
									
										26
									
								
								.deploy/docker/vhost.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								.deploy/docker/vhost.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| server { | ||||
|     listen 80 default_server; | ||||
|  | ||||
|     server_name  _ *.vm docker; | ||||
|  | ||||
|     root "/app/public"; | ||||
|     index index.php; | ||||
|  | ||||
|     include /opt/docker/etc/nginx/vhost.common.d/*.conf; | ||||
| } | ||||
|  | ||||
| ############## | ||||
| # SSL | ||||
| ############## | ||||
|  | ||||
| server { | ||||
|     listen 443 default_server; | ||||
|  | ||||
|     server_name  _ *.vm docker; | ||||
|  | ||||
|     root "/app/public"; | ||||
|     index index.php; | ||||
|  | ||||
|     include /opt/docker/etc/nginx/vhost.common.d/*.conf; | ||||
|     include /opt/docker/etc/nginx/vhost.ssl.conf; | ||||
| } | ||||
							
								
								
									
										82
									
								
								.deploy/kubernetes/firefly.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								.deploy/kubernetes/firefly.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| apiVersion: v1 | ||||
| kind: PersistentVolumeClaim | ||||
| metadata: | ||||
|   name: mysql-pv-export-claim | ||||
|   labels: | ||||
|     app: firefly-local | ||||
| spec: | ||||
|   accessModes: | ||||
|     - ReadWriteOnce | ||||
|   resources: | ||||
|     requests: | ||||
|       storage: 20Gi | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: PersistentVolumeClaim | ||||
| metadata: | ||||
|   name: mysql-pv-upload-claim | ||||
|   labels: | ||||
|     app: firefly-local | ||||
| spec: | ||||
|   accessModes: | ||||
|     - ReadWriteOnce | ||||
|   resources: | ||||
|     requests: | ||||
|       storage: 20Gi | ||||
| ---  | ||||
| apiVersion: apps/v1beta1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: firefly-local | ||||
|   namespace: firefly | ||||
|   labels: | ||||
|     app: firefly-local | ||||
| spec: | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: firefly-local | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: firefly-local | ||||
|     spec: | ||||
|       containers: | ||||
|       - image: firefly-local | ||||
|         name: firefly-local | ||||
|         env: | ||||
|         - name: FF_APP_ENV | ||||
|           value: "local" | ||||
|         - name: FF_APP_KEY | ||||
|           value: "S0m3R@nd0mString0f32Ch@rsEx@ct1y" | ||||
|         - name: FF_DB_HOST | ||||
|           value: "172.17.0.9"  | ||||
|         - name: FF_DB_NAME | ||||
|           value: "firefly_db" | ||||
|         - name: FF_DB_USER | ||||
|           value: "firefly_db" | ||||
|         - name: FF_DB_PASSWORD | ||||
|           value: "password"  | ||||
|         volumeMounts: | ||||
|         - mountPath: "/var/www/firefly-iii/storage/export" | ||||
|           name: mysql-persistent-export | ||||
|         - mountPath: "/var/www/firefly-iii/storage/upload" | ||||
|           name: mysql-persistent-upload  | ||||
|         imagePullPolicy: IfNotPresent | ||||
|       volumes: | ||||
|         - name: mysql-persistent-export | ||||
|           persistentVolumeClaim: | ||||
|             claimName: mysql-pv-export-claim | ||||
|         - name: mysql-persistent-upload | ||||
|           persistentVolumeClaim: | ||||
|             claimName: mysql-pv-upload-claim | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: firefly-local | ||||
| spec: | ||||
|   ports: | ||||
|     - port: 80 | ||||
|   type: NodePort | ||||
|   selector: | ||||
|     app: firefly-local | ||||
							
								
								
									
										49
									
								
								.deploy/kubernetes/sql.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								.deploy/kubernetes/sql.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| apiVersion: v1 | ||||
| kind: Secret | ||||
| metadata: | ||||
|   name: sql-pass | ||||
| type: Opaque | ||||
| data: | ||||
|   password: cGFzc3dvcmQ= | ||||
| --- | ||||
| apiVersion: apps/v1beta1 | ||||
| kind: Deployment | ||||
| metadata: | ||||
|   name: mysql | ||||
|   namespace: firefly | ||||
|   labels: | ||||
|     app: mysql | ||||
| spec: | ||||
|   selector: | ||||
|     matchLabels: | ||||
|       app: mysql | ||||
|   template: | ||||
|     metadata: | ||||
|       labels: | ||||
|         app: mysql | ||||
|     spec: | ||||
|       containers: | ||||
|       - image: mysql | ||||
|         imagePullPolicy: IfNotPresent | ||||
|         name: mysql | ||||
|         env: | ||||
|           - name: MYSQL_ROOT_PASSWORD | ||||
|             valueFrom: | ||||
|               secretKeyRef: | ||||
|                 name: sql-pass | ||||
|                 key: password | ||||
|         ports: | ||||
|         - containerPort: 3306 | ||||
|           name: mysql | ||||
| --- | ||||
| apiVersion: v1 | ||||
| kind: Service | ||||
| metadata: | ||||
|   name: mysql | ||||
| spec: | ||||
|   ports: | ||||
|     - port: 3306 | ||||
|   type: NodePort | ||||
|   selector: | ||||
|     app: mysql | ||||
|  | ||||
| @@ -1,4 +1,3 @@ | ||||
| # Ignore composer specific files and vendor folder | ||||
| composer.phar | ||||
| composer.lock | ||||
| vendor | ||||
|   | ||||
							
								
								
									
										118
									
								
								.env.docker
									
									
									
									
									
								
							
							
						
						
									
										118
									
								
								.env.docker
									
									
									
									
									
								
							| @@ -1,60 +1,112 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=${FF_APP_ENV} | ||||
| APP_DEBUG=false | ||||
| APP_NAME=FireflyIII | ||||
| APP_KEY=${FF_APP_KEY} | ||||
| APP_LOG=daily | ||||
| APP_LOG_LEVEL=warning | ||||
| APP_URL=http://localhost | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| DB_CONNECTION=mysql | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=${APP_DEBUG} | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=${SITE_OWNER} | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=${FF_APP_KEY} | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=${TZ} | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=${APP_URL} | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES=${TRUSTED_PROXIES} | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=${APP_LOG_LEVEL} | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=${FF_DB_CONNECTION} | ||||
| DB_HOST=${FF_DB_HOST} | ||||
| DB_PORT=3306 | ||||
| DB_PORT=${FF_DB_PORT} | ||||
| DB_DATABASE=${FF_DB_NAME} | ||||
| DB_USERNAME=${FF_DB_USER} | ||||
| DB_PASSWORD=${FF_DB_PASSWORD} | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=${MAIL_DRIVER} | ||||
| MAIL_HOST=${MAIL_HOST} | ||||
| MAIL_PORT=${MAIL_PORT} | ||||
| MAIL_FROM=${MAIL_FROM} | ||||
| MAIL_USERNAME=${MAIL_USERNAME} | ||||
| MAIL_PASSWORD=${MAIL_PASSWORD} | ||||
| MAIL_ENCRYPTION=${MAIL_ENCRYPTION} | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN=${MAILGUN_DOMAIN} | ||||
| MAILGUN_SECRET=${MAILGUN_SECRET} | ||||
| MANDRILL_SECRET=${MANDRILL_SECRET} | ||||
| SPARKPOST_SECRET=${SPARKPOST_SECRET} | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=false | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY=${MAPBOX_API_KEY} | ||||
|  | ||||
| # Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this will only work for paid fixer.io accounts because they severly limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY=${FIXER_API_KEY} | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID=${ANALYTICS_ID} | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
|  | ||||
| MAPBOX_API_KEY= | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=mail@example.com | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=true | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
							
								
								
									
										88
									
								
								.env.example
									
									
									
									
									
								
							
							
						
						
									
										88
									
								
								.env.example
									
									
									
									
									
								
							| @@ -1,12 +1,43 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=local | ||||
|  | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=false | ||||
| APP_NAME=FireflyIII | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
| APP_LOG=daily | ||||
| APP_LOG_LEVEL=notice | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=Europe/Amsterdam | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=daily | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=notice | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=127.0.0.1 | ||||
| DB_PORT=3306 | ||||
| @@ -14,20 +45,18 @@ DB_DATABASE=homestead | ||||
| DB_USERNAME=homestead | ||||
| DB_PASSWORD=secret | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=log | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| @@ -35,26 +64,49 @@ MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY= | ||||
|  | ||||
| # Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this will only work for paid fixer.io accounts because they severly limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
							
								
								
									
										96
									
								
								.env.heroku
									
									
									
									
									
								
							
							
						
						
									
										96
									
								
								.env.heroku
									
									
									
									
									
								
							| @@ -1,12 +1,43 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=heroku | ||||
| APP_DEBUG=true | ||||
| APP_NAME=FireflyIII | ||||
| APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2 | ||||
| APP_LOG=errorlog | ||||
| APP_LOG_LEVEL=debug | ||||
| APP_URL=http://localhost | ||||
| TRUSTED_PROXIES=* | ||||
|  | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=false | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=heroku@example.com | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=7ahyYVPVsmxjdhsweWCauGeJfwc92NP2 | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=UTC | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES=** | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # If you use SQLite, set connection to `sqlite` and remove the database, username and password settings. | ||||
| DB_CONNECTION=pgsql | ||||
|  | ||||
|  | ||||
| @@ -14,20 +45,18 @@ DB_CONNECTION=pgsql | ||||
|  | ||||
|  | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=log | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| @@ -35,26 +64,49 @@ MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY= | ||||
|  | ||||
| # Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this will only work for paid fixer.io accounts because they severly limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=heroku@example.com | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=true | ||||
| BUNQ_USE_SANDBOX=false | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
| @@ -1,12 +1,43 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=local | ||||
|  | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=false | ||||
| APP_NAME=FireflyIII | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=sandstorm@example.com | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=SomeRandomStringOf32CharsExactly | ||||
| APP_LOG=syslog | ||||
| APP_LOG_LEVEL=info | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=UTC | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=stdout | ||||
|  | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # If you use SQLite, set connection to `sqlite` and remove the database, username and password settings. | ||||
| DB_CONNECTION=mysql | ||||
| DB_HOST=127.0.0.1 | ||||
| DB_PORT=3306 | ||||
| @@ -14,20 +45,18 @@ DB_DATABASE=firefly | ||||
| DB_USERNAME=firefly | ||||
| DB_PASSWORD=firefly | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=log | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| @@ -35,26 +64,49 @@ MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY= | ||||
|  | ||||
| # Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this will only work for paid fixer.io accounts because they severly limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=mail@example.com | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
| CACHE_PREFIX=firefly | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=true | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=false | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
							
								
								
									
										106
									
								
								.env.testing
									
									
									
									
									
								
							
							
						
						
									
										106
									
								
								.env.testing
									
									
									
									
									
								
							| @@ -1,33 +1,62 @@ | ||||
| # You can leave this on "local". If you change it to production most console commands will ask for extra confirmation. | ||||
| # Never set it to "testing". | ||||
| APP_ENV=testing | ||||
|  | ||||
| # Set to true if you want to see debug information in error screens. | ||||
| APP_DEBUG=true | ||||
| APP_NAME=FireflyIII | ||||
|  | ||||
| # This should be your email address | ||||
| SITE_OWNER=thegrumpydictator+testing@gmail.com | ||||
|  | ||||
| # The encryption key for your database and sessions. Keep this very secure. | ||||
| # If you generate a new one all existing data must be considered LOST. | ||||
| # Change it to a string of exactly 32 chars or use command `php artisan key:generate` to generate it | ||||
| APP_KEY=TestTestTestTestTestTestTestTest | ||||
| APP_LOG=daily | ||||
| APP_LOG_LEVEL=debug | ||||
|  | ||||
| # Change this value to your preferred time zone. | ||||
| # Example: Europe/Amsterdam | ||||
| TZ=Europe/Amsterdam | ||||
|  | ||||
| # This variable must match your installation's external address but keep in mind that | ||||
| # it's only used on the command line as a fallback value. | ||||
| APP_URL=http://localhost | ||||
|  | ||||
| # TRUSTED_PROXIES is a useful variable when using Docker and/or a reverse proxy. | ||||
| TRUSTED_PROXIES= | ||||
|  | ||||
| DB_CONNECTION=sqlite | ||||
| DB_HOST=127.0.0.1 | ||||
| DB_PORT=3306 | ||||
| #DB_DATABASE=firefly | ||||
| DB_USERNAME=homestead | ||||
| DB_PASSWORD= | ||||
| # The log channel defines where your log entries go to. | ||||
| # 'daily' is the default logging mode giving you 5 daily rotated log files in /storage/logs/. | ||||
| # Several other options exist. You can use 'single' for one big fat error log (not recommended). | ||||
| # Also available are 'syslog', 'errorlog' and 'stdout' which will log to the system itself. | ||||
| LOG_CHANNEL=dailytest | ||||
|  | ||||
| BROADCAST_DRIVER=log | ||||
| # Log level. You can set this from least severe to most severe: | ||||
| # debug, info, notice, warning, error, critical, alert, emergency | ||||
| # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably | ||||
| # nothing will get logged, ever. | ||||
| APP_LOG_LEVEL=info | ||||
|  | ||||
| # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III | ||||
| # For other database types, please see the FAQ: http://firefly-iii.readthedocs.io/en/latest/support/faq.html | ||||
| DB_CONNECTION=sqlite | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| # If you're looking for performance improvements, you could install memcached. | ||||
| CACHE_DRIVER=file | ||||
| SESSION_DRIVER=file | ||||
| QUEUE_DRIVER=sync | ||||
|  | ||||
| # Cookie settings. Should not be necessary to change these. | ||||
| COOKIE_PATH="/" | ||||
| COOKIE_DOMAIN= | ||||
| COOKIE_SECURE=false | ||||
|  | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
|  | ||||
| MAIL_DRIVER=smtp | ||||
| # If you want Firefly III to mail you, update these settings | ||||
| # For instructions, see: https://firefly-iii.readthedocs.io/en/latest/installation/mail.html | ||||
| MAIL_DRIVER=log | ||||
| MAIL_HOST=smtp.mailtrap.io | ||||
| MAIL_PORT=2525 | ||||
| MAIL_FROM=changeme@example.com | ||||
| @@ -35,26 +64,49 @@ MAIL_USERNAME=null | ||||
| MAIL_PASSWORD=null | ||||
| MAIL_ENCRYPTION=null | ||||
|  | ||||
| # Other mail drivers: | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
| MANDRILL_SECRET= | ||||
| SPARKPOST_SECRET= | ||||
|  | ||||
| # Firefly III can send you the following messages | ||||
| SEND_REGISTRATION_MAIL=true | ||||
| SEND_ERROR_MESSAGE=true | ||||
|  | ||||
| CACHE_PREFIX=firefly | ||||
|  | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| EXCHANGE_RATE_SERVICE=fixerio | ||||
| SEND_ERROR_MESSAGE=false | ||||
|  | ||||
| # Set a Mapbox API key here (see mapbox.com) so there might be a map available at various places. | ||||
| MAPBOX_API_KEY= | ||||
| ANALYTICS_ID= | ||||
| SITE_OWNER=mail@example.com | ||||
| USE_ENCRYPTION=true | ||||
|  | ||||
| # Set a Fixer IO API key here (see https://fixer.io) to enable live currency exchange rates. | ||||
| # Please note that this will only work for paid fixer.io accounts because they severly limited | ||||
| # the free API up to the point where you might as well offer nothing. | ||||
| FIXER_API_KEY= | ||||
|  | ||||
| # If you wish to track your own behavior over Firefly III, set a valid analytics tracker ID here. | ||||
| ANALYTICS_ID= | ||||
|  | ||||
| # Most parts of the database are encrypted by default, but you can turn this off if you want to. | ||||
| # This makes it easier to migrate your database. Not that some fields will never be decrypted. | ||||
| USE_ENCRYPTION=false | ||||
|  | ||||
| # Leave the following configuration vars as is. | ||||
| # Unless you like to tinker and know what you're doing. | ||||
| APP_NAME=FireflyIII | ||||
| BROADCAST_DRIVER=log | ||||
| QUEUE_DRIVER=sync | ||||
| REDIS_HOST=127.0.0.1 | ||||
| REDIS_PASSWORD=null | ||||
| REDIS_PORT=6379 | ||||
| CACHE_PREFIX=firefly_tst | ||||
| SEARCH_RESULT_LIMIT=50 | ||||
| PUSHER_KEY= | ||||
| PUSHER_SECRET= | ||||
| PUSHER_ID= | ||||
|  | ||||
| DEMO_USERNAME= | ||||
| DEMO_PASSWORD= | ||||
|  | ||||
| IS_DOCKER=false | ||||
| IS_SANDSTORM=false | ||||
| IS_HEROKU=false | ||||
| BUNQ_USE_SANDBOX=true | ||||
| MAILGUN_DOMAIN= | ||||
| MAILGUN_SECRET= | ||||
|   | ||||
							
								
								
									
										11
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							| @@ -1,11 +0,0 @@ | ||||
| I am running Firefly III version x.x.x  | ||||
|  | ||||
| #### Description of my issue: | ||||
|  | ||||
| #### Steps to reproduce  | ||||
|  | ||||
| (please include if this problem also exists on the demo site) | ||||
|  | ||||
| #### Other important details (log files, system info): | ||||
|  | ||||
| Please click the version number in the right corner of any Firefly III page to get debug information.  | ||||
							
								
								
									
										25
									
								
								.github/ISSUE_TEMPLATE/Bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								.github/ISSUE_TEMPLATE/Bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| --- | ||||
| name: Bug report | ||||
| about: Create a report to help Firefly III improve | ||||
|  | ||||
| --- | ||||
|  | ||||
| **Bug description** | ||||
| I am running Firefly III version x.x.x | ||||
|  | ||||
| (please give a clear and concise description of what the bug is) | ||||
|  | ||||
| **Steps to reproduce** | ||||
| What do you need to do to trigger this bug? | ||||
|  | ||||
| **Expected behavior** | ||||
| What do you expect to see after those steps? | ||||
|  | ||||
| **Extra info** | ||||
| Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom). | ||||
|  | ||||
| **Bonus points** | ||||
| Earn bonus points by: | ||||
|  | ||||
| - Post a stacktrace from your log files | ||||
| - Add a screenshot | ||||
							
								
								
									
										27
									
								
								.github/ISSUE_TEMPLATE/Custom.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								.github/ISSUE_TEMPLATE/Custom.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| --- | ||||
| name: I have a question or a problem | ||||
| about: Ask away! | ||||
|  | ||||
| --- | ||||
|  | ||||
| I am running Firefly III version x.x.x | ||||
|  | ||||
| **Description** | ||||
|  | ||||
|  | ||||
|  | ||||
| **Steps to reproduce**  | ||||
| (if relevant of course) | ||||
|  | ||||
|  | ||||
|  | ||||
| **Extra info** | ||||
| Please add extra info here, such as OS, browser, and the output from the `/debug`-page of your Firefly III installation (click the version at the bottom).  | ||||
|  | ||||
|  | ||||
|  | ||||
| **Bonus points** | ||||
| Earn bonus points by: | ||||
|  | ||||
| - Add a screenshot | ||||
| - Replicate the problem on the demo site https://demo.firefly-iii.org/ | ||||
							
								
								
									
										21
									
								
								.github/ISSUE_TEMPLATE/Feature_request.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								.github/ISSUE_TEMPLATE/Feature_request.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| --- | ||||
| name: Feature request | ||||
| about: Suggest an idea or feature for Firefly III | ||||
|  | ||||
| --- | ||||
|  | ||||
| **Description** | ||||
| Please describe your feature request: | ||||
|  | ||||
| - I would like Firefly III to do X. | ||||
| - What if you would add feature Y? | ||||
| - Firefly III doesn't do Z. | ||||
|  | ||||
| **Solution** | ||||
| Describe what your feature would add to Firefly III. | ||||
|  | ||||
| **What are alternatives?** | ||||
| Please describe what alternatives currently exist. | ||||
|  | ||||
| **Additional context** | ||||
| Add any other context or screenshots about the feature request here. | ||||
| @@ -4,7 +4,7 @@ | ||||
| 
 | ||||
| ## Feature requests | ||||
| 
 | ||||
| I am always interested in expanding Firefly III's many features. If you are requesting a new feature, please check out the list of [often requested features](https://firefly-iii.org/requested-features/). | ||||
| I am always interested in expanding Firefly III's many features. Just open a ticket or [drop me a line](mailto:thegrumpydictator@gmail.com). | ||||
| 
 | ||||
| ## Pull requests | ||||
| 
 | ||||
							
								
								
									
										56
									
								
								.github/stale.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								.github/stale.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| # Configuration for probot-stale - https://github.com/probot/stale | ||||
|  | ||||
| # Number of days of inactivity before an Issue or Pull Request becomes stale | ||||
| daysUntilStale: 14 | ||||
|  | ||||
| # Number of days of inactivity before a stale Issue or Pull Request is closed. | ||||
| # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. | ||||
| daysUntilClose: 7 | ||||
|  | ||||
| # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable | ||||
| # - "[Status] Maybe Later" | ||||
| exemptLabels: | ||||
|   - enhancement | ||||
|   - feature | ||||
|   - bug | ||||
|  | ||||
| # Set to true to ignore issues in a project (defaults to false) | ||||
| exemptProjects: false | ||||
|  | ||||
| # Set to true to ignore issues in a milestone (defaults to false) | ||||
| exemptMilestones: false | ||||
|  | ||||
| # Label to use when marking as stale | ||||
| staleLabel: stale | ||||
|  | ||||
| # Comment to post when marking as stale. Set to `false` to disable | ||||
| markComment: > | ||||
|   This issue has been automatically marked as stale because it has not had | ||||
|   recent activity. It will be closed if no further activity occurs. Thank you | ||||
|   for your contributions. | ||||
|  | ||||
| # Comment to post when removing the stale label. | ||||
| # unmarkComment: > | ||||
| #   Your comment here. | ||||
|  | ||||
| # Comment to post when closing a stale Issue or Pull Request. | ||||
| # closeComment: > | ||||
| #   Your comment here. | ||||
|  | ||||
| # Limit the number of actions per hour, from 1-30. Default is 30 | ||||
| limitPerRun: 30 | ||||
|  | ||||
| # Limit to only `issues` or `pulls` | ||||
| # only: issues | ||||
|  | ||||
| # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': | ||||
| # pulls: | ||||
| #   daysUntilStale: 30 | ||||
| #   markComment: > | ||||
| #     This pull request has been automatically marked as stale because it has not had | ||||
| #     recent activity. It will be closed if no further activity occurs. Thank you | ||||
| #     for your contributions. | ||||
|  | ||||
| # issues: | ||||
| #   exemptLabels: | ||||
| #     - confirmed | ||||
							
								
								
									
										0
									
								
								.github/SUPPORT.md → .github/support.md
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										0
									
								
								.github/SUPPORT.md → .github/support.md
									
									
									
									
										vendored
									
									
								
							
							
								
								
									
										9
									
								
								.sandstorm/Vagrantfile
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								.sandstorm/Vagrantfile
									
									
									
									
										vendored
									
									
								
							| @@ -9,9 +9,16 @@ VM_NAME = File.basename(File.dirname(File.dirname(__FILE__))) + "_sandstorm_#{Ti | ||||
| # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! | ||||
| VAGRANTFILE_API_VERSION = "2" | ||||
|  | ||||
| # ugly hack to prevent hashicorp's bitrot. See https://github.com/hashicorp/vagrant/issues/9442 | ||||
| # this setting is required for pre-2.0 vagrant, but causes an error as of 2.0.3, | ||||
| # remove entirely when confident nobody uses vagrant 1.x for anything. | ||||
| unless Vagrant::DEFAULT_SERVER_URL.frozen? | ||||
|   Vagrant::DEFAULT_SERVER_URL.replace('https://vagrantcloud.com') | ||||
| end | ||||
|  | ||||
| Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| | ||||
|   # Base on the Sandstorm snapshots of the official Debian 8 (jessie) box. | ||||
|   config.vm.box = "sandstorm/debian-jessie64" | ||||
|   config.vm.box = "debian/contrib-jessie64" | ||||
|  | ||||
|   if Vagrant.has_plugin?("vagrant-vbguest") then | ||||
|     # vagrant-vbguest is a Vagrant plugin that upgrades | ||||
|   | ||||
| @@ -3,10 +3,9 @@ | ||||
| # This script only runs once, when the app connects to sandstorm. | ||||
| set -euo pipefail | ||||
|  | ||||
|  | ||||
| echo "In build.sh" | ||||
|  | ||||
| cd /opt/app | ||||
|  | ||||
| cp .env.sandstorm .env | ||||
|  | ||||
| if [ -f /opt/app/composer.json ] ; then | ||||
|   | ||||
| @@ -1,3 +1,298 @@ | ||||
| # 4.7.7 | ||||
| - [Issue 954](https://github.com/firefly-iii/firefly-iii/issues/954) Some additional view chart ranges | ||||
| - [Issue 1710](https://github.com/firefly-iii/firefly-iii/issues/1710) Added a new currency ([hamuz](https://github.com/hamuz))  | ||||
| - Transactions will now store (in the database) how they were created. | ||||
| - [Issue 907](https://github.com/firefly-iii/firefly-iii/issues/907) Better and more options on the transaction list. | ||||
| - [Issue 1450](https://github.com/firefly-iii/firefly-iii/issues/1450) Add a rule to change the type of a transaction automagically | ||||
| - [Issue 1701](https://github.com/firefly-iii/firefly-iii/issues/1701) Fix reference to PHP executable ([hertzg](https://github.com/hertzg)) | ||||
| - Budget limits have currency information, for future expansion. | ||||
| - Some charts and pages can handle multiple currencies better. | ||||
| - New GA code for those who use it. | ||||
| - The credit card liability type has been removed. | ||||
| - [Issue 896](https://github.com/firefly-iii/firefly-iii/issues/896) Better redirection when coming from deleted objects. | ||||
| - [Issue 1519](https://github.com/firefly-iii/firefly-iii/issues/1519) Fix autocomplete tags | ||||
| - [Issue 1607](https://github.com/firefly-iii/firefly-iii/issues/1607) Some fixes for the bunq api calls | ||||
| - [Issue 1650](https://github.com/firefly-iii/firefly-iii/issues/1650) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz)) | ||||
| - [Issue 1658](https://github.com/firefly-iii/firefly-iii/issues/1658) Make font heavy again. | ||||
| - [Issue 1660](https://github.com/firefly-iii/firefly-iii/issues/1660) Add a negated amount column for CSV imports ([hamuz](https://github.com/hamuz)) | ||||
| - [Issue 1667](https://github.com/firefly-iii/firefly-iii/issues/1667) Fix pie charts | ||||
| - [Issue 1668](https://github.com/firefly-iii/firefly-iii/issues/1668) YNAB iso_code fix | ||||
| - [Issue 1670](https://github.com/firefly-iii/firefly-iii/issues/1670) Fix piggy bank API error | ||||
| - [Issue 1671](https://github.com/firefly-iii/firefly-iii/issues/1671) More options for liability accounts. | ||||
| - [Issue 1673](https://github.com/firefly-iii/firefly-iii/issues/1673) Fix reconciliation issues. | ||||
| - [Issue 1675](https://github.com/firefly-iii/firefly-iii/issues/1675) Wrong sum in tag report. | ||||
| - [Issue 1679](https://github.com/firefly-iii/firefly-iii/issues/1679) Change type of a transaction wouldn't trigger rules. | ||||
| - [Issue 1682](https://github.com/firefly-iii/firefly-iii/issues/1682) Add liability accounts to transaction conversion | ||||
| - [Issue 1683](https://github.com/firefly-iii/firefly-iii/issues/1683) See matching transaction showed transfers twice. | ||||
| - [Issue 1685](https://github.com/firefly-iii/firefly-iii/issues/1685) fix autocomplete for rules | ||||
| - [Issue 1690](https://github.com/firefly-iii/firefly-iii/issues/1690) Missing highlighted button in intro popup | ||||
| - [Issue 1691](https://github.com/firefly-iii/firefly-iii/issues/1691) No mention of liabilities in demo text | ||||
| - [Issue 1695](https://github.com/firefly-iii/firefly-iii/issues/1695) Small fixes in bills pages. | ||||
| - [Issue 1708](https://github.com/firefly-iii/firefly-iii/issues/1708) Fix by [mathieupost](https://github.com/mathieupost) for bunq | ||||
| - [Issue 1709](https://github.com/firefly-iii/firefly-iii/issues/1709) Fix oauth buttons  | ||||
| - [Issue 1712](https://github.com/firefly-iii/firefly-iii/issues/1712) Double slash fix by [hamuz](https://github.com/hamuz) | ||||
| - [Issue 1719](https://github.com/firefly-iii/firefly-iii/issues/1719) Add missing accounts to API | ||||
| - [Issue 1720](https://github.com/firefly-iii/firefly-iii/issues/1720) Fix validation for transaction type. | ||||
| - [Issue 1723](https://github.com/firefly-iii/firefly-iii/issues/1723) API broken for currency exchange rates. | ||||
| - [Issue 1728](https://github.com/firefly-iii/firefly-iii/issues/1728) Fix problem with transaction factory. | ||||
| - [Issue 1729](https://github.com/firefly-iii/firefly-iii/issues/1729) Fix bulk transaction editor | ||||
| - [Issue 1731](https://github.com/firefly-iii/firefly-iii/issues/1731) API failure for budget limits. | ||||
| - Secure headers now allow Mapbox and the 2FA QR code. | ||||
|  | ||||
| # 4.7.6.2 | ||||
| - Docker file builds again. | ||||
| - Fix CSS of OAuth2 authorization view. | ||||
|  | ||||
| # 4.7.6.1 | ||||
| - An issue where I switched variables from the Docker `.env` file to the normal `.env` file and vice versa -- breaking both. | ||||
| - [Issue 1649](https://github.com/firefly-iii/firefly-iii/issues/1649) 2FA QR code would not show up due to very strict security policy headers | ||||
| - Docker build gave a cURL error whenever it runs PHP commands. | ||||
|  | ||||
| # 4.7.6 | ||||
| - [Issue 145](https://github.com/firefly-iii/firefly-iii/issues/145) You can now download transactions from YNAB. | ||||
| - [Issue 306](https://github.com/firefly-iii/firefly-iii/issues/306) You can now add liabilities to Firefly III. | ||||
| - [Issue 740](https://github.com/firefly-iii/firefly-iii/issues/740) Various charts are now currency aware. | ||||
| - [Issue 833](https://github.com/firefly-iii/firefly-iii/issues/833) Bills can use non-default currencies. | ||||
| - [Issue 1578](https://github.com/firefly-iii/firefly-iii/issues/1578) Firefly III will notify you if the cron job hasn't fired. | ||||
| - [Issue 1623](https://github.com/firefly-iii/firefly-iii/issues/1623) New transactions will link back from the success message. | ||||
| - [Issue 1624](https://github.com/firefly-iii/firefly-iii/issues/1624) transactions will link to the object. | ||||
| - You can call the cron job over the web now (see docs). | ||||
| - You don't need to call the cron job every minute any more. | ||||
| - Various charts are now red/green to signify income and expenses. | ||||
| - Option to add or remove accounts from the net worth calculations. | ||||
| - This will be the last release on PHP 7.1. Future versions will require PHP 7.2. | ||||
| - [Issue 1460](https://github.com/firefly-iii/firefly-iii/issues/1460) Downloading transactions from bunq should go more smoothly. | ||||
| - [Issue 1464](https://github.com/firefly-iii/firefly-iii/issues/1464) Fixed the docker file to work on Raspberry Pi's. | ||||
| - [Issue 1540](https://github.com/firefly-iii/firefly-iii/issues/1540) The Docker file now has a working cron job for recurring transactions. | ||||
| - [Issue 1564](https://github.com/firefly-iii/firefly-iii/issues/1564) Fix double transfers when importing from bunq. | ||||
| - [Issue 1575](https://github.com/firefly-iii/firefly-iii/issues/1575) Some views would give a XSRF token warning | ||||
| - [Issue 1576](https://github.com/firefly-iii/firefly-iii/issues/1576) Fix assigning budgets | ||||
| - [Issue 1580](https://github.com/firefly-iii/firefly-iii/issues/1580) Missing string for translation | ||||
| - [Issue 1581](https://github.com/firefly-iii/firefly-iii/issues/1581) Expand help text | ||||
| - [Issue 1584](https://github.com/firefly-iii/firefly-iii/issues/1584) Link to administration is back. | ||||
| - [Issue 1586](https://github.com/firefly-iii/firefly-iii/issues/1586) Date fields in import were mislabeled. | ||||
| - [Issue 1593](https://github.com/firefly-iii/firefly-iii/issues/1593) Link types are translatable. | ||||
| - [Issue 1594](https://github.com/firefly-iii/firefly-iii/issues/1594) Very long breadcrumbs are weird. | ||||
| - [Issue 1598](https://github.com/firefly-iii/firefly-iii/issues/1598) Fix budget calculations. | ||||
| - [Issue 1597](https://github.com/firefly-iii/firefly-iii/issues/1597) Piggy banks are always inactive. | ||||
| - [Issue 1605](https://github.com/firefly-iii/firefly-iii/issues/1605) System will ignore foreign currency setting if user doesn't indicate the amount. | ||||
| - [Issue 1608](https://github.com/firefly-iii/firefly-iii/issues/1608) Spelling error in command line import. | ||||
| - [Issue 1609](https://github.com/firefly-iii/firefly-iii/issues/1609) Link to budgets page was absolute. | ||||
| - [Issue 1615](https://github.com/firefly-iii/firefly-iii/issues/1615) Fix currency bug in transactions. | ||||
| - [Issue 1616](https://github.com/firefly-iii/firefly-iii/issues/1616) Fix null pointer exception in pie charts. | ||||
| - [Issue 1617](https://github.com/firefly-iii/firefly-iii/issues/1617) Fix for complex tag names in URL's. | ||||
| - [Issue 1620](https://github.com/firefly-iii/firefly-iii/issues/1620) Fixed index reference in API. | ||||
| - [Issue 1639](https://github.com/firefly-iii/firefly-iii/issues/1639) Firefly III trusts the Heroku load balancer, fixing deployment on Heroku. | ||||
| - [Issue 1642](https://github.com/firefly-iii/firefly-iii/issues/1642) Fix issue with split journals. | ||||
| - [Issue 1643](https://github.com/firefly-iii/firefly-iii/issues/1643) Fix reconciliation issue. | ||||
| - Users can no longer give income a budget. | ||||
| - Fix bug in Spectre import. | ||||
| - Heroku would not make you owner. | ||||
| - Add `.htaccess` files to all public directories. | ||||
| - New secure headers will make Firefly III slightly more secure. | ||||
| - The rule "tester" will now also take the "strict"-checkbox into account. | ||||
|  | ||||
| # 4.7.5.3 | ||||
| - [Issue 1527](https://github.com/firefly-iii/firefly-iii/issues/1527), fixed views for transactions without a budget. | ||||
| - [Issue 1553](https://github.com/firefly-iii/firefly-iii/issues/1553), report could not handle transactions before the first one in the system. | ||||
| - [Issue 1549](https://github.com/firefly-iii/firefly-iii/issues/1549) update a budget will also update any rules that refer to that budget. | ||||
| - [Issue 1530](https://github.com/firefly-iii/firefly-iii/issues/1530), fix issue with bill chart. | ||||
| - [Issue 1563](https://github.com/firefly-iii/firefly-iii/issues/1563), fix piggy bank suggested amount | ||||
| - [Issue 1571](https://github.com/firefly-iii/firefly-iii/issues/1571), fix OAuth in Sandstorm | ||||
| - [Issue 1568](https://github.com/firefly-iii/firefly-iii/issues/1568), bug in Sandstorm user code. | ||||
| - [Issue 1569](https://github.com/firefly-iii/firefly-iii/issues/1569), optimized Sandstorm build by [ocdtrekkie](https://github.com/ocdtrekkie) | ||||
| - Fixed a bug where transfers would be stored inversely when using the CSV import. | ||||
| - Retired the "Rabobank description"-fix, because it is no longer necessary. | ||||
| - Fixed a bug where users could not delete budget limits in the API. | ||||
| - Piggy bank notes are visible again. | ||||
|  | ||||
| # 4.7.5.1 | ||||
| - [Issue 1531](https://github.com/firefly-iii/firefly-iii/issues/1531), the database routine incorrectly reports empty categories. | ||||
| - [Issue 1532](https://github.com/firefly-iii/firefly-iii/issues/1532), broken dropdown for autosuggest things. | ||||
| - [Issue 1533](https://github.com/firefly-iii/firefly-iii/issues/1533), fix where the import could not import category names. | ||||
| - [Issue 1538](https://github.com/firefly-iii/firefly-iii/issues/1538), fix a bug where Spectre would not work when ignoring rules. | ||||
| - [Issue 1542](https://github.com/firefly-iii/firefly-iii/issues/1542), fix a bug where the importer was incapable of generating new currencies. | ||||
| - [Issue 1541](https://github.com/firefly-iii/firefly-iii/issues/1541), no longer ignore composer.lock in Docker ignore. | ||||
| - Bills are stored inactive. | ||||
|  | ||||
| # 4.7.5 | ||||
| - A new feature called "recurring transactions" that will make Firefly III automatically create transactions for you. | ||||
| - New API end points for attachments, available budgets, budgets, budget limits, categories, configuration, currency exchange rates, journal links, link types, piggy banks, preferences, recurring transactions, rules, rule groups and tags. | ||||
| - Added support for YunoHost. | ||||
| - The 2FA secret is visible so you can type it into 2FA apps. | ||||
| - Bunq and Spectre imports will now ask to apply rules. | ||||
| - Sandstorm users can now make API keys. | ||||
| - Various typo's in the English translations. [issue 1493](https://github.com/firefly-iii/firefly-iii/issues/1493) | ||||
| - Bug where Spectre was never called [issue 1492](https://github.com/firefly-iii/firefly-iii/issues/1492) | ||||
| - Clear cache after journal is created through API [issue 1483](https://github.com/firefly-iii/firefly-iii/issues/1483) | ||||
| - Make sure docker directories exist [issue 1500](https://github.com/firefly-iii/firefly-iii/issues/1500) | ||||
| - Broken link to bill edit [issue 1505](https://github.com/firefly-iii/firefly-iii/issues/1505) | ||||
| - Several bugs in the editing of split transactions [issue 1509](https://github.com/firefly-iii/firefly-iii/issues/1509) | ||||
| - Import routine ignored formatting of several date fields [issue 1510](https://github.com/firefly-iii/firefly-iii/issues/1510) | ||||
| - Piggy bank events now show the correct currency [issue 1446](https://github.com/firefly-iii/firefly-iii/issues/1446) | ||||
| - Inactive accounts are no longer suggested [issue 1463](https://github.com/firefly-iii/firefly-iii/issues/1463) | ||||
| - Some income / expense charts are less confusing [issue 1518](https://github.com/firefly-iii/firefly-iii/issues/1518) | ||||
| - Validation bug in multi-currency create view [issue 1521](https://github.com/firefly-iii/firefly-iii/issues/1521) | ||||
|  | ||||
| # 4.7.4 | ||||
| - [Issue 1409](https://github.com/firefly-iii/firefly-iii/issues/1409), add Indian Rupee and explain that users can do this themselves [issue 1413](https://github.com/firefly-iii/firefly-iii/issues/1413) | ||||
| - [Issue 1445](https://github.com/firefly-iii/firefly-iii/issues/1445), upgrade Curl in Docker image. | ||||
| - [Issue 1386](https://github.com/firefly-iii/firefly-iii/issues/1386), quick links to often used pages. | ||||
| - [Issue 1405](https://github.com/firefly-iii/firefly-iii/issues/1405), show proposed amount to piggy banks. | ||||
| - [Issue 1416](https://github.com/firefly-iii/firefly-iii/issues/1416), ability to delete lost attachments. | ||||
| - A completely rewritten import routine that can handle bunq (thanks everybody for testing!), CSV files and Spectre. Please make sure you read about this at http://bit.ly/FF3-new-import | ||||
| - [Issue 1392](https://github.com/firefly-iii/firefly-iii/issues/1392), explicitly mention rules are inactive (when they are). | ||||
| - [Issue 1406](https://github.com/firefly-iii/firefly-iii/issues/1406), bill conversion to rules will be smarter about the rules they create. | ||||
| - [Issue 1369](https://github.com/firefly-iii/firefly-iii/issues/1369), you can now properly order piggy banks again. | ||||
| - [Issue 1389](https://github.com/firefly-iii/firefly-iii/issues/1389), null-pointer in the import routine. | ||||
| - [Issue 1400](https://github.com/firefly-iii/firefly-iii/issues/1400), missing translation. | ||||
| - [Issue 1403](https://github.com/firefly-iii/firefly-iii/issues/1403), bill would always be marked as inactive in edit screen. | ||||
| - [Issue 1418](https://github.com/firefly-iii/firefly-iii/issues/1418), missing note text on bill page. | ||||
| - Export routine would break when encountering un-decryptable files. | ||||
| - [Issue 1425](https://github.com/firefly-iii/firefly-iii/issues/1425), empty fields when edit multiple transactions at once. | ||||
| - [Issue 1449](https://github.com/firefly-iii/firefly-iii/issues/1449), bad calculations in "budget left to spend" view. | ||||
| - [Issue 1451](https://github.com/firefly-iii/firefly-iii/issues/1451), same but in another view. | ||||
| - [Issue 1453](https://github.com/firefly-iii/firefly-iii/issues/1453), same as [issue 1403](https://github.com/firefly-iii/firefly-iii/issues/1403). | ||||
| - [Issue 1455](https://github.com/firefly-iii/firefly-iii/issues/1455), could add income to a budget. | ||||
| - [Issue 1442](https://github.com/firefly-iii/firefly-iii/issues/1442), issues with editing a split deposit. | ||||
| - [Issue 1452](https://github.com/firefly-iii/firefly-iii/issues/1452), date range problems with tags. | ||||
| - [Issue 1458](https://github.com/firefly-iii/firefly-iii/issues/1458), same for transactions. | ||||
| - [Issue 1415](https://github.com/firefly-iii/firefly-iii/issues/1415), will email you when OAuth2 keys are generated. | ||||
|  | ||||
| # 4.7.3.2 | ||||
| - Forgot to increase the version number :(. | ||||
|  | ||||
| # 4.7.3.1 | ||||
| - Fixed a critical bug where the rules-engine would fire inadvertently. | ||||
|  | ||||
| # 4.7.3 | ||||
| - Currency added to API | ||||
| - Firfely III will also generate a cash wallet for new users. | ||||
| - Can now reset Spectre and bunq settings | ||||
| - Docker file has a time zone | ||||
| - Allow database connection to be configured in Docker file | ||||
| - Can now view and edit attachments in edit-screen | ||||
| - User can visit hidden `/attachments` page | ||||
| - [Issue 1356](https://github.com/firefly-iii/firefly-iii/issues/1356): Budgets will show the remaining amount per day | ||||
| - [Issue 1367](https://github.com/firefly-iii/firefly-iii/issues/1367): Rules now come in strict and non-strict mode. | ||||
| - Added a security.txt | ||||
| - More support for trusted proxies | ||||
| - Improved edit routine for split transactions. | ||||
| - Upgrade routine can handle `proc_close` being disabled. | ||||
| - Bills now use rules to match transactions, making it more flexible. | ||||
| - [Issue 1328](https://github.com/firefly-iii/firefly-iii/issues/1328): piggy banks no have a more useful chart. | ||||
| - Spectre API upgraded to v4 | ||||
| - Move to MariaDB ([issue 1366](https://github.com/firefly-iii/firefly-iii/issues/1366)) | ||||
| - Piggy banks take currency from parent account ([issue 1334](https://github.com/firefly-iii/firefly-iii/issues/1334)) | ||||
| - [Issue 1341](https://github.com/firefly-iii/firefly-iii/issues/1341): Removed depricated command from dockerfile | ||||
| - Several issues with docker image ([issue 1320](https://github.com/firefly-iii/firefly-iii/issues/1320), [issue 1382](https://github.com/firefly-iii/firefly-iii/issues/1382)). | ||||
| - Fix giant tags and division by zero ([issue 1325](https://github.com/firefly-iii/firefly-iii/issues/1325) and others) | ||||
| - Several issues with bunq import ([issue 1352](https://github.com/firefly-iii/firefly-iii/issues/1352), [issue 1330](https://github.com/firefly-iii/firefly-iii/issues/1330), [issue 1378](https://github.com/firefly-iii/firefly-iii/issues/1378), [issue 1380](https://github.com/firefly-iii/firefly-iii/issues/1380)) | ||||
| - [Issue 1246](https://github.com/firefly-iii/firefly-iii/issues/1246): date picker is internationalised | ||||
| - [Issue 1327](https://github.com/firefly-iii/firefly-iii/issues/1327): fix formattting issues in piggy banks | ||||
| - [Issue 1348](https://github.com/firefly-iii/firefly-iii/issues/1348): 500 error in API | ||||
| - [Issue 1349](https://github.com/firefly-iii/firefly-iii/issues/1349): Errors in import routine | ||||
| - Several fixes for (multi-currency) reconciliation ([issue 1336](https://github.com/firefly-iii/firefly-iii/issues/1336), [issue 1363](https://github.com/firefly-iii/firefly-iii/issues/1363)) | ||||
| - [Issue 1353](https://github.com/firefly-iii/firefly-iii/issues/1353): return NULL values in range-indicator | ||||
| - Bug in split transaction edit routine | ||||
| - Piggy bank percentage was very specific. | ||||
| - Logging in Slack is easier to config. | ||||
| - [Issue 1312](https://github.com/firefly-iii/firefly-iii/issues/1312) Import broken for ING accounts | ||||
| - [Issue 1313](https://github.com/firefly-iii/firefly-iii/issues/1313) Error when creating new asset account | ||||
| - [Issue 1317](https://github.com/firefly-iii/firefly-iii/issues/1317) Forgot an include :( | ||||
| - Null pointer exception in transaction overview. | ||||
| - Installations running in subdirs were incapable of creating OAuth tokens. | ||||
| - OAuth keys were not created in all cases. | ||||
|  | ||||
| # 4.7.2 | ||||
| - [Issue 1123](https://github.com/firefly-iii/firefly-iii/issues/1123) First browser based update routine. | ||||
| - Add support for Italian. | ||||
| - [Issue 1232](https://github.com/firefly-iii/firefly-iii/issues/1232) Allow user to specify Docker database port. | ||||
| - [Issue 1197](https://github.com/firefly-iii/firefly-iii/issues/1197) Beter account list overview  | ||||
| - [Issue 1202](https://github.com/firefly-iii/firefly-iii/issues/1202) Some budgetary warnings  | ||||
| - [Issue 1284](https://github.com/firefly-iii/firefly-iii/issues/1284) Experimental support for bunq import | ||||
| - [Issue 1248](https://github.com/firefly-iii/firefly-iii/issues/1248) Ability to import BIC, ability to import SEPA fields.  | ||||
| - [Issue 1102](https://github.com/firefly-iii/firefly-iii/issues/1102) Summary line for bills  | ||||
| - More info to debug page. | ||||
| - [Issue 1186](https://github.com/firefly-iii/firefly-iii/issues/1186) You can see the latest account balance in CRUD forms  | ||||
| - Add Kubernetes YAML files, kindly created by a FF3 user. | ||||
| - [Issue 1244](https://github.com/firefly-iii/firefly-iii/issues/1244) Better line for "today" marker and add it to other chart as well ([issue 1214](https://github.com/firefly-iii/firefly-iii/issues/1214)) | ||||
| - [Issue 1219](https://github.com/firefly-iii/firefly-iii/issues/1219) Languages in dropdown  | ||||
| - [Issue 1189](https://github.com/firefly-iii/firefly-iii/issues/1189) Inactive accounts get removed from net worth  | ||||
| - [Issue 1220](https://github.com/firefly-iii/firefly-iii/issues/1220) Attachment description and notes migrated to just "notes".  | ||||
| - [Issue 1236](https://github.com/firefly-iii/firefly-iii/issues/1236) Multi currency balance box  | ||||
| - [Issue 1240](https://github.com/firefly-iii/firefly-iii/issues/1240) Better overview for accounts.  | ||||
| - [Issue 1292](https://github.com/firefly-iii/firefly-iii/issues/1292) Removed some charts from the "all"-overview of budgets and categories  | ||||
| - [Issue 1245](https://github.com/firefly-iii/firefly-iii/issues/1245) Improved recognition of IBANs  | ||||
| - Improved import routine. | ||||
| - Update notifier will wait three days before notifying users. | ||||
| - [Issue 1300](https://github.com/firefly-iii/firefly-iii/issues/1300) Virtual balance of credit cards does not count for net worth  | ||||
| - [Issue 1247](https://github.com/firefly-iii/firefly-iii/issues/1247) Can now see overspent amount  | ||||
| - [Issue 1221](https://github.com/firefly-iii/firefly-iii/issues/1221) Upgrade to Laravel 5.6  | ||||
| - [Issue 1187](https://github.com/firefly-iii/firefly-iii/issues/1187) Updated the password verifier to use Troy Hunt's new API  | ||||
| - Revenue chart is now on frontpage permanently | ||||
| - [Issue 1153](https://github.com/firefly-iii/firefly-iii/issues/1153) 2FA settings are in your profile now  | ||||
| - [Issue 1227](https://github.com/firefly-iii/firefly-iii/issues/1227) Can set the timezone in config or in Docker  | ||||
| - [Issue 1294](https://github.com/firefly-iii/firefly-iii/issues/1294) Ability to link a transaction to itself  | ||||
| - Correct reference to journal description in split form. | ||||
| - [Issue 1234](https://github.com/firefly-iii/firefly-iii/issues/1234) Fix budget page issues in SQLite  | ||||
| - [Issue 1262](https://github.com/firefly-iii/firefly-iii/issues/1262) Can now use double and epty headers in CSV files  | ||||
| - [Issue 1258](https://github.com/firefly-iii/firefly-iii/issues/1258) Fixed a possible date mismatch in piggy banks | ||||
| - [Issue 1283](https://github.com/firefly-iii/firefly-iii/issues/1283) Bulk delete was broken  | ||||
| - [Issue 1293](https://github.com/firefly-iii/firefly-iii/issues/1293) Layout problem with notes  | ||||
| - [Issue 1257](https://github.com/firefly-iii/firefly-iii/issues/1257) Improve transaction lists query count  | ||||
| - [Issue 1291](https://github.com/firefly-iii/firefly-iii/issues/1291) Fixer IO problems  | ||||
| - [Issue 1239](https://github.com/firefly-iii/firefly-iii/issues/1239) Could not edit expense or revenue accounts ([issue 1298](https://github.com/firefly-iii/firefly-iii/issues/1298))  | ||||
| - [Issue 1297](https://github.com/firefly-iii/firefly-iii/issues/1297) Could not convert to withdrawal  | ||||
| - [Issue 1226](https://github.com/firefly-iii/firefly-iii/issues/1226) Category overview in default report shows no income.  | ||||
| - Various other bugs and problems ([issue 1198](https://github.com/firefly-iii/firefly-iii/issues/1198), [issue 1213](https://github.com/firefly-iii/firefly-iii/issues/1213), [issue 1237](https://github.com/firefly-iii/firefly-iii/issues/1237), [issue 1238](https://github.com/firefly-iii/firefly-iii/issues/1238), [issue 1199](https://github.com/firefly-iii/firefly-iii/issues/1199), [issue 1200](https://github.com/firefly-iii/firefly-iii/issues/1200)) | ||||
| - Fixed an issue with token validation on the command line. | ||||
|  | ||||
| # 4.7.1 | ||||
| - A brand new API. Read about it in the [documentation](http://firefly-iii.readthedocs.io/en/latest/). | ||||
| - Add support for Spanish. [issue 1194](https://github.com/firefly-iii/firefly-iii/issues/1194) | ||||
| - Some custom preferences are selected by default for a better user experience. | ||||
| - Some new currencies [issue 1211](https://github.com/firefly-iii/firefly-iii/issues/1211) | ||||
| - Fixed [issue 1155](https://github.com/firefly-iii/firefly-iii/issues/1155) (reported by [ndandanov](https://github.com/ndandanov)) | ||||
| - [Issue 1156](https://github.com/firefly-iii/firefly-iii/issues/1156) [issue 1182](https://github.com/firefly-iii/firefly-iii/issues/1182) and other issues related to SQLite databases. | ||||
| - Multi-page budget overview was broken (reported by [jinformatique](https://github.com/jinformatique)) | ||||
| - Importing CSV files with semi-colons in them did not work [issue 1172](https://github.com/firefly-iii/firefly-iii/issues/1172) [issue 1183](https://github.com/firefly-iii/firefly-iii/issues/1183) [issue 1210](https://github.com/firefly-iii/firefly-iii/issues/1210) | ||||
| - Could not use account number that was in use by a deleted account [issue 1174](https://github.com/firefly-iii/firefly-iii/issues/1174)  | ||||
| - Fixed spelling error that lead to 404's [issue 1175](https://github.com/firefly-iii/firefly-iii/issues/1175) [issue 1190](https://github.com/firefly-iii/firefly-iii/issues/1190) | ||||
| - Fixed tag autocomplete [issue 1178](https://github.com/firefly-iii/firefly-iii/issues/1178) | ||||
| - Better links for "new transaction" buttons [issue 1185](https://github.com/firefly-iii/firefly-iii/issues/1185) | ||||
| - Cache errors in budget charts [issue 1192](https://github.com/firefly-iii/firefly-iii/issues/1192) | ||||
| - Deleting transactions that are linked to other other transactions would lead to errors [issue 1209](https://github.com/firefly-iii/firefly-iii/issues/1209) | ||||
|  | ||||
| # 4.7.0 | ||||
| - Support for Russian and Portuguese (Brazil) | ||||
| - Support for the Spectre API (Salt Edge) | ||||
| - Many strings now translatable thanks to [Nik-vr](https://github.com/Nik-vr) ([issue 1118](https://github.com/firefly-iii/firefly-iii/issues/1118), [issue 1116](https://github.com/firefly-iii/firefly-iii/issues/1116), [issue 1109](https://github.com/firefly-iii/firefly-iii/issues/1109), ) | ||||
| - Many buttons to quickly create stuff | ||||
| - Sum of tables in reports, requested by [MacPaille](https://github.com/MacPaille) ([issue 1106](https://github.com/firefly-iii/firefly-iii/issues/1106)) | ||||
| - Future versions of Firefly III will notify you there is a new version, as suggested by [8bitgentleman](https://github.com/8bitgentleman) in [issue 1050](https://github.com/firefly-iii/firefly-iii/issues/1050) | ||||
| - Improved net worth box [issue 1101](https://github.com/firefly-iii/firefly-iii/issues/1101) ([Nik-vr](https://github.com/Nik-vr)) | ||||
| - Nice dropdown in transaction list [issue 1082](https://github.com/firefly-iii/firefly-iii/issues/1082) | ||||
| - Better support for local fonts thanks to [devlearner](https://github.com/devlearner) ([issue 1145](https://github.com/firefly-iii/firefly-iii/issues/1145)) | ||||
| - Improve attachment support and view capabilities (suggested by [trinhit](https://github.com/trinhit) in [issue 1146](https://github.com/firefly-iii/firefly-iii/issues/1146)) | ||||
| - Whole new [read me file](https://github.com/firefly-iii/firefly-iii/blob/master/readme.md), [new end user documentation](https://firefly-iii.readthedocs.io/en/latest/) and an [updated website](https://www.firefly-iii.org/)! | ||||
| - Many charts and info-blocks now scale property ([issue 989](https://github.com/firefly-iii/firefly-iii/issues/989) and [issue 1040](https://github.com/firefly-iii/firefly-iii/issues/1040)) | ||||
| - Charts work in IE thanks to [devlearner](https://github.com/devlearner) ([issue 1107](https://github.com/firefly-iii/firefly-iii/issues/1107)) | ||||
| - Various fixes in import routine | ||||
| - Bug that left charts empty ([issue 1088](https://github.com/firefly-iii/firefly-iii/issues/1088)), reported by various users amongst which [jinformatique](https://github.com/jinformatique) | ||||
| - [Issue 1124](https://github.com/firefly-iii/firefly-iii/issues/1124), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1125](https://github.com/firefly-iii/firefly-iii/issues/1125), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1126](https://github.com/firefly-iii/firefly-iii/issues/1126), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1131](https://github.com/firefly-iii/firefly-iii/issues/1131), as reported by [dp87](https://github.com/dp87) | ||||
| - [Issue 1129](https://github.com/firefly-iii/firefly-iii/issues/1129), as reported by [gavu](https://github.com/gavu) | ||||
| - [Issue 1132](https://github.com/firefly-iii/firefly-iii/issues/1132), as reported by [gavu](https://github.com/gavu) | ||||
| - Issue with cache in Sandstorm ([issue 1130](https://github.com/firefly-iii/firefly-iii/issues/1130)) | ||||
| - [Issue 1134](https://github.com/firefly-iii/firefly-iii/issues/1134) | ||||
| - [Issue 1140](https://github.com/firefly-iii/firefly-iii/issues/1140) | ||||
| - [Issue 1141](https://github.com/firefly-iii/firefly-iii/issues/1141), reported by [ErikFontanel](https://github.com/ErikFontanel) | ||||
| - [Issue 1142](https://github.com/firefly-iii/firefly-iii/issues/1142) | ||||
| - Removed many access rights from the demo user | ||||
|  | ||||
| # 4.6.13 | ||||
| - [Issue 1074](https://github.com/firefly-iii/firefly-iii/issues/1074), suggested by [MacPaille](https://github.com/MacPaille) | ||||
| - [Issue 1077](https://github.com/firefly-iii/firefly-iii/issues/1077), suggested by [wtercato](https://github.com/wtercato) | ||||
|   | ||||
| @@ -9,6 +9,10 @@ CURL_OPTS="--silent --show-error" | ||||
| echo localhost > /etc/hostname | ||||
| hostname localhost | ||||
|  | ||||
| # Install curl that is needed below. | ||||
| apt-get update | ||||
| apt-get install -y curl | ||||
|  | ||||
| # The following line copies stderr through stderr to cat without accidentally leaving it in the | ||||
| # output file. Be careful when changing. See: https://github.com/sandstorm-io/vagrant-spk/pull/159 | ||||
| curl $CURL_OPTS https://install.sandstorm.io/ 2>&1 > /host-dot-sandstorm/caches/install.sh | cat | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| # Runs every time we create a new grain! | ||||
| echo "Now in launcher.sh" | ||||
|  | ||||
| # Create a bunch of folders under the clean /var that php, nginx, and mysql expect to exist | ||||
| mkdir -p /var/lib/mysql | ||||
| @@ -30,22 +31,21 @@ mkdir -p /var/storage/framework/views | ||||
| mkdir -p /var/storage/logs | ||||
| mkdir -p /var/storage/upload | ||||
|  | ||||
|  | ||||
| # Ensure mysql tables created | ||||
| HOME=/etc/mysql /usr/bin/mysql_install_db --force | ||||
|  | ||||
| # Spawn mysqld, php | ||||
| HOME=/etc/mysql /usr/sbin/mysqld & | ||||
|  | ||||
| /usr/sbin/php-fpm7.1 --nodaemonize --fpm-config /etc/php/7.1/fpm/php-fpm.conf & | ||||
| /usr/sbin/php-fpm7.2 --nodaemonize --fpm-config /etc/php/7.2/fpm/php-fpm.conf & | ||||
|  | ||||
| # Wait until mysql and php have bound their sockets, indicating readiness | ||||
| while [ ! -e /var/run/mysqld/mysqld.sock ] ; do | ||||
|     echo "waiting for mysql to be available at /var/run/mysqld/mysqld.sock" | ||||
|     sleep .5 | ||||
| done | ||||
| while [ ! -e /var/run/php7.1-fpm.sock ] ; do | ||||
|     echo "waiting for php7.1-fpm to be available at /var/run/php7.1-fpm.sock" | ||||
| while [ ! -e /var/run/php7.2-fpm.sock ] ; do | ||||
|     echo "waiting for php7.2-fpm to be available at /var/run/php7.2-fpm.sock" | ||||
|     sleep .5 | ||||
| done | ||||
|  | ||||
| @@ -58,5 +58,9 @@ echo "Migrating..." | ||||
| php /opt/app/artisan migrate --seed --force | ||||
| echo "Done!" | ||||
|  | ||||
| echo "Clear cache.." | ||||
| php /opt/app/artisan cache:clear | ||||
| echo "Done" | ||||
|  | ||||
| # Start nginx. | ||||
| /usr/sbin/nginx -c /opt/app/.sandstorm/service-config/nginx.conf -g "daemon off;" | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -15,8 +15,8 @@ const pkgdef :Spk.PackageDefinition = ( | ||||
|  | ||||
|   manifest = ( | ||||
|     appTitle = (defaultText = "Firefly III"), | ||||
|     appVersion = 7, | ||||
|     appMarketingVersion = (defaultText = "4.6.13"), | ||||
|     appVersion = 17, | ||||
|     appMarketingVersion = (defaultText = "4.7.7"), | ||||
|  | ||||
|     actions = [ | ||||
|       # Define your "new document" handlers here. | ||||
| @@ -65,9 +65,9 @@ const pkgdef :Spk.PackageDefinition = ( | ||||
|         # Sizes are given in device-independent pixels, so if you took these | ||||
|         # screenshots on a Retina-style high DPI screen, divide each dimension by two. | ||||
|  | ||||
|         (width = 1291, height = 800, png = embed "screenshots/screenshot-1.png"), | ||||
|         (width = 1291, height = 800, png = embed "screenshots/screenshot-2.png"), | ||||
|         (width = 1291, height = 800, png = embed "screenshots/screenshot-3.png"), | ||||
|         (width = 1290, height = 800, png = embed "screenshots/screenshot-1.png"), | ||||
|         (width = 1290, height = 800, png = embed "screenshots/screenshot-2.png"), | ||||
|         (width = 1290, height = 800, png = embed "screenshots/screenshot-3.png"), | ||||
|  | ||||
|       ], | ||||
|       changeLog = (defaultText = embed "changelog.md"), | ||||
|   | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 173 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 171 KiB | 
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 107 KiB After Width: | Height: | Size: 163 KiB | 
| @@ -53,10 +53,11 @@ http { | ||||
| 		} | ||||
| 		location ~ \.php$ { | ||||
| 			try_files $uri =404; | ||||
|             fastcgi_pass unix:/var/run/php7.1-fpm.sock; | ||||
|             fastcgi_pass unix:/var/run/php7.2-fpm.sock; | ||||
|             fastcgi_index index.php; | ||||
|             fastcgi_split_path_info ^(.+\.php)(/.+)$; | ||||
| 			fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name; | ||||
| 			fastcgi_read_timeout 900; | ||||
|  | ||||
|  | ||||
| 			fastcgi_param  QUERY_STRING       $query_string; | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|  | ||||
| # When you change this file, you must take manual action. Read this doc: | ||||
| # - https://docs.sandstorm.io/en/latest/vagrant-spk/customizing/#setupsh | ||||
| echo "Now in setup.sh" | ||||
|  | ||||
| set -euo pipefail | ||||
|  | ||||
| @@ -14,8 +15,13 @@ apt-get install -y python-software-properties software-properties-common | ||||
| # install all languages | ||||
| sed -i 's/# de_DE.UTF-8 UTF-8/de_DE.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# fr_FR.UTF-8 UTF-8/fr_FR.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# it_IT.UTF-8 UTF-8/it_IT.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# nl_NL.UTF-8 UTF-8/nl_NL.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# pl_PL.UTF-8 UTF-8/pl_PL.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# pt_BR.UTF-8 UTF-8/pt_BR.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# ru_RU.UTF-8 UTF-8/ru_RU.UTF-8 UTF-8/g' /etc/locale.gen | ||||
| sed -i 's/# tr_TR.UTF-8 UTF-8/tr_TR.UTF-8 UTF-8/g' /etc/locale.gen | ||||
|  | ||||
| dpkg-reconfigure --frontend=noninteractive locales | ||||
|  | ||||
|  | ||||
| @@ -26,43 +32,43 @@ apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E9C74FEEA2098A6E | ||||
| add-apt-repository "deb http://packages.dotdeb.org jessie all" | ||||
|  | ||||
| # add another repos | ||||
| apt-get install apt-transport-https lsb-release ca-certificates | ||||
| apt-get install -y apt-transport-https lsb-release ca-certificates | ||||
| wget -O /etc/apt/trusted.gpg.d/php.gpg https://packages.sury.org/php/apt.gpg | ||||
| echo "deb https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list | ||||
|  | ||||
| # install packages. | ||||
| apt-get update | ||||
| apt-get install -y nginx php7.1-fpm php7.1-mysql php7.1-gd php7.1-cli php7.1-curl git php7.1-dev php7.1-zip php7.1-intl php7.1-dom php7.1-mbstring php7.1-bcmath mysql-server | ||||
| apt-get install -y nginx php7.2-fpm php7.2-mysql php7.2-gd php7.2-cli php7.2-curl git php7.2-dev php7.2-zip php7.2-intl php7.2-dom php7.2-mbstring php7.2-bcmath mysql-server | ||||
| service nginx stop | ||||
| service php7.1-fpm stop | ||||
| service php7.2-fpm stop | ||||
| service mysql stop | ||||
| systemctl disable nginx | ||||
| systemctl disable php7.1-fpm | ||||
| systemctl disable php7.2-fpm | ||||
| systemctl disable mysql | ||||
|  | ||||
| # make php.ini display errors: | ||||
| sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.1/fpm/php.ini | ||||
| sed -i 's/display_errors = Off/display_errors = On/g' /etc/php/7.2/fpm/php.ini | ||||
|  | ||||
| # patch /etc/php/7.1/fpm/pool.d/www.conf to not change uid/gid to www-data | ||||
| # patch /etc/php/7.2/fpm/pool.d/www.conf to not change uid/gid to www-data | ||||
| sed --in-place='' \ | ||||
|        --expression='s/^listen.owner = www-data/;listen.owner = www-data/' \ | ||||
|        --expression='s/^listen.group = www-data/;listen.group = www-data/' \ | ||||
|        /etc/php/7.1/fpm/pool.d/www.conf | ||||
| # patch /etc/php/7.1/fpm/php-fpm.conf to not have a pidfile | ||||
|        /etc/php/7.2/fpm/pool.d/www.conf | ||||
| # patch /etc/php/7.2/fpm/php-fpm.conf to not have a pidfile | ||||
| sed --in-place='' \ | ||||
|        --expression='s/^pid =/;pid =/' \ | ||||
|        /etc/php/7.1/fpm/php-fpm.conf | ||||
|        /etc/php/7.2/fpm/php-fpm.conf | ||||
|  | ||||
| # move sock file to better dir: | ||||
| sed --in-place='' \ | ||||
|        --expression='s/^listen = \/run\/php\/php7.1-fpm.sock/listen = \/var\/run\/php7.1-fpm.sock/' \ | ||||
|        /etc/php/7.1/fpm/pool.d/www.conf | ||||
|        --expression='s/^listen = \/run\/php\/php7.2-fpm.sock/listen = \/var\/run\/php7.2-fpm.sock/' \ | ||||
|        /etc/php/7.2/fpm/pool.d/www.conf | ||||
|  | ||||
| # patch /etc/php/7.1/fpm/pool.d/www.conf to no clear environment variables | ||||
| # patch /etc/php/7.2/fpm/pool.d/www.conf to no clear environment variables | ||||
| # so we can pass in SANDSTORM=1 to apps | ||||
| sed --in-place='' \ | ||||
|        --expression='s/^;clear_env = no/clear_env=no/' \ | ||||
|        /etc/php/7.1/fpm/pool.d/www.conf | ||||
|        /etc/php/7.2/fpm/pool.d/www.conf | ||||
| # patch mysql conf to not change uid, and to use /var/tmp over /tmp | ||||
| # for secure-file-priv see https://github.com/sandstorm-io/vagrant-spk/issues/195 | ||||
| sed --in-place='' \ | ||||
|   | ||||
							
								
								
									
										105
									
								
								.scrutinizer.yml
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								.scrutinizer.yml
									
									
									
									
									
								
							| @@ -1,51 +1,58 @@ | ||||
| # .scrutinizer.yml | ||||
| tools: | ||||
|   external_code_coverage: false | ||||
| filter: | ||||
|   paths: | ||||
| ---  | ||||
| build:  | ||||
|   nodes:  | ||||
|     analysis:  | ||||
|       project_setup:  | ||||
|         override: true | ||||
|       tests:  | ||||
|         override:  | ||||
|           - php-scrutinizer-run | ||||
| checks:  | ||||
|   javascript: true | ||||
|   php:  | ||||
|     align_assignments: true | ||||
|     avoid_fixme_comments: true | ||||
|     avoid_multiple_statements_on_same_line: true | ||||
|     avoid_perl_style_comments: true | ||||
|     avoid_todo_comments: true | ||||
|     duplication: false | ||||
|     encourage_single_quotes: true | ||||
|     newline_at_end_of_file: true | ||||
|     no_goto: true | ||||
|     no_long_variable_names:  | ||||
|       maximum: "20" | ||||
|     no_short_method_names:  | ||||
|       minimum: "3" | ||||
|     no_short_variable_names:  | ||||
|       minimum: "3" | ||||
|     optional_parameters_at_the_end: true | ||||
|     parameter_doc_comments: true | ||||
|     remove_extra_empty_lines: true | ||||
|     return_doc_comment_if_not_inferrable: true | ||||
|     return_doc_comments: true | ||||
|     uppercase_constants: true | ||||
|     use_self_instead_of_fqcn: true | ||||
| coding_style:  | ||||
|   php:  | ||||
|     spaces:  | ||||
|       around_operators:  | ||||
|         concatenation: true | ||||
|       other:  | ||||
|         after_type_cast: false | ||||
| filter:  | ||||
|   excluded_paths:  | ||||
|     - database/migrations/* | ||||
|     - bootstrap/* | ||||
|     - config/* | ||||
|     - docker/* | ||||
|     - public/js/lib/* | ||||
|     - public/lib/adminlte/js/* | ||||
|     - public/lib/bootstrap/js/* | ||||
|     - resources/* | ||||
|     - routes/* | ||||
|     - storage/* | ||||
|   paths:  | ||||
|     - app/* | ||||
|     - public/js/ff/* | ||||
|   excluded_paths: | ||||
|     - "database/migrations/*" | ||||
|     - "bootstrap/*" | ||||
|     - "config/*" | ||||
|     - "docker/*" | ||||
|     - "public/js/lib/*" | ||||
|     - "public/lib/adminlte/js/*" | ||||
|     - "public/lib/bootstrap/js/*" | ||||
|     - "resources/*" | ||||
|     - "routes/*" | ||||
|     - "storage/*" | ||||
| checks: | ||||
|     php: | ||||
|         use_self_instead_of_fqcn: true | ||||
|         uppercase_constants: true | ||||
|         return_doc_comments: true | ||||
|         return_doc_comment_if_not_inferrable: true | ||||
|         remove_extra_empty_lines: true | ||||
|         parameter_doc_comments: true | ||||
|         optional_parameters_at_the_end: true | ||||
|         no_short_variable_names: | ||||
|             minimum: '3' | ||||
|         no_short_method_names: | ||||
|             minimum: '3' | ||||
|         no_long_variable_names: | ||||
|             maximum: '20' | ||||
|         no_goto: true | ||||
|         newline_at_end_of_file: true | ||||
|         encourage_single_quotes: true | ||||
|         avoid_todo_comments: true | ||||
|         avoid_perl_style_comments: true | ||||
|         avoid_fixme_comments: true | ||||
|         avoid_multiple_statements_on_same_line: true | ||||
|         align_assignments: true | ||||
|         duplication: false | ||||
|     javascript: true | ||||
|  | ||||
| coding_style: | ||||
|     php: | ||||
|         spaces: | ||||
|             around_operators: | ||||
|                 concatenation: true | ||||
|             other: | ||||
|                 after_type_cast: false | ||||
| tools:  | ||||
|   external_code_coverage: false | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| language: php | ||||
| php: | ||||
|   - 7.1 | ||||
|   - 7.2 | ||||
|  | ||||
| cache: | ||||
| @@ -13,14 +12,12 @@ install: | ||||
|   - composer update --no-scripts | ||||
|   - cp .env.testing .env | ||||
|   - php artisan clear-compiled | ||||
|   - php artisan optimize | ||||
|   - php artisan env | ||||
|   - cp .env.testing .env | ||||
|   - wget -q https://github.com/firefly-iii/test-data/raw/master/storage/database.sqlite -O storage/database/database.sqlite | ||||
|   - mkdir -p build/logs | ||||
|  | ||||
| script: | ||||
|   - phpunit -c phpunit.coverage.xml | ||||
|   - ./vendor/bin/phpunit -c phpunit.coverage.xml | ||||
|  | ||||
| after_success: | ||||
|   - travis_retry php vendor/bin/php-coveralls -x storage/build/clover-all.xml | ||||
| @@ -29,4 +26,4 @@ after_success: | ||||
| branches: | ||||
|   only: | ||||
|   - develop | ||||
|   - master | ||||
|   - master | ||||
|   | ||||
							
								
								
									
										85
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								Dockerfile
									
									
									
									
									
								
							| @@ -1,37 +1,85 @@ | ||||
| # use PHP 7.1 and Apache as a base. | ||||
| FROM php:7.1-apache | ||||
| FROM php:7.2-apache | ||||
|  | ||||
| # If building on a RPi, use --build-arg cores=3 to use all cores when compiling | ||||
| # to speed up the image build | ||||
| ARG CORES | ||||
| ENV CORES ${CORES:-1} | ||||
|  | ||||
| ENV FIREFLY_PATH /var/www/firefly-iii/ | ||||
| ENV CURL_VERSION 7.60.0 | ||||
| ENV OPENSSL_VERSION 1.1.1-pre6 | ||||
|  | ||||
| LABEL version="1.0" maintainer="thegrumpydictator@gmail.com" | ||||
|  | ||||
| # set working dir | ||||
| ENV FIREFLY_PATH /var/www/firefly-iii | ||||
| WORKDIR $FIREFLY_PATH | ||||
| ADD . $FIREFLY_PATH | ||||
|  | ||||
| # install packages | ||||
| RUN apt-get update -y && \ | ||||
|     apt-get install -y --no-install-recommends libcurl4-openssl-dev \ | ||||
|                                                zlib1g-dev \ | ||||
|                                                libjpeg62-turbo-dev \ | ||||
|                                                libpng12-dev \ | ||||
|                                                wget \ | ||||
|                                                libpng-dev \ | ||||
|                                                libicu-dev \ | ||||
|                                                libedit-dev \ | ||||
|                                                libtidy-dev \ | ||||
|                                                libxml2-dev \ | ||||
|                                                unzip \ | ||||
|                                                libsqlite3-dev \ | ||||
|                                                nano \ | ||||
|                                                libpq-dev \ | ||||
|                                                libbz2-dev \ | ||||
|                                                gettext-base \ | ||||
|                                                cron \ | ||||
|                                                rsyslog \ | ||||
|                                                supervisor \ | ||||
|                                                locales && \ | ||||
|                                                apt-get clean && \ | ||||
|                                                rm -rf /var/lib/apt/lists/* | ||||
|  | ||||
| # Install latest curl | ||||
| RUN cd /tmp && \ | ||||
|     wget https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz && \ | ||||
|     tar -xvf openssl-${OPENSSL_VERSION}.tar.gz && \ | ||||
|     cd openssl-${OPENSSL_VERSION} && \ | ||||
|     ./config && \ | ||||
|     make -j${CORES} && \ | ||||
|     make install | ||||
|  | ||||
| RUN cd /tmp && \ | ||||
|     wget https://curl.haxx.se/download/curl-${CURL_VERSION}.tar.gz && \ | ||||
|     tar -xvf curl-${CURL_VERSION}.tar.gz && \ | ||||
|     cd curl-${CURL_VERSION} && \ | ||||
|     ./configure --with-ssl --host=$(gcc -dumpmachine) && \ | ||||
|     make -j${CORES} && \ | ||||
|     make install | ||||
|  | ||||
| # Make sure that libcurl is using the newer curl libaries | ||||
| RUN echo "/usr/local/lib" >> /etc/ld.so.conf.d/00-curl.conf && ldconfig | ||||
|  | ||||
| # Mimic the Debian/Ubuntu config file structure for supervisor | ||||
| COPY .deploy/docker/supervisord.conf /etc/supervisor/supervisord.conf | ||||
| RUN mkdir -p /etc/supervisor/conf.d /var/log/supervisor | ||||
|  | ||||
| # copy Firefly III supervisor conf file. | ||||
| COPY ./.deploy/docker/firefly-iii.conf /etc/supervisor/conf.d/firefly-iii.conf | ||||
|  | ||||
| # copy cron job supervisor conf file. | ||||
| COPY ./.deploy/docker/cronjob.conf /etc/supervisor/conf.d/cronjob.conf | ||||
|  | ||||
| # test crons added via crontab | ||||
| RUN echo "0 3 * * * /usr/local/bin/php /var/www/firefly-iii/artisan firefly:cron" | crontab - | ||||
| #RUN (crontab -l ; echo "*/1 * * * * free >> /var/www/firefly-iii/public/cron.html") 2>&1 | crontab - | ||||
| # Install PHP exentions. | ||||
| RUN docker-php-ext-install -j$(nproc) curl gd intl json readline tidy zip bcmath xml mbstring pdo_sqlite pdo_mysql bz2 pdo_pgsql | ||||
| RUN docker-php-ext-install -j$(nproc) gd intl tidy zip bcmath pdo_mysql bz2 pdo_pgsql | ||||
|  | ||||
| # Install composer | ||||
| RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer | ||||
|  | ||||
| # Generate locales supported by Firefly III | ||||
| RUN echo "de_DE.UTF-8 UTF-8\nen_US.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nid_ID.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8" > /etc/locale.gen && locale-gen | ||||
| RUN echo "en_US.UTF-8 UTF-8\nde_DE.UTF-8 UTF-8\nfr_FR.UTF-8 UTF-8\nit_IT.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npl_PL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8\nru_RU.UTF-8 UTF-8\ntr_TR.UTF-8 UTF-8\n\n" > /etc/locale.gen && locale-gen | ||||
|  | ||||
| # copy Apache config to correct spot. | ||||
| COPY ./docker/apache2.conf /etc/apache2/apache2.conf | ||||
| COPY ./.deploy/docker/apache2.conf /etc/apache2/apache2.conf | ||||
|  | ||||
| # Enable apache mod rewrite.. | ||||
| RUN a2enmod rewrite | ||||
| @@ -39,23 +87,28 @@ RUN a2enmod rewrite | ||||
| # Enable apache mod ssl.. | ||||
| RUN a2enmod ssl | ||||
|  | ||||
| # Create volumes for several directories: | ||||
| # Create volumes | ||||
| VOLUME $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload | ||||
|  | ||||
| # Setup the Composer installer | ||||
| RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer | ||||
|  | ||||
| # Enable default site (Firefly III) | ||||
| COPY ./docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf | ||||
| COPY ./.deploy/docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf | ||||
|  | ||||
| # Make sure we own Firefly III directory | ||||
| RUN chown -R www-data:www-data /var/www && chmod -R 775 $FIREFLY_PATH/storage | ||||
|  | ||||
| # Copy in Firefly Source | ||||
| WORKDIR $FIREFLY_PATH | ||||
| ADD . $FIREFLY_PATH | ||||
|  | ||||
| # Fix the link to curl: | ||||
| RUN rm -rf /usr/local/lib/libcurl.so.4 && ln -s /usr/lib/x86_64-linux-gnu/libcurl.so.4.4.0 /usr/local/lib/libcurl.so.4 | ||||
|  | ||||
| # Run composer | ||||
| ENV COMPOSER_ALLOW_SUPERUSER 1 | ||||
| RUN composer install --prefer-dist --no-dev --no-scripts --no-suggest | ||||
|  | ||||
| # Expose port 80 | ||||
| EXPOSE 80 | ||||
|  | ||||
| # Run entrypoint thing | ||||
| ENTRYPOINT ["docker/entrypoint.sh"] | ||||
| ENTRYPOINT [".deploy/docker/entrypoint.sh"] | ||||
|   | ||||
							
								
								
									
										89
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,89 +0,0 @@ | ||||
| # Firefly III: A personal finances manager  | ||||
|  | ||||
| [](https://secure.php.net/downloads.php) [](https://packagist.org/packages/grumpydictator/firefly-iii) [](https://www.gnu.org/licenses/gpl.html) [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)  | ||||
|  | ||||
| [](https://firefly-iii.org/static/screenshots/4.6.12/index.png) [](https://firefly-iii.org/static/screenshots/4.6.12/account.png) | ||||
|  | ||||
| [](https://firefly-iii.org/static/screenshots/4.6.12/budget.png) [](https://firefly-iii.org/static/screenshots/4.6.12/category.png) | ||||
|  | ||||
| [](https://firefly-iii.org/static/screenshots/4.6.12/report1.png) [](https://firefly-iii.org/static/screenshots/4.6.12/report2.png) | ||||
|  | ||||
| "Firefly III" is a financial manager for your personal finances. It can help you keep track of your expenses and income. | ||||
| Firefly III supports the use of budgets. You can categorize and tag your transactions. | ||||
| It also supports credit cards, shared  household accounts and savings accounts. | ||||
| There are many financial reports available. | ||||
|  | ||||
| ## Want to try Firefly III? | ||||
|  | ||||
| There is a **[demo site](https://demo.firefly-iii.org)** with an example financial administration already present. You can use Docker, Heroku or Sandstorm.io (see below) to quickly setup your own instance. | ||||
|  | ||||
| ## Install Firefly III | ||||
|  | ||||
| ### Using docker | ||||
|  | ||||
| You can use docker-compose to [set up your personal secure](https://firefly-iii.org/using-docker.html) Firefly III environment. Advanced users can use the Dockerfile directly.  | ||||
|  | ||||
| ### Using vagrant (or other VMs) | ||||
|  | ||||
| You can install Firefly III on any Linux or Windows machine. You'll need a web server (preferrably on Linux) and access to the command line. Please read the [installation guide](https://firefly-iii.org/using-installing.html). | ||||
|  | ||||
| ### Using Heroku | ||||
|  | ||||
| [](https://heroku.com/deploy?template=https://github.com/firefly-iii/firefly-iii/tree/master) | ||||
|  | ||||
| Register for a free Heroku account and instantly run Firefly III on your very own cloud instance. | ||||
|  | ||||
| ### Using Sandstorm.io | ||||
|  | ||||
| You can find Firefly III in [the Sandstorm.io marketplace](https://apps.sandstorm.io/app/uws252ya9mep4t77tevn85333xzsgrpgth8q4y1rhknn1hammw70). You can run it on your own installation or on Oasis. | ||||
|  | ||||
| ### Other options | ||||
|  | ||||
| Firefly III is also available as a package on [https://softaculous.com/](Softaculous) and [AMPPS](https://www.ampps.com/). | ||||
|  | ||||
| ## More about Firefly III | ||||
|  | ||||
| Personal financial management is pretty difficult, and everybody has their own approach to it. | ||||
| Some people make budgets, other people limit their cashflow by throwing away their credit cards,  | ||||
| others try to increase their current cashflow. There are tons of ways to save and earn money. | ||||
|  | ||||
| Firefly works on the principle that if you know where you're money is going, you can stop it from going there. | ||||
|  | ||||
| ### Some advantages of using Firefly | ||||
|  | ||||
| - Firefly can import any CSV file, so migrating from other systems is easy. | ||||
| - Firefly runs on your own server, so you are fully in control of your data. Remember, there is no such thing as "the cloud", it’s just somebody else’s computer! | ||||
| - Firefly has lots of features without being fancy or bloated. | ||||
| - If you feel you're missing something you can just ask me and I'll add it! | ||||
|  | ||||
| Firefly III has become pretty awesome over the years! (but please excuse me for bragging, it's just that I'm proud of it). | ||||
| [You can read more about Firefly III, and its features, on the website](https://firefly-iii.org/). | ||||
|  | ||||
| ### Contributing | ||||
|  | ||||
| Please read [CONTRIBUTING.md](https://github.com/firefly-iii/firefly-iii/blob/master/.github/CONTRIBUTING.md) for details on contributing, and the process for submitting pull requests. Please check out the [code of conduct](https://github.com/firefly-iii/firefly-iii/blob/master/CODE_OF_CONDUCT.md) as well. | ||||
|  | ||||
| ### Versioning | ||||
|  | ||||
| We use [SemVer](http://semver.org/) for versioning. For the versions available, see [the tags](https://github.com/firefly-iii/firefly-iii/tags) on this repository. | ||||
|  | ||||
| ### Authors | ||||
|  | ||||
| * James Cole | ||||
| * Over time, [many people have contributed to Firefly III](https://github.com/firefly-iii/firefly-iii/graphs/contributors). | ||||
|  | ||||
| ### License | ||||
|  | ||||
| This work [is licensed](https://github.com/firefly-iii/firefly-iii/blob/master/LICENSE) under the [GPL v3](https://www.gnu.org/licenses/gpl.html). | ||||
|  | ||||
| ### Other stuff | ||||
|  | ||||
| If you like Firefly III and if it helps you save lots of money, why not send me [a dime for every dollar saved](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA) (this is a joke, although the Paypal form works just fine, try it!) | ||||
|  | ||||
| If you want to contact me, please open an issue or [email me](mailto:thegrumpydictator@gmail.com). | ||||
|  | ||||
| ### Alternatives | ||||
|  | ||||
| If you are looking for alternatives, check out [Kickball's Awesome-Selfhosted list](https://github.com/Kickball/awesome-selfhosted) which features not only Firefly III but also noteworthy alternatives such as [Silverstrike](https://github.com/agstrike/silverstrike). | ||||
|  | ||||
| [](https://travis-ci.org/firefly-iii/firefly-iii) [](https://scrutinizer-ci.com/g/firefly-iii/firefly-iii/?branch=master) [](https://coveralls.io/github/firefly-iii/firefly-iii?branch=master) | ||||
							
								
								
									
										82
									
								
								app/Api/V1/Controllers/AboutController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								app/Api/V1/Controllers/AboutController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * AboutController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use DB; | ||||
| use FireflyIII\Transformers\UserTransformer; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Returns basic information about this installation. | ||||
|  * | ||||
|  * Class AboutController. | ||||
|  */ | ||||
| class AboutController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * Returns system information. | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function about(): JsonResponse | ||||
|     { | ||||
|         $search        = ['~', '#']; | ||||
|         $replace       = ['\~', '# ']; | ||||
|         $phpVersion    = str_replace($search, $replace, PHP_VERSION); | ||||
|         $phpOs         = str_replace($search, $replace, PHP_OS); | ||||
|         $currentDriver = DB::getDriverName(); | ||||
|         $data | ||||
|                        = [ | ||||
|             'version'     => config('firefly.version'), | ||||
|             'api_version' => config('firefly.api_version'), | ||||
|             'php_version' => $phpVersion, | ||||
|             'os'          => $phpOs, | ||||
|             'driver'      => $currentDriver, | ||||
|         ]; | ||||
|  | ||||
|         return response()->json(['data' => $data], 200)->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns information about the user. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function user(Request $request): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item(auth()->user(), new UserTransformer($this->parameters), 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										250
									
								
								app/Api/V1/Controllers/AccountController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										250
									
								
								app/Api/V1/Controllers/AccountController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,250 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AccountController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\AccountRequest; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Transformers\AccountTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class AccountController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class AccountController extends Controller | ||||
| { | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $currencyRepository; | ||||
|     /** @var AccountRepositoryInterface The account repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|                 // @var AccountRepositoryInterface repository | ||||
|                 $this->repository = app(AccountRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 $this->currencyRepository = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->currencyRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param \FireflyIII\Models\Account $account | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Account $account): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($account, null); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // read type from URI | ||||
|         $type = $request->get('type') ?? 'all'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $types    = $this->mapTypes($this->parameters->get('type')); | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         $collection = $this->repository->getAccountsByType($types); | ||||
|         $count      = $collection->count(); | ||||
|         $accounts   = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.accounts.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($accounts, new AccountTransformer($this->parameters), 'accounts'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show single instance. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Account $account | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Account $account): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($account, new AccountTransformer($this->parameters), 'accounts'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a new instance. | ||||
|      * | ||||
|      * @param AccountRequest $request | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function store(AccountRequest $request): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         // if currency ID is 0, find the currency by the code: | ||||
|         if (0 === $data['currency_id']) { | ||||
|             $currency            = $this->currencyRepository->findByCodeNull($data['currency_code']); | ||||
|             $data['currency_id'] = null === $currency ? 0 : $currency->id; | ||||
|         } | ||||
|         $account = $this->repository->store($data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($account, new AccountTransformer($this->parameters), 'accounts'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update account. | ||||
|      * | ||||
|      * @param AccountRequest $request | ||||
|      * @param Account        $account | ||||
|      * | ||||
|      * @return \Illuminate\Http\JsonResponse | ||||
|      */ | ||||
|     public function update(AccountRequest $request, Account $account): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         // if currency ID is 0, find the currency by the code: | ||||
|         if (0 === $data['currency_id']) { | ||||
|             $currency            = $this->currencyRepository->findByCodeNull($data['currency_code']); | ||||
|             $data['currency_id'] = null === $currency ? 0 : $currency->id; | ||||
|         } | ||||
|         // set correct type: | ||||
|         $data['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type); | ||||
|         $this->repository->update($account, $data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($account, new AccountTransformer($this->parameters), 'accounts'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * All the available types. | ||||
|      * | ||||
|      * @param string $type | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function mapTypes(string $type): array | ||||
|     { | ||||
|         $types  = [ | ||||
|             'all'                        => [AccountType::DEFAULT, AccountType::CASH, AccountType::ASSET, AccountType::EXPENSE, AccountType::REVENUE, | ||||
|                                              AccountType::INITIAL_BALANCE, AccountType::BENEFICIARY, AccountType::IMPORT, AccountType::RECONCILIATION, | ||||
|                                              AccountType::LOAN,AccountType::DEBT, AccountType::MORTGAGE], | ||||
|             'asset'                      => [AccountType::DEFAULT, AccountType::ASSET,], | ||||
|             'cash'                       => [AccountType::CASH,], | ||||
|             'expense'                    => [AccountType::EXPENSE, AccountType::BENEFICIARY,], | ||||
|             'revenue'                    => [AccountType::REVENUE,], | ||||
|             'special'                    => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION,], | ||||
|             'hidden'                     => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION], | ||||
|             'liability'                  => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD], | ||||
|             'liabilities'                => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD], | ||||
|             'cc'                         => [AccountType::CREDITCARD], | ||||
|             'creditcard'                 => [AccountType::CREDITCARD], | ||||
|             'credit_card'                => [AccountType::CREDITCARD], | ||||
|             AccountType::DEFAULT         => [AccountType::DEFAULT], | ||||
|             AccountType::CASH            => [AccountType::CASH], | ||||
|             AccountType::ASSET           => [AccountType::ASSET], | ||||
|             AccountType::EXPENSE         => [AccountType::EXPENSE], | ||||
|             AccountType::REVENUE         => [AccountType::REVENUE], | ||||
|             AccountType::INITIAL_BALANCE => [AccountType::INITIAL_BALANCE], | ||||
|             AccountType::BENEFICIARY     => [AccountType::BENEFICIARY], | ||||
|             AccountType::IMPORT          => [AccountType::IMPORT], | ||||
|             AccountType::RECONCILIATION  => [AccountType::RECONCILIATION], | ||||
|             AccountType::LOAN            => [AccountType::LOAN], | ||||
|             AccountType::MORTGAGE        => [AccountType::MORTGAGE], | ||||
|             AccountType::DEBT            => [AccountType::DEBT], | ||||
|             AccountType::CREDITCARD      => [AccountType::CREDITCARD], | ||||
|  | ||||
|         ]; | ||||
|         $return = $types['all']; | ||||
|         if (isset($types[$type])) { | ||||
|             $return = $types[$type]; | ||||
|         } | ||||
|  | ||||
|         return $return; // @codeCoverageIgnore | ||||
|     } | ||||
| } | ||||
							
								
								
									
										235
									
								
								app/Api/V1/Controllers/AttachmentController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								app/Api/V1/Controllers/AttachmentController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,235 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AttachmentController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\AttachmentRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Attachments\AttachmentHelperInterface; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; | ||||
| use FireflyIII\Transformers\AttachmentTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Http\Response as LaravelResponse; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class AttachmentController extends Controller | ||||
| { | ||||
|     /** @var AttachmentRepositoryInterface The attachment repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(AttachmentRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Attachment $attachment): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($attachment); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Download an attachment. | ||||
|      * | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return LaravelResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function download(Attachment $attachment): LaravelResponse | ||||
|     { | ||||
|         if (false === $attachment->uploaded) { | ||||
|             throw new FireflyException('No file has been uploaded for this attachment (yet).'); | ||||
|         } | ||||
|         if ($this->repository->exists($attachment)) { | ||||
|             $content = $this->repository->getContent($attachment); | ||||
|             $quoted  = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\')); | ||||
|  | ||||
|             /** @var LaravelResponse $response */ | ||||
|             $response = response($content, 200); | ||||
|             $response | ||||
|                 ->header('Content-Description', 'File Transfer') | ||||
|                 ->header('Content-Type', 'application/octet-stream') | ||||
|                 ->header('Content-Disposition', 'attachment; filename=' . $quoted) | ||||
|                 ->header('Content-Transfer-Encoding', 'binary') | ||||
|                 ->header('Connection', 'Keep-Alive') | ||||
|                 ->header('Expires', '0') | ||||
|                 ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') | ||||
|                 ->header('Pragma', 'public') | ||||
|                 ->header('Content-Length', \strlen($content)); | ||||
|  | ||||
|             return $response; | ||||
|         } | ||||
|         throw new FireflyException('Could not find the indicated attachment. The file is no longer there.'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         $collection  = $this->repository->get(); | ||||
|         $count       = $collection->count(); | ||||
|         $attachments = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.attachments.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($attachments, new AttachmentTransformer($this->parameters), 'attachments'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Attachment $attachment): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param AttachmentRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(AttachmentRequest $request): JsonResponse | ||||
|     { | ||||
|         $data       = $request->getAll(); | ||||
|         $attachment = $this->repository->store($data); | ||||
|         $manager    = new Manager; | ||||
|         $baseUrl    = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param AttachmentRequest $request | ||||
|      * @param Attachment        $attachment | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(AttachmentRequest $request, Attachment $attachment): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         $this->repository->update($attachment, $data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($attachment, new AttachmentTransformer($this->parameters), 'attachments'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Upload an attachment. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Attachment $attachment | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function upload(Request $request, Attachment $attachment): JsonResponse | ||||
|     { | ||||
|         /** @var AttachmentHelperInterface $helper */ | ||||
|         $helper = app(AttachmentHelperInterface::class); | ||||
|         $body   = $request->getContent(); | ||||
|         $helper->saveAttachmentFromApi($attachment, $body); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										195
									
								
								app/Api/V1/Controllers/AvailableBudgetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								app/Api/V1/Controllers/AvailableBudgetController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,195 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AvailableBudgetController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\AvailableBudgetRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\AvailableBudget; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Transformers\AvailableBudgetTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class AvailableBudgetController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class AvailableBudgetController extends Controller | ||||
| { | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $currencyRepository; | ||||
|     /** @var BudgetRepositoryInterface The budget repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user                     = auth()->user(); | ||||
|                 $this->repository         = app(BudgetRepositoryInterface::class); | ||||
|                 $this->currencyRepository = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param AvailableBudget $availableBudget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(AvailableBudget $availableBudget): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroyAvailableBudget($availableBudget); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of available budgets. Count it and split it. | ||||
|         $collection       = $this->repository->getAvailableBudgets(); | ||||
|         $count            = $collection->count(); | ||||
|         $availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.available_budgets.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($availableBudgets, new AvailableBudgetTransformer($this->parameters), 'available_budgets'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param Request          $request | ||||
|      * @param  AvailableBudget $availableBudget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, AvailableBudget $availableBudget): JsonResponse | ||||
|     { | ||||
|  | ||||
|         $manager = new Manager; | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param AvailableBudgetRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(AvailableBudgetRequest $request): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getAll(); | ||||
|         $currency = $this->currencyRepository->findNull($data['currency_id']); | ||||
|         if (null === $currency) { | ||||
|             $currency = $this->currencyRepository->findByCodeNull($data['currency_code']); | ||||
|         } | ||||
|         if (null === $currency) { | ||||
|             throw new FireflyException('Could not find the indicated currency.'); | ||||
|         } | ||||
|         $availableBudget = $this->repository->setAvailableBudget($currency, $data['start_date'], $data['end_date'], $data['amount']); | ||||
|         $manager         = new Manager; | ||||
|         $baseUrl         = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param AvailableBudgetRequest $request | ||||
|      * @param AvailableBudget        $availableBudget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(AvailableBudgetRequest $request, AvailableBudget $availableBudget): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         $this->repository->updateAvailableBudget($availableBudget, $data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($availableBudget, new AvailableBudgetTransformer($this->parameters), 'available_budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										178
									
								
								app/Api/V1/Controllers/BillController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								app/Api/V1/Controllers/BillController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * BillController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\BillRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Repositories\Bill\BillRepositoryInterface; | ||||
| use FireflyIII\Transformers\BillTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class BillController. | ||||
|  */ | ||||
| class BillController extends Controller | ||||
| { | ||||
|     /** @var BillRepositoryInterface The bill repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * BillController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var BillRepositoryInterface repository */ | ||||
|                 $this->repository = app(BillRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  Bill $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Bill $bill): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($bill); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         $pageSize  = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $paginator = $this->repository->getPaginator($pageSize); | ||||
|         /** @var Collection $bills */ | ||||
|         $bills = $paginator->getCollection(); | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new FractalCollection($bills, new BillTransformer($this->parameters), 'bills'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show the specified bill. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Bill    $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Bill $bill): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($bill, new BillTransformer($this->parameters), 'bills'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a bill. | ||||
|      * | ||||
|      * @param BillRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(BillRequest $request): JsonResponse | ||||
|     { | ||||
|         $bill = $this->repository->store($request->getAll()); | ||||
|         if (null !== $bill) { | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|             $resource = new Item($bill, new BillTransformer($this->parameters), 'bills'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new bill.'); // @codeCoverageIgnore | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update a bill. | ||||
|      * | ||||
|      * @param BillRequest $request | ||||
|      * @param Bill        $bill | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(BillRequest $request, Bill $bill): JsonResponse | ||||
|     { | ||||
|         $data    = $request->getAll(); | ||||
|         $bill    = $this->repository->update($bill, $data); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($bill, new BillTransformer($this->parameters), 'bills'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										188
									
								
								app/Api/V1/Controllers/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								app/Api/V1/Controllers/BudgetController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,188 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\BudgetRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Transformers\BudgetTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class BudgetController extends Controller | ||||
| { | ||||
|     /** @var BudgetRepositoryInterface The budget repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * BudgetController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var BudgetRepositoryInterface repository */ | ||||
|                 $this->repository = app(BudgetRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param Budget $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Budget $budget): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($budget); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getBudgets(); | ||||
|         $count      = $collection->count(); | ||||
|         $budgets    = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.budgets.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($budgets, new BudgetTransformer($this->parameters), 'budgets'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show a budget. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Budget  $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Budget $budget): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a budget. | ||||
|      * | ||||
|      * @param BudgetRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(BudgetRequest $request): JsonResponse | ||||
|     { | ||||
|         $budget = $this->repository->store($request->getAll()); | ||||
|         if (null !== $budget) { | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|             $resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new budget.'); // @codeCoverageIgnore | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update a budget. | ||||
|      * | ||||
|      * @param BudgetRequest $request | ||||
|      * @param Budget        $budget | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(BudgetRequest $request, Budget $budget): JsonResponse | ||||
|     { | ||||
|         $data    = $request->getAll(); | ||||
|         $budget  = $this->repository->update($budget, $data); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($budget, new BudgetTransformer($this->parameters), 'budgets'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										197
									
								
								app/Api/V1/Controllers/BudgetLimitController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								app/Api/V1/Controllers/BudgetLimitController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetLimitController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\BudgetLimitRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; | ||||
| use FireflyIII\Transformers\BudgetLimitTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class BudgetLimitController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class BudgetLimitController extends Controller | ||||
| { | ||||
|     /** @var BudgetRepositoryInterface The budget repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * AccountController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user             = auth()->user(); | ||||
|                 $this->repository = app(BudgetRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param BudgetLimit $budgetLimit | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(BudgetLimit $budgetLimit): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroyBudgetLimit($budgetLimit); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $budgetId = (int)($request->get('budget_id') ?? 0); | ||||
|         $budget   = $this->repository->findNull($budgetId); | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $this->parameters->set('budget_id', $budgetId); | ||||
|  | ||||
|         $collection = new Collection; | ||||
|         if (null === $budget) { | ||||
|             $collection = $this->repository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         if (null !== $budget) { | ||||
|             $collection = $this->repository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|  | ||||
|         $count        = $collection->count(); | ||||
|         $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator    = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams()); | ||||
|  | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($budgetLimits, new BudgetLimitTransformer($this->parameters), 'budget_limits'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display the specified resource. | ||||
|      * | ||||
|      * @param Request     $request | ||||
|      * @param BudgetLimit $budgetLimit | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, BudgetLimit $budgetLimit): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a newly created resource in storage. | ||||
|      * | ||||
|      * @param BudgetLimitRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(BudgetLimitRequest $request): JsonResponse | ||||
|     { | ||||
|         $data   = $request->getAll(); | ||||
|         $budget = $this->repository->findNull($data['budget_id']); | ||||
|         if (null === $budget) { | ||||
|             throw new FireflyException('Unknown budget.'); | ||||
|         } | ||||
|         $data['budget'] = $budget; | ||||
|         $budgetLimit    = $this->repository->storeBudgetLimit($data); | ||||
|         $manager        = new Manager; | ||||
|         $baseUrl        = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the specified resource in storage. | ||||
|      * | ||||
|      * @param BudgetLimitRequest $request | ||||
|      * @param BudgetLimit        $budgetLimit | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(BudgetLimitRequest $request, BudgetLimit $budgetLimit): JsonResponse | ||||
|     { | ||||
|         $data   = $request->getAll(); | ||||
|         $budget = $this->repository->findNull($data['budget_id']); | ||||
|         if (null === $budget) { | ||||
|             $budget = $budgetLimit->budget; | ||||
|         } | ||||
|         $data['budget'] = $budget; | ||||
|         $budgetLimit    = $this->repository->updateBudgetLimit($budgetLimit, $data); | ||||
|         $manager        = new Manager; | ||||
|         $baseUrl        = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($budgetLimit, new BudgetLimitTransformer($this->parameters), 'budget_limits'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										188
									
								
								app/Api/V1/Controllers/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								app/Api/V1/Controllers/CategoryController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,188 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CategoryController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\CategoryRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Repositories\Category\CategoryRepositoryInterface; | ||||
| use FireflyIII\Transformers\CategoryTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class CategoryController extends Controller | ||||
| { | ||||
|     /** @var CategoryRepositoryInterface The category repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * CategoryController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var CategoryRepositoryInterface repository */ | ||||
|                 $this->repository = app(CategoryRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Category $category): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($category); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getCategories(); | ||||
|         $count      = $collection->count(); | ||||
|         $categories = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.categories.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($categories, new CategoryTransformer($this->parameters), 'categories'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show the category. | ||||
|      * | ||||
|      * @param Request  $request | ||||
|      * @param Category $category | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Category $category): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($category, new CategoryTransformer($this->parameters), 'categories'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new category. | ||||
|      * | ||||
|      * @param CategoryRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(CategoryRequest $request): JsonResponse | ||||
|     { | ||||
|         $category = $this->repository->store($request->getAll()); | ||||
|         if (null !== $category) { | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|             $resource = new Item($category, new CategoryTransformer($this->parameters), 'categories'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new category.'); // @codeCoverageIgnore | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update the category. | ||||
|      * | ||||
|      * @param CategoryRequest $request | ||||
|      * @param Category        $category | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(CategoryRequest $request, Category $category): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getAll(); | ||||
|         $category = $this->repository->update($category, $data); | ||||
|         $manager  = new Manager(); | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($category, new CategoryTransformer($this->parameters), 'categories'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										136
									
								
								app/Api/V1/Controllers/ConfigurationController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								app/Api/V1/Controllers/ConfigurationController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
| <?php | ||||
| /** | ||||
|  * ConfigurationController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\Configuration; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
|  | ||||
| /** | ||||
|  * Class ConfigurationController. | ||||
|  */ | ||||
| class ConfigurationController extends Controller | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * BudgetController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @noinspection UnusedConstructorDependenciesInspection */ | ||||
|                 $this->repository = app(UserRepositoryInterface::class); | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 if (!$this->repository->hasRole($admin, 'owner')) { | ||||
|                     /** @noinspection ExceptionsAnnotatingAndHandlingInspection */ | ||||
|                     throw new FireflyException('No access to method.'); // @codeCoverageIgnore | ||||
|                 } | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all configuration. | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(): JsonResponse | ||||
|     { | ||||
|         $configData = $this->getConfigData(); | ||||
|  | ||||
|         return response()->json(['data' => $configData], 200)->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update the configuration. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function update(Request $request): JsonResponse | ||||
|     { | ||||
|         $name  = $request->get('name'); | ||||
|         $value = $request->get('value'); | ||||
|         $valid = ['is_demo_site', 'permission_update_check', 'single_user_mode']; | ||||
|         if (!\in_array($name, $valid, true)) { | ||||
|             throw new FireflyException('You cannot edit this configuration value.'); | ||||
|         } | ||||
|         $configValue = ''; | ||||
|         switch ($name) { | ||||
|             case 'is_demo_site': | ||||
|             case 'single_user_mode': | ||||
|                 $configValue = 'true' === $value; | ||||
|                 break; | ||||
|             case 'permission_update_check': | ||||
|                 $configValue = (int)$value >= -1 && (int)$value <= 1 ? (int)$value : -1; | ||||
|                 break; | ||||
|         } | ||||
|         app('fireflyconfig')->set($name, $configValue); | ||||
|         $configData = $this->getConfigData(); | ||||
|  | ||||
|         return response()->json(['data' => $configData], 200)->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all config values. | ||||
|      * | ||||
|      * @return array | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     private function getConfigData(): array | ||||
|     { | ||||
|         /** @var Configuration $isDemoSite */ | ||||
|         $isDemoSite = app('fireflyconfig')->get('is_demo_site'); | ||||
|         /** @var Configuration $updateCheck */ | ||||
|         $updateCheck = app('fireflyconfig')->get('permission_update_check'); | ||||
|         /** @var Configuration $lastCheck */ | ||||
|         $lastCheck = app('fireflyconfig')->get('last_update_check'); | ||||
|         /** @var Configuration $singleUser */ | ||||
|         $singleUser = app('fireflyconfig')->get('single_user_mode'); | ||||
|         $data       = [ | ||||
|             'is_demo_site'            => null === $isDemoSite ? null : $isDemoSite->data, | ||||
|             'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data, | ||||
|             'last_update_check'       => null === $lastCheck ? null : (int)$lastCheck->data, | ||||
|             'single_user_mode'        => null === $singleUser ? null : $singleUser->data, | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										119
									
								
								app/Api/V1/Controllers/Controller.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								app/Api/V1/Controllers/Controller.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Controller.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use Carbon\Exceptions\InvalidDateException; | ||||
| use Illuminate\Foundation\Auth\Access\AuthorizesRequests; | ||||
| use Illuminate\Foundation\Bus\DispatchesJobs; | ||||
| use Illuminate\Foundation\Validation\ValidatesRequests; | ||||
| use Illuminate\Routing\Controller as BaseController; | ||||
| use Log; | ||||
| use Symfony\Component\HttpFoundation\ParameterBag; | ||||
|  | ||||
| /** | ||||
|  * Class Controller. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  * @SuppressWarnings(PHPMD.NumberOfChildren) | ||||
|  */ | ||||
| class Controller extends BaseController | ||||
| { | ||||
|     use AuthorizesRequests, DispatchesJobs, ValidatesRequests; | ||||
|  | ||||
|     /** @var ParameterBag Parameters from the URI are stored here. */ | ||||
|     protected $parameters; | ||||
|  | ||||
|     /** | ||||
|      * Controller constructor. | ||||
|      * | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         // get global parameters | ||||
|         $this->parameters = $this->getParameters(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Method to help build URI's. | ||||
|      * | ||||
|      * @return string | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     protected function buildParams(): string | ||||
|     { | ||||
|         $return = '?'; | ||||
|         $params = []; | ||||
|         foreach ($this->parameters as $key => $value) { | ||||
|             if ('page' === $key) { | ||||
|                 continue; | ||||
|             } | ||||
|             if ($value instanceof Carbon) { | ||||
|                 $params[$key] = $value->format('Y-m-d'); | ||||
|                 continue; | ||||
|             } | ||||
|             $params[$key] = $value; | ||||
|         } | ||||
|         $return .= http_build_query($params); | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Method to grab all parameters from the URI. | ||||
|      * | ||||
|      * @return ParameterBag | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     private function getParameters(): ParameterBag | ||||
|     { | ||||
|         $bag  = new ParameterBag; | ||||
|         $page = (int)request()->get('page'); | ||||
|         if (0 === $page) { | ||||
|             $page = 1; | ||||
|         } | ||||
|         $bag->set('page', $page); | ||||
|  | ||||
|         // some date fields: | ||||
|         $dates = ['start', 'end', 'date']; | ||||
|         foreach ($dates as $field) { | ||||
|             $date = request()->get($field); | ||||
|             $obj  = null; | ||||
|             if (null !== $date) { | ||||
|                 try { | ||||
|                     $obj = new Carbon($date); | ||||
|                 } catch (InvalidDateException $e) { | ||||
|                     // don't care | ||||
|                     Log::error(sprintf('Invalid date exception in API controller: %s', $e->getMessage())); | ||||
|                 } | ||||
|             } | ||||
|             $bag->set($field, $obj); | ||||
|         } | ||||
|  | ||||
|         return $bag; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										219
									
								
								app/Api/V1/Controllers/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										219
									
								
								app/Api/V1/Controllers/CurrencyController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,219 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CurrencyController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\CurrencyRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Transformers\CurrencyTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class CurrencyController extends Controller | ||||
| { | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $repository; | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $userRepository; | ||||
|  | ||||
|     /** | ||||
|      * CurrencyRepository constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var CurrencyRepositoryInterface repository */ | ||||
|                 $this->repository     = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->userRepository = app(UserRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function delete(TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|  | ||||
|         if (!$this->userRepository->hasRole($admin, 'owner')) { | ||||
|             // access denied: | ||||
|             throw new FireflyException('No access to method, user is not owner.'); // @codeCoverageIgnore | ||||
|         } | ||||
|         if (!$this->repository->canDeleteCurrency($currency)) { | ||||
|             throw new FireflyException('No access to method, currency is in use.'); // @codeCoverageIgnore | ||||
|         } | ||||
|         $this->repository->destroy($currency); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         $pageSize   = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $collection = $this->repository->get(); | ||||
|         $count      = $collection->count(); | ||||
|         // slice them: | ||||
|         $currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|         $paginator  = new LengthAwarePaginator($currencies, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.currencies.index') . $this->buildParams()); | ||||
|  | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|         $resource = new FractalCollection($currencies, new CurrencyTransformer($this->parameters), 'currencies'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show a currency. | ||||
|      * | ||||
|      * @param Request             $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|         $resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new currency. | ||||
|      * | ||||
|      * @param CurrencyRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(CurrencyRequest $request): JsonResponse | ||||
|     { | ||||
|         $currency = $this->repository->store($request->getAll()); | ||||
|  | ||||
|         if (null !== $currency) { | ||||
|             if (true === $request->boolean('default')) { | ||||
|                 app('preferences')->set('currencyPreference', $currency->code); | ||||
|                 app('preferences')->mark(); | ||||
|             } | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|             $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|             $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|             $resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new currency.'); // @codeCoverageIgnore | ||||
|  | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update a currency. | ||||
|      * | ||||
|      * @param CurrencyRequest     $request | ||||
|      * @param TransactionCurrency $currency | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(CurrencyRequest $request, TransactionCurrency $currency): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getAll(); | ||||
|         $currency = $this->repository->update($currency, $data); | ||||
|  | ||||
|         if (true === $request->boolean('default')) { | ||||
|             app('preferences')->set('currencyPreference', $currency->code); | ||||
|             app('preferences')->mark(); | ||||
|         } | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); | ||||
|         $this->parameters->set('defaultCurrency', $defaultCurrency); | ||||
|  | ||||
|         $resource = new Item($currency, new CurrencyTransformer($this->parameters), 'currencies'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										111
									
								
								app/Api/V1/Controllers/CurrencyExchangeRateController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								app/Api/V1/Controllers/CurrencyExchangeRateController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CurrencyExchangeRateController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Services\Currency\ExchangeRateInterface; | ||||
| use FireflyIII\Transformers\CurrencyExchangeRateTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyExchangeRateController | ||||
|  */ | ||||
| class CurrencyExchangeRateController extends Controller | ||||
| { | ||||
|     /** @var CurrencyRepositoryInterface The currency repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * CurrencyExchangeRateController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 $this->repository = app(CurrencyRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show an exchange rate. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $fromCurrency = $this->repository->findByCodeNull($request->get('from') ?? 'EUR'); | ||||
|         $toCurrency   = $this->repository->findByCodeNull($request->get('to') ?? 'USD'); | ||||
|  | ||||
|         if (null === $fromCurrency) { | ||||
|             throw new FireflyException('Unknown source currency.'); | ||||
|         } | ||||
|         if (null === $toCurrency) { | ||||
|             throw new FireflyException('Unknown destination currency.'); | ||||
|         } | ||||
|  | ||||
|         $dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d')); | ||||
|         $this->parameters->set('from', $fromCurrency->code); | ||||
|         $this->parameters->set('to', $toCurrency->code); | ||||
|         $this->parameters->set('date', $dateObj->format('Y-m-d')); | ||||
|  | ||||
|         $rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj); | ||||
|         if (null === $rate) { | ||||
|             /** @var User $admin */ | ||||
|             $admin = auth()->user(); | ||||
|             // create service: | ||||
|             /** @var ExchangeRateInterface $service */ | ||||
|             $service = app(ExchangeRateInterface::class); | ||||
|             $service->setUser($admin); | ||||
|             $rate = $service->getRate($fromCurrency, $toCurrency, $dateObj); | ||||
|         } | ||||
|  | ||||
|         $resource = new Item($rate, new CurrencyExchangeRateTransformer($this->parameters), 'currency_exchange_rates'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										216
									
								
								app/Api/V1/Controllers/JournalLinkController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										216
									
								
								app/Api/V1/Controllers/JournalLinkController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,216 @@ | ||||
| <?php | ||||
| /** | ||||
|  * JournalLinkController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\JournalLinkRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\TransactionJournalLink; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use FireflyIII\Transformers\JournalLinkTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class JournalLinkController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class JournalLinkController extends Controller | ||||
| { | ||||
|     /** @var JournalRepositoryInterface The journal repository */ | ||||
|     private $journalRepository; | ||||
|     /** @var LinkTypeRepositoryInterface The link type repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * JournalLinkController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 $this->repository        = app(LinkTypeRepositoryInterface::class); | ||||
|                 $this->journalRepository = app(JournalRepositoryInterface::class); | ||||
|  | ||||
|                 $this->repository->setUser($user); | ||||
|                 $this->journalRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param TransactionJournalLink $link | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(TransactionJournalLink $link): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroyLink($link); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // read type from URI | ||||
|         $name = $request->get('name') ?? null; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         $linkType = $this->repository->findByName($name); | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         $collection   = $this->repository->getJournalLinks($linkType); | ||||
|         $count        = $collection->count(); | ||||
|         $journalLinks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.journal_links.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($journalLinks, new JournalLinkTransformer($this->parameters), 'journal_links'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request                $request | ||||
|      * @param TransactionJournalLink $journalLink | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, TransactionJournalLink $journalLink): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param JournalLinkRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(JournalLinkRequest $request): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $data    = $request->getAll(); | ||||
|         $inward  = $this->journalRepository->findNull($data['inward_id'] ?? 0); | ||||
|         $outward = $this->journalRepository->findNull($data['outward_id'] ?? 0); | ||||
|         if (null === $inward || null === $outward) { | ||||
|             throw new FireflyException('Source or destination is NULL.'); | ||||
|         } | ||||
|         $data['direction'] = 'inward'; | ||||
|  | ||||
|         $journalLink = $this->repository->storeLink($data, $inward, $outward); | ||||
|         $resource    = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update object. | ||||
|      * | ||||
|      * @param JournalLinkRequest     $request | ||||
|      * @param TransactionJournalLink $journalLink | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(JournalLinkRequest $request, TransactionJournalLink $journalLink): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|  | ||||
|         $data            = $request->getAll(); | ||||
|         $data['inward']  = $this->journalRepository->findNull($data['inward_id'] ?? 0); | ||||
|         $data['outward'] = $this->journalRepository->findNull($data['outward_id'] ?? 0); | ||||
|         if (null === $data['inward'] || null === $data['outward']) { | ||||
|             throw new FireflyException('Source or destination is NULL.'); | ||||
|         } | ||||
|         $data['direction'] = 'inward'; | ||||
|         $journalLink       = $this->repository->updateLink($journalLink, $data); | ||||
|  | ||||
|         $resource = new Item($journalLink, new JournalLinkTransformer($this->parameters), 'journal_links'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										210
									
								
								app/Api/V1/Controllers/LinkTypeController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								app/Api/V1/Controllers/LinkTypeController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| <?php | ||||
| /** | ||||
|  * LinkTypeController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\LinkTypeRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\LinkType; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Transformers\LinkTypeTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class LinkTypeController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class LinkTypeController extends Controller | ||||
| { | ||||
|     /** @var LinkTypeRepositoryInterface The link type repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $userRepository; | ||||
|  | ||||
|     /** | ||||
|      * LinkTypeController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user                 = auth()->user(); | ||||
|                 $this->repository     = app(LinkTypeRepositoryInterface::class); | ||||
|                 $this->userRepository = app(UserRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param LinkType $linkType | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function delete(LinkType $linkType): JsonResponse | ||||
|     { | ||||
|         if (false === $linkType->editable) { | ||||
|             throw new FireflyException(sprintf('You cannot delete this link type (#%d, "%s")', $linkType->id, $linkType->name)); | ||||
|         } | ||||
|         $this->repository->destroy($linkType, null); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of accounts. Count it and split it. | ||||
|         $collection = $this->repository->get(); | ||||
|         $count      = $collection->count(); | ||||
|         $linkTypes  = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.link_types.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($linkTypes, new LinkTypeTransformer($this->parameters), 'link_types'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request  $request | ||||
|      * @param LinkType $linkType | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, LinkType $linkType): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager; | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param LinkTypeRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(LinkTypeRequest $request): JsonResponse | ||||
|     { | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|  | ||||
|         if (!$this->userRepository->hasRole($admin, 'owner')) { | ||||
|             throw new FireflyException('You need the "owner"-role to do this.'); | ||||
|         } | ||||
|         $data = $request->getAll(); | ||||
|         // if currency ID is 0, find the currency by the code: | ||||
|         $linkType = $this->repository->store($data); | ||||
|         $manager  = new Manager; | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update object. | ||||
|      * | ||||
|      * @param LinkTypeRequest $request | ||||
|      * @param LinkType        $linkType | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse | ||||
|     { | ||||
|         if (false === $linkType->editable) { | ||||
|             throw new FireflyException(sprintf('You cannot edit this link type (#%d, "%s")', $linkType->id, $linkType->name)); | ||||
|         } | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|  | ||||
|         if (!$this->userRepository->hasRole($admin, 'owner')) { | ||||
|             throw new FireflyException('You need the "owner"-role to do this.'); | ||||
|         } | ||||
|  | ||||
|         $data = $request->getAll(); | ||||
|         $this->repository->update($linkType, $data); | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($linkType, new LinkTypeTransformer($this->parameters), 'link_types'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										188
									
								
								app/Api/V1/Controllers/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								app/Api/V1/Controllers/PiggyBankController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,188 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PiggyBankController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\PiggyBankRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; | ||||
| use FireflyIII\Transformers\PiggyBankTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class PiggyBankController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class PiggyBankController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var PiggyBankRepositoryInterface The piggy bank repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * PiggyBankController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 $this->repository = app(PiggyBankRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(PiggyBank $piggyBank): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($piggyBank); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getPiggyBanks(); | ||||
|         $count      = $collection->count(); | ||||
|         $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.piggy_banks.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($piggyBanks, new PiggyBankTransformer($this->parameters), 'piggy_banks'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request   $request | ||||
|      * @param PiggyBank $piggyBank | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, PiggyBank $piggyBank): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param PiggyBankRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function store(PiggyBankRequest $request): JsonResponse | ||||
|     { | ||||
|         $piggyBank = $this->repository->store($request->getAll()); | ||||
|         if (null !== $piggyBank) { | ||||
|             $manager = new Manager(); | ||||
|             $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|             $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|             $resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks'); | ||||
|  | ||||
|             return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|         } | ||||
|         throw new FireflyException('Could not store new piggy bank.'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update piggy bank. | ||||
|      * | ||||
|      * @param PiggyBankRequest $request | ||||
|      * @param PiggyBank        $piggyBank | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(PiggyBankRequest $request, PiggyBank $piggyBank): JsonResponse | ||||
|     { | ||||
|         $piggyBank = $this->repository->update($piggyBank, $request->getAll()); | ||||
|         $manager   = new Manager(); | ||||
|         $baseUrl   = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($piggyBank, new PiggyBankTransformer($this->parameters), 'piggy_banks'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										145
									
								
								app/Api/V1/Controllers/PreferenceController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								app/Api/V1/Controllers/PreferenceController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PreferencesController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\PreferenceRequest; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Transformers\PreferenceTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PreferenceController | ||||
|  */ | ||||
| class PreferenceController extends Controller | ||||
| { | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         /** @var User $user */ | ||||
|         $user        = auth()->user(); | ||||
|         $available   = [ | ||||
|             'language', 'customFiscalYear', 'fiscalYearStart', 'currencyPreference', | ||||
|             'transaction_journal_optional_fields', 'frontPageAccounts', 'viewRange', | ||||
|             'listPageSize, twoFactorAuthEnabled', | ||||
|         ]; | ||||
|         $preferences = new Collection; | ||||
|         foreach ($available as $name) { | ||||
|             $pref = app('preferences')->getForUser($user, $name); | ||||
|             if (null !== $pref) { | ||||
|                 $preferences->push($pref); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($preferences, new PreferenceTransformer($this->parameters), 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Preference $preference | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Preference $preference): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($preference, new PreferenceTransformer($this->parameters), 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a preference. | ||||
|      * | ||||
|      * @param PreferenceRequest $request | ||||
|      * @param Preference        $preference | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     public function update(PreferenceRequest $request, Preference $preference): JsonResponse | ||||
|     { | ||||
|  | ||||
|         $data     = $request->getAll(); | ||||
|         $newValue = $data['data']; | ||||
|         switch ($preference->name) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'transaction_journal_optional_fields': | ||||
|             case 'frontPageAccounts': | ||||
|                 $newValue = explode(',', $data['data']); | ||||
|                 break; | ||||
|             case 'listPageSize': | ||||
|                 $newValue = (int)$data['data']; | ||||
|                 break; | ||||
|             case 'customFiscalYear': | ||||
|             case 'twoFactorAuthEnabled': | ||||
|                 $newValue = 1 === (int)$data['data']; | ||||
|                 break; | ||||
|         } | ||||
|         $result = app('preferences')->set($preference->name, $newValue); | ||||
|  | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($result, new PreferenceTransformer($this->parameters), 'preferences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										180
									
								
								app/Api/V1/Controllers/RecurrenceController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										180
									
								
								app/Api/V1/Controllers/RecurrenceController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,180 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RecurrenceController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\RecurrenceRequest; | ||||
| use FireflyIII\Models\Recurrence; | ||||
| use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; | ||||
| use FireflyIII\Transformers\RecurrenceTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class RecurrenceController | ||||
|  */ | ||||
| class RecurrenceController extends Controller | ||||
| { | ||||
|     /** @var RecurringRepositoryInterface The recurring transaction repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * RecurrenceController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 /** @var RecurringRepositoryInterface repository */ | ||||
|                 $this->repository = app(RecurringRepositoryInterface::class); | ||||
|                 $this->repository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param Recurrence $recurrence | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Recurrence $recurrence): JsonResponse | ||||
|     { | ||||
|         $this->repository->destroy($recurrence); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->repository->getAll(); | ||||
|         $count      = $collection->count(); | ||||
|         $piggyBanks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.recurrences.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($piggyBanks, new RecurrenceTransformer($this->parameters), 'recurrences'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request    $request | ||||
|      * @param Recurrence $recurrence | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Recurrence $recurrence): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($recurrence, new RecurrenceTransformer($this->parameters), 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param RecurrenceRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(RecurrenceRequest $request): JsonResponse | ||||
|     { | ||||
|         $recurrence = $this->repository->store($request->getAll()); | ||||
|         $manager    = new Manager(); | ||||
|         $baseUrl    = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new Item($recurrence, new RecurrenceTransformer($this->parameters), 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update single recurrence. | ||||
|      * | ||||
|      * @param RecurrenceRequest $request | ||||
|      * @param Recurrence        $recurrence | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(RecurrenceRequest $request, Recurrence $recurrence): JsonResponse | ||||
|     { | ||||
|         $data     = $request->getAll(); | ||||
|         $category = $this->repository->update($recurrence, $data); | ||||
|         $manager  = new Manager(); | ||||
|         $baseUrl  = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($category, new RecurrenceTransformer($this->parameters), 'recurrences'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										178
									
								
								app/Api/V1/Controllers/RuleController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										178
									
								
								app/Api/V1/Controllers/RuleController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,178 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\RuleRequest; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Repositories\Rule\RuleRepositoryInterface; | ||||
| use FireflyIII\Transformers\RuleTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class RuleController | ||||
|  */ | ||||
| class RuleController extends Controller | ||||
| { | ||||
|     /** @var RuleRepositoryInterface The rule repository */ | ||||
|     private $ruleRepository; | ||||
|  | ||||
|     /** | ||||
|      * RuleController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 $this->ruleRepository = app(RuleRepositoryInterface::class); | ||||
|                 $this->ruleRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param Rule $rule | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Rule $rule): JsonResponse | ||||
|     { | ||||
|         $this->ruleRepository->destroy($rule); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of budgets. Count it and split it. | ||||
|         $collection = $this->ruleRepository->getAll(); | ||||
|         $count      = $collection->count(); | ||||
|         $rules      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rules.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($rules, new RuleTransformer($this->parameters), 'rules'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param Rule    $rule | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Rule $rule): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($rule, new RuleTransformer($this->parameters), 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param RuleRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(RuleRequest $request): JsonResponse | ||||
|     { | ||||
|         $rule    = $this->ruleRepository->store($request->getAll()); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($rule, new RuleTransformer($this->parameters), 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a rule. | ||||
|      * | ||||
|      * @param RuleRequest $request | ||||
|      * @param Rule        $rule | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(RuleRequest $request, Rule $rule): JsonResponse | ||||
|     { | ||||
|         $rule    = $this->ruleRepository->update($rule, $request->getAll()); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($rule, new RuleTransformer($this->parameters), 'rules'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										179
									
								
								app/Api/V1/Controllers/RuleGroupController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										179
									
								
								app/Api/V1/Controllers/RuleGroupController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,179 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleGroupController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\RuleGroupRequest; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; | ||||
| use FireflyIII\Transformers\RuleGroupTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class RuleGroupController | ||||
|  */ | ||||
| class RuleGroupController extends Controller | ||||
| { | ||||
|     /** @var RuleGroupRepositoryInterface The rule group repository */ | ||||
|     private $ruleGroupRepository; | ||||
|  | ||||
|     /** | ||||
|      * RuleGroupController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $user */ | ||||
|                 $user = auth()->user(); | ||||
|  | ||||
|                 $this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class); | ||||
|                 $this->ruleGroupRepository->setUser($user); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Delete the resource. | ||||
|      * | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(RuleGroup $ruleGroup): JsonResponse | ||||
|     { | ||||
|         $this->ruleGroupRepository->destroy($ruleGroup, null); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List all of them. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse] | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // create some objects: | ||||
|         $manager = new Manager; | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|  | ||||
|         // types to get, page size: | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // get list of rule groups. Count it and split it. | ||||
|         $collection = $this->ruleGroupRepository->get(); | ||||
|         $count      = $collection->count(); | ||||
|         $ruleGroups = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.rule_groups.index') . $this->buildParams()); | ||||
|  | ||||
|         // present to user. | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|         $resource = new FractalCollection($ruleGroups, new RuleGroupTransformer($this->parameters), 'rule_groups'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * List single resource. | ||||
|      * | ||||
|      * @param Request   $request | ||||
|      * @param RuleGroup $ruleGroup | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, RuleGroup $ruleGroup): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store new object. | ||||
|      * | ||||
|      * @param RuleGroupRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(RuleGroupRequest $request): JsonResponse | ||||
|     { | ||||
|         $ruleGroup = $this->ruleGroupRepository->store($request->getAll()); | ||||
|         $manager   = new Manager(); | ||||
|         $baseUrl   = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a rule group. | ||||
|      * | ||||
|      * @param RuleGroupRequest $request | ||||
|      * @param RuleGroup        $ruleGroup | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(RuleGroupRequest $request, RuleGroup $ruleGroup): JsonResponse | ||||
|     { | ||||
|         $ruleGroup = $this->ruleGroupRepository->update($ruleGroup, $request->getAll()); | ||||
|         $manager   = new Manager(); | ||||
|         $baseUrl   = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         $resource = new Item($ruleGroup, new RuleGroupTransformer($this->parameters), 'rule_groups'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										313
									
								
								app/Api/V1/Controllers/TransactionController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								app/Api/V1/Controllers/TransactionController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,313 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * TransactionController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\TransactionRequest; | ||||
| use FireflyIII\Events\StoredTransactionJournal; | ||||
| use FireflyIII\Events\UpdatedTransactionJournal; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Helpers\Collector\TransactionCollectorInterface; | ||||
| use FireflyIII\Helpers\Filter\InternalTransferFilter; | ||||
| use FireflyIII\Helpers\Filter\NegativeAmountFilter; | ||||
| use FireflyIII\Helpers\Filter\PositiveAmountFilter; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Transformers\TransactionTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Support\Collection; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
| /** | ||||
|  * Class TransactionController | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class TransactionController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var JournalRepositoryInterface The journal repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * TransactionController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var User $admin */ | ||||
|                 $admin = auth()->user(); | ||||
|  | ||||
|                 /** @var JournalRepositoryInterface repository */ | ||||
|                 $this->repository = app(JournalRepositoryInterface::class); | ||||
|                 $this->repository->setUser($admin); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \FireflyIII\Models\Transaction $transaction | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function delete(Transaction $transaction): JsonResponse | ||||
|     { | ||||
|         $journal = $transaction->transactionJournal; | ||||
|         $this->repository->destroy($journal); | ||||
|  | ||||
|         return response()->json([], 204); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show all transactions. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|         $type     = $request->get('type') ?? 'default'; | ||||
|         $this->parameters->set('type', $type); | ||||
|  | ||||
|         $types   = $this->mapTypes($this->parameters->get('type')); | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         /** @var TransactionCollectorInterface $collector */ | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser($admin); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         $collector->setAllAssetAccounts(); | ||||
|  | ||||
|         if (\in_array(TransactionType::TRANSFER, $types, true)) { | ||||
|             $collector->removeFilter(InternalTransferFilter::class); | ||||
|         } | ||||
|  | ||||
|         if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { | ||||
|             $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); | ||||
|         } | ||||
|         $collector->setLimit($pageSize)->setPage($this->parameters->get('page')); | ||||
|         $collector->setTypes($types); | ||||
|         $paginator = $collector->getPaginatedTransactions(); | ||||
|         $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); | ||||
|         $transactions = $paginator->getCollection(); | ||||
|  | ||||
|         $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Show a single transaction. | ||||
|      * | ||||
|      * @param Request     $request | ||||
|      * @param Transaction $transaction | ||||
|      * @param string      $include | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, Transaction $transaction, string $include = null): JsonResponse | ||||
|     { | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $include ?? ''; | ||||
|         $include = $request->get('include') ?? $include; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
|         $collector->setJournals(new Collection([$transaction->transactionJournal])); | ||||
|  | ||||
|         // add filter to remove transactions: | ||||
|         $transactionType = $transaction->transactionJournal->transactionType->type; | ||||
|         if ($transactionType === TransactionType::WITHDRAWAL) { | ||||
|             $collector->addFilter(PositiveAmountFilter::class); | ||||
|         } | ||||
|         if (!($transactionType === TransactionType::WITHDRAWAL)) { | ||||
|             $collector->addFilter(NegativeAmountFilter::class); | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         $resource     = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a new transaction. | ||||
|      * | ||||
|      * @param TransactionRequest         $request | ||||
|      * | ||||
|      * @param JournalRepositoryInterface $repository | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(TransactionRequest $request, JournalRepositoryInterface $repository): JsonResponse | ||||
|     { | ||||
|         $data         = $request->getAll(); | ||||
|         $data['user'] = auth()->user()->id; | ||||
|         $journal      = $repository->store($data); | ||||
|  | ||||
|         event(new StoredTransactionJournal($journal, 0)); | ||||
|  | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
|         $collector->setJournals(new Collection([$journal])); | ||||
|  | ||||
|         // add filter to remove transactions: | ||||
|         $transactionType = $journal->transactionType->type; | ||||
|         if ($transactionType === TransactionType::WITHDRAWAL) { | ||||
|             $collector->addFilter(PositiveAmountFilter::class); | ||||
|         } | ||||
|         if (!($transactionType === TransactionType::WITHDRAWAL)) { | ||||
|             $collector->addFilter(NegativeAmountFilter::class); | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         $resource     = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Update a transaction. | ||||
|      * | ||||
|      * @param TransactionRequest         $request | ||||
|      * @param JournalRepositoryInterface $repository | ||||
|      * @param Transaction                $transaction | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction): JsonResponse | ||||
|     { | ||||
|         $data         = $request->getAll(); | ||||
|         $data['user'] = auth()->user()->id; | ||||
|         $journal      = $repository->update($transaction->transactionJournal, $data); | ||||
|         $manager      = new Manager(); | ||||
|         $baseUrl      = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         event(new UpdatedTransactionJournal($journal)); | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         // needs a lot of extra data to match the journal collector. Or just expand that one. | ||||
|         // collect transactions using the journal collector | ||||
|         $collector = app(TransactionCollectorInterface::class); | ||||
|         $collector->setUser(auth()->user()); | ||||
|         $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); | ||||
|         // filter on specific journals. | ||||
|         $collector->setJournals(new Collection([$journal])); | ||||
|  | ||||
|         // add filter to remove transactions: | ||||
|         $transactionType = $journal->transactionType->type; | ||||
|         if ($transactionType === TransactionType::WITHDRAWAL) { | ||||
|             $collector->addFilter(PositiveAmountFilter::class); | ||||
|         } | ||||
|         if (!($transactionType === TransactionType::WITHDRAWAL)) { | ||||
|             $collector->addFilter(NegativeAmountFilter::class); | ||||
|         } | ||||
|  | ||||
|         $transactions = $collector->getTransactions(); | ||||
|         $resource     = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * All the types you can request. | ||||
|      * | ||||
|      * @param string $type | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function mapTypes(string $type): array | ||||
|     { | ||||
|         $types  = [ | ||||
|             'all'             => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE, | ||||
|                                   TransactionType::RECONCILIATION,], | ||||
|             'withdrawal'      => [TransactionType::WITHDRAWAL,], | ||||
|             'withdrawals'     => [TransactionType::WITHDRAWAL,], | ||||
|             'expense'         => [TransactionType::WITHDRAWAL,], | ||||
|             'income'          => [TransactionType::DEPOSIT,], | ||||
|             'deposit'         => [TransactionType::DEPOSIT,], | ||||
|             'deposits'        => [TransactionType::DEPOSIT,], | ||||
|             'transfer'        => [TransactionType::TRANSFER,], | ||||
|             'transfers'       => [TransactionType::TRANSFER,], | ||||
|             'opening_balance' => [TransactionType::OPENING_BALANCE,], | ||||
|             'reconciliation'  => [TransactionType::RECONCILIATION,], | ||||
|             'reconciliations' => [TransactionType::RECONCILIATION,], | ||||
|             'special'         => [TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,], | ||||
|             'specials'        => [TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,], | ||||
|             'default'         => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER,], | ||||
|         ]; | ||||
|         $return = $types['default']; | ||||
|         if (isset($types[$type])) { | ||||
|             $return = $types[$type]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										203
									
								
								app/Api/V1/Controllers/UserController.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								app/Api/V1/Controllers/UserController.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * UserController.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Controllers; | ||||
|  | ||||
| use FireflyIII\Api\V1\Requests\UserRequest; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\Transformers\UserTransformer; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Http\JsonResponse; | ||||
| use Illuminate\Http\Request; | ||||
| use Illuminate\Pagination\LengthAwarePaginator; | ||||
| use League\Fractal\Manager; | ||||
| use League\Fractal\Pagination\IlluminatePaginatorAdapter; | ||||
| use League\Fractal\Resource\Collection as FractalCollection; | ||||
| use League\Fractal\Resource\Item; | ||||
| use League\Fractal\Serializer\JsonApiSerializer; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class UserController. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  */ | ||||
| class UserController extends Controller | ||||
| { | ||||
|  | ||||
|     /** @var UserRepositoryInterface The user repository */ | ||||
|     private $repository; | ||||
|  | ||||
|     /** | ||||
|      * UserController constructor. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|         $this->middleware( | ||||
|             function ($request, $next) { | ||||
|                 /** @var UserRepositoryInterface repository */ | ||||
|                 $this->repository = app(UserRepositoryInterface::class); | ||||
|  | ||||
|                 return $next($request); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Remove the specified resource from storage. | ||||
|      * | ||||
|      * @param  \FireflyIII\User $user | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function delete(User $user): JsonResponse | ||||
|     { | ||||
|         /** @var User $admin */ | ||||
|         $admin = auth()->user(); | ||||
|         if ($this->repository->hasRole($admin, 'owner')) { | ||||
|             $this->repository->destroy($user); | ||||
|  | ||||
|             return response()->json([], 204); | ||||
|         } | ||||
|         throw new FireflyException('No access to method.'); // @codeCoverageIgnore | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Display a listing of the resource. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function index(Request $request): JsonResponse | ||||
|     { | ||||
|         // user preferences | ||||
|         $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; | ||||
|  | ||||
|         // make manager | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // build collection | ||||
|         $collection = $this->repository->all(); | ||||
|         $count      = $collection->count(); | ||||
|         $users      = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); | ||||
|  | ||||
|         // make paginator: | ||||
|         $paginator = new LengthAwarePaginator($users, $count, $pageSize, $this->parameters->get('page')); | ||||
|         $paginator->setPath(route('api.v1.users.index') . $this->buildParams()); | ||||
|  | ||||
|         // make resource | ||||
|         $resource = new FractalCollection($users, new UserTransformer($this->parameters), 'users'); | ||||
|         $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Show a single user. | ||||
|      * | ||||
|      * @param Request $request | ||||
|      * @param User    $user | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function show(Request $request, User $user): JsonResponse | ||||
|     { | ||||
|         // make manager | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         // make resource | ||||
|         $resource = new Item($user, new UserTransformer($this->parameters), 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Store a new user. | ||||
|      * | ||||
|      * @param UserRequest $request | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function store(UserRequest $request): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         $user = $this->repository->store($data); | ||||
|  | ||||
|         // make manager | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         // make resource | ||||
|         $resource = new Item($user, new UserTransformer($this->parameters), 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Update a user. | ||||
|      * | ||||
|      * @param UserRequest $request | ||||
|      * @param User        $user | ||||
|      * | ||||
|      * @return JsonResponse | ||||
|      */ | ||||
|     public function update(UserRequest $request, User $user): JsonResponse | ||||
|     { | ||||
|         $data = $request->getAll(); | ||||
|         $user = $this->repository->update($user, $data); | ||||
|  | ||||
|         // make manager | ||||
|         $manager = new Manager(); | ||||
|         $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; | ||||
|         $manager->setSerializer(new JsonApiSerializer($baseUrl)); | ||||
|  | ||||
|         // add include parameter: | ||||
|         $include = $request->get('include') ?? ''; | ||||
|         $manager->parseIncludes($include); | ||||
|  | ||||
|         // make resource | ||||
|         $resource = new Item($user, new UserTransformer($this->parameters), 'users'); | ||||
|  | ||||
|         return response()->json($manager->createData($resource)->toArray())->header('Content-Type', 'application/vnd.api+json'); | ||||
|  | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										136
									
								
								app/Api/V1/Requests/AccountRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								app/Api/V1/Requests/AccountRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,136 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * AccountRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
| /** | ||||
|  * Class AccountRequest | ||||
|  */ | ||||
| class AccountRequest extends Request | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'name'                 => $this->string('name'), | ||||
|             'active'               => $this->boolean('active'), | ||||
|             'include_net_worth'    => $this->boolean('include_net_worth'), | ||||
|             'accountType'          => $this->string('type'), | ||||
|             'account_type_id'      => null, | ||||
|             'currency_id'          => $this->integer('currency_id'), | ||||
|             'currency_code'        => $this->string('currency_code'), | ||||
|             'virtualBalance'       => $this->string('virtual_balance'), | ||||
|             'iban'                 => $this->string('iban'), | ||||
|             'BIC'                  => $this->string('bic'), | ||||
|             'accountNumber'        => $this->string('account_number'), | ||||
|             'accountRole'          => $this->string('account_role'), | ||||
|             'openingBalance'       => $this->string('opening_balance'), | ||||
|             'openingBalanceDate'   => $this->date('opening_balance_date'), | ||||
|             'ccType'               => $this->string('cc_type'), | ||||
|             'ccMonthlyPaymentDate' => $this->string('cc_monthly_payment_date'), | ||||
|             'notes'                => $this->string('notes'), | ||||
|             'interest'             => $this->string('interest'), | ||||
|             'interest_period'      => $this->string('interest_period'), | ||||
|         ]; | ||||
|         // new fields for liabilities | ||||
|         //            'liability_type'       => $this->string('liability_type'), | ||||
|         //            'liability_start_date' => $this->date('liability_start_date'), | ||||
|  | ||||
|  | ||||
|         //]; | ||||
|         if ('liability' === $data['accountType']) { | ||||
|             $data['openingBalance']     = bcmul($this->string('liability_amount'), '-1'); | ||||
|             $data['openingBalanceDate'] = $this->date('liability_start_date'); | ||||
|             $data['accountType']        = $this->string('liability_type'); | ||||
|             $data['account_type_id']    = null; | ||||
|         } | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $accountRoles   = implode(',', config('firefly.accountRoles')); | ||||
|         $types          = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); | ||||
|         $ccPaymentTypes = implode(',', array_keys(config('firefly.ccTypes'))); | ||||
|         $rules          = [ | ||||
|             'name'                    => 'required|min:1|uniqueAccountForUser', | ||||
|             'opening_balance'         => 'numeric|required_with:opening_balance_date|nullable', | ||||
|             'opening_balance_date'    => 'date|required_with:opening_balance|nullable', | ||||
|             'iban'                    => 'iban|nullable', | ||||
|             'bic'                     => 'bic|nullable', | ||||
|             'virtual_balance'         => 'numeric|nullable', | ||||
|             'currency_id'             => 'numeric|exists:transaction_currencies,id|required_without:currency_code', | ||||
|             'currency_code'           => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id', | ||||
|             'account_number'          => 'between:1,255|nullable|uniqueAccountNumberForUser', | ||||
|             'account_role'            => 'in:' . $accountRoles . '|required_if:type,asset', | ||||
|             'active'                  => 'required|boolean', | ||||
|             'include_net_worth'       => 'required|boolean', | ||||
|             'cc_type'                 => 'in:' . $ccPaymentTypes . '|required_if:account_role,ccAsset', | ||||
|             'cc_monthly_payment_date' => 'date' . '|required_if:account_role,ccAsset|required_if:cc_type,monthlyFull', | ||||
|             'type'                    => 'required|in:' . $types, | ||||
|             'notes'                   => 'min:0|max:65536', | ||||
|             // required fields for liabilities: | ||||
|             'liability_type'          => 'required_if:type,liability|in:loan,debt,mortgage,credit card', | ||||
|             'liability_amount'        => 'required_if:type,liability|min:0|numeric', | ||||
|             'liability_start_date'    => 'required_if:type,liability|date', | ||||
|             'interest'                => 'required_if:type,liability|between:0,100|numeric', | ||||
|             'interest_period'         => 'required_if:type,liability|in:daily,monthly,yearly', | ||||
|  | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $account                 = $this->route()->parameter('account'); | ||||
|                 $rules['name']           .= ':' . $account->id; | ||||
|                 $rules['account_number'] .= ':' . $account->id; | ||||
|                 $rules['type']           = 'in:' . $types; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										97
									
								
								app/Api/V1/Requests/AttachmentRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								app/Api/V1/Requests/AttachmentRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AttachmentRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\ImportJob; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Rules\IsValidAttachmentModel; | ||||
|  | ||||
| /** | ||||
|  * Class AttachmentRequest | ||||
|  */ | ||||
| class AttachmentRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'filename' => $this->string('filename'), | ||||
|             'title'    => $this->string('title'), | ||||
|             'notes'    => $this->string('notes'), | ||||
|             'model'    => $this->string('model'), | ||||
|             'model_id' => $this->integer('model_id'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $models = implode( | ||||
|             ',', [ | ||||
|                    Bill::class, | ||||
|                    ImportJob::class, | ||||
|                    TransactionJournal::class, | ||||
|                ] | ||||
|         ); | ||||
|         $model  = $this->string('model'); | ||||
|         $rules  = [ | ||||
|             'filename' => 'required|between:1,255', | ||||
|             'title'    => 'between:1,255', | ||||
|             'notes'    => 'between:1,65000', | ||||
|             'model'    => sprintf('required|in:%s', $models), | ||||
|             'model_id' => ['required', 'numeric', new IsValidAttachmentModel($model)], | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 unset($rules['model'], $rules['model_id']); | ||||
|                 $rules['filename'] = 'between:1,255'; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										77
									
								
								app/Api/V1/Requests/AvailableBudgetRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								app/Api/V1/Requests/AvailableBudgetRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| <?php | ||||
| /** | ||||
|  * AvailableBudgetRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| /** | ||||
|  * Class AvailableBudgetRequest | ||||
|  */ | ||||
| class AvailableBudgetRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'currency_id'   => $this->integer('currency_id'), | ||||
|             'currency_code' => $this->string('currency_code'), | ||||
|             'amount'        => $this->string('amount'), | ||||
|             'start_date'    => $this->date('start_date'), | ||||
|             'end_date'      => $this->date('end_date'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'currency_id'   => 'numeric|exists:transaction_currencies,id|required_without:currency_code', | ||||
|             'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id', | ||||
|             'amount'        => 'required|numeric|more:0', | ||||
|             'start_date'    => 'required|date|before:end_date', | ||||
|             'end_date'      => 'required|date|after:start_date', | ||||
|         ]; | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
							
								
								
									
										123
									
								
								app/Api/V1/Requests/BillRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								app/Api/V1/Requests/BillRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * BillRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * Class BillRequest | ||||
|  */ | ||||
| class BillRequest extends Request | ||||
| { | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'name'          => $this->string('name'), | ||||
|             'amount_min'    => $this->string('amount_min'), | ||||
|             'amount_max'    => $this->string('amount_max'), | ||||
|             'currency_id'   => $this->integer('currency_id'), | ||||
|             'currency_code' => $this->string('currency_code'), | ||||
|             'date'          => $this->date('date'), | ||||
|             'repeat_freq'   => $this->string('repeat_freq'), | ||||
|             'skip'          => $this->integer('skip'), | ||||
|             'automatch'     => $this->boolean('automatch'), | ||||
|             'active'        => $this->boolean('active'), | ||||
|             'notes'         => $this->string('notes'), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'          => 'required|between:1,255|uniqueObjectForUser:bills,name', | ||||
|             'amount_min'    => 'required|numeric|more:0', | ||||
|             'amount_max'    => 'required|numeric|more:0', | ||||
|             'currency_id'   => 'numeric|exists:transaction_currencies,id|required_without:currency_code', | ||||
|             'currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:currency_id', | ||||
|             'date'          => 'required|date', | ||||
|             'repeat_freq'   => 'required|in:weekly,monthly,quarterly,half-year,yearly', | ||||
|             'skip'          => 'required|between:0,31', | ||||
|             'automatch'     => 'required|boolean', | ||||
|             'active'        => 'required|boolean', | ||||
|             'notes'         => 'between:1,65536', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $bill          = $this->route()->parameter('bill'); | ||||
|                 $rules['name'] .= ',' . $bill->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $data = $validator->getData(); | ||||
|                 $min  = (float)($data['amount_min'] ?? 0); | ||||
|                 $max  = (float)($data['amount_max'] ?? 0); | ||||
|                 if ($min > $max) { | ||||
|                     $validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max')); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										83
									
								
								app/Api/V1/Requests/BudgetLimitRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								app/Api/V1/Requests/BudgetLimitRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,83 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetLimitRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class BudgetLimitRequest | ||||
|  */ | ||||
| class BudgetLimitRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'budget_id'  => $this->integer('budget_id'), | ||||
|             'start_date' => $this->date('start_date'), | ||||
|             'end_date'   => $this->date('end_date'), | ||||
|             'amount'     => $this->string('amount'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'budget_id'  => 'required|exists:budgets,id|belongsToUser:budgets,id', | ||||
|             'start_date' => 'required|before:end_date|date', | ||||
|             'end_date'   => 'required|after:start_date|date', | ||||
|             'amount'     => 'required|more:0', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $rules['budget_id'] = 'required|exists:budgets,id|belongsToUser:budgets,id'; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										82
									
								
								app/Api/V1/Requests/BudgetRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								app/Api/V1/Requests/BudgetRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| <?php | ||||
| /** | ||||
|  * BudgetRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Budget; | ||||
|  | ||||
| /** | ||||
|  * Class BudgetRequest | ||||
|  */ | ||||
| class BudgetRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'name'   => $this->string('name'), | ||||
|             'active' => $this->boolean('active'), | ||||
|             'order'  => 0, | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'   => 'required|between:1,100|uniqueObjectForUser:budgets,name', | ||||
|             'active' => 'required|boolean', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var Budget $budget */ | ||||
|                 $budget        = $this->route()->parameter('budget'); | ||||
|                 $rules['name'] = sprintf('required|between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										81
									
								
								app/Api/V1/Requests/CategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								app/Api/V1/Requests/CategoryRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CategoryRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\Category; | ||||
|  | ||||
| /** | ||||
|  * Class CategoryRequest | ||||
|  */ | ||||
| class CategoryRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'name'   => $this->string('name'), | ||||
|             'active' => $this->boolean('active'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'   => 'required|between:1,100|uniqueObjectForUser:categories,name', | ||||
|             'active' => 'required|boolean', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var Category $category */ | ||||
|                 $category      = $this->route()->parameter('category'); | ||||
|                 $rules['name'] = sprintf('required|between:1,100|uniqueObjectForUser:categories,name,%d', $category->id); | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										89
									
								
								app/Api/V1/Requests/CurrencyRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								app/Api/V1/Requests/CurrencyRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CurrencyRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class CurrencyRequest | ||||
|  */ | ||||
| class CurrencyRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'name'           => $this->string('name'), | ||||
|             'code'           => $this->string('code'), | ||||
|             'symbol'         => $this->string('symbol'), | ||||
|             'decimal_places' => $this->integer('decimal_places'), | ||||
|             'default'        => $this->boolean('default'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'           => 'required|between:1,255|unique:transaction_currencies,name', | ||||
|             'code'           => 'required|between:3,3|unique:transaction_currencies,code', | ||||
|             'symbol'         => 'required|between:1,5|unique:transaction_currencies,symbol', | ||||
|             'decimal_places' => 'required|between:0,20|numeric|min:0|max:20', | ||||
|             'default'        => 'boolean', | ||||
|         ]; | ||||
|  | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $currency        = $this->route()->parameter('currency'); | ||||
|                 $rules['name']   = 'required|between:1,255|unique:transaction_currencies,name,' . $currency->id; | ||||
|                 $rules['code']   = 'required|between:1,255|unique:transaction_currencies,code,' . $currency->id; | ||||
|                 $rules['symbol'] = 'required|between:1,255|unique:transaction_currencies,symbol,' . $currency->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|  | ||||
|     } | ||||
| } | ||||
							
								
								
									
										131
									
								
								app/Api/V1/Requests/JournalLinkRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										131
									
								
								app/Api/V1/Requests/JournalLinkRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,131 @@ | ||||
| <?php | ||||
| /** | ||||
|  * JournalLinkRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class JournalLinkRequest | ||||
|  */ | ||||
| class JournalLinkRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'link_type_id'   => $this->integer('link_type_id'), | ||||
|             'link_type_name' => $this->string('link_type_name'), | ||||
|             'inward_id'      => $this->integer('inward_id'), | ||||
|             'outward_id'     => $this->integer('outward_id'), | ||||
|             'notes'          => $this->string('notes'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'link_type_id'   => 'exists:link_types,id|required_without:link_type_name', | ||||
|             'link_type_name' => 'exists:link_types,name|required_without:link_type_id', | ||||
|             'inward_id'      => 'required|belongsToUser:transaction_journals,id', | ||||
|             'outward_id'     => 'required|belongsToUser:transaction_journals,id', | ||||
|             'notes'          => 'between:0,65000', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->validateExistingLink($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     private function validateExistingLink(Validator $validator): void | ||||
|     { | ||||
|         /** @var LinkTypeRepositoryInterface $repository */ | ||||
|         $repository = app(LinkTypeRepositoryInterface::class); | ||||
|         $repository->setUser(auth()->user()); | ||||
|  | ||||
|         /** @var JournalRepositoryInterface $journalRepos */ | ||||
|         $journalRepos = app(JournalRepositoryInterface::class); | ||||
|         $journalRepos->setUser(auth()->user()); | ||||
|  | ||||
|         $data      = $validator->getData(); | ||||
|         $inwardId  = (int)($data['inward_id'] ?? 0); | ||||
|         $outwardId = (int)($data['outward_id'] ?? 0); | ||||
|         $inward    = $journalRepos->findNull($inwardId); | ||||
|         $outward   = $journalRepos->findNull($outwardId); | ||||
|  | ||||
|         if (null === $inward) { | ||||
|             $validator->errors()->add('inward_id', 'Invalid inward ID.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|         if (null === $outward) { | ||||
|             $validator->errors()->add('outward_id', 'Invalid outward ID.'); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if ($repository->findLink($inward, $outward)) { | ||||
|             $validator->errors()->add('outward_id', 'Already have a link between inward and outward.'); | ||||
|             $validator->errors()->add('inward_id', 'Already have a link between inward and outward.'); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										91
									
								
								app/Api/V1/Requests/LinkTypeRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								app/Api/V1/Requests/LinkTypeRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| <?php | ||||
| /** | ||||
|  * LinkTypeRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\LinkType; | ||||
| use Illuminate\Validation\Rule; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class LinkTypeRequest | ||||
|  */ | ||||
| class LinkTypeRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'name'    => $this->string('name'), | ||||
|             'outward' => $this->string('outward'), | ||||
|             'inward'  => $this->string('inward'), | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'    => 'required|unique:link_types,name|min:1', | ||||
|             'outward' => 'required|unique:link_types,outward|min:1|different:inward', | ||||
|             'inward'  => 'required|unique:link_types,inward|min:1|different:outward', | ||||
|         ]; | ||||
|  | ||||
|  | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var LinkType $linkType */ | ||||
|                 $linkType         = $this->route()->parameter('linkType'); | ||||
|                 $rules['name']    = ['required', Rule::unique('link_types', 'name')->ignore($linkType->id), 'min:1']; | ||||
|                 $rules['outward'] = ['required', 'different:inward', Rule::unique('link_types', 'outward')->ignore($linkType->id), 'min:1']; | ||||
|                 $rules['inward']  = ['required', 'different:outward', Rule::unique('link_types', 'inward')->ignore($linkType->id), 'min:1']; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										99
									
								
								app/Api/V1/Requests/PiggyBankRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								app/Api/V1/Requests/PiggyBankRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,99 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PiggyBankRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\PiggyBank; | ||||
| use FireflyIII\Rules\IsAssetAccountId; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PiggyBankRequest | ||||
|  */ | ||||
| class PiggyBankRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $current = $this->string('current_amount'); | ||||
|         $current = '' === $current ? '0' : $current; | ||||
|  | ||||
|         return [ | ||||
|             'name'           => $this->string('name'), | ||||
|             'account_id'     => $this->integer('account_id'), | ||||
|             'targetamount'   => $this->string('target_amount'), | ||||
|             'current_amount' => $current, | ||||
|             'start_date'     => $this->date('start_date'), | ||||
|             'target_date'    => $this->date('target_date'), | ||||
|             'notes'          => $this->string('notes'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'name'           => 'required|between:1,255|uniquePiggyBankForUser', | ||||
|             'account_id'     => ['required', 'belongsToUser:accounts', new IsAssetAccountId], | ||||
|             'target_amount'  => 'required|numeric|more:0', | ||||
|             'current_amount' => 'numeric|more:0|lte:target_amount', | ||||
|             'start_date'     => 'date|nullable', | ||||
|             'target_date'    => 'date|nullable|after:start_date', | ||||
|             'notes'          => 'max:65000', | ||||
|         ]; | ||||
|  | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var PiggyBank $piggyBank */ | ||||
|                 $piggyBank     = $this->route()->parameter('piggyBank'); | ||||
|                 $rules['name'] = 'required|between:1,255|uniquePiggyBankForUser:' . $piggyBank->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										69
									
								
								app/Api/V1/Requests/PreferenceRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								app/Api/V1/Requests/PreferenceRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| <?php | ||||
| /** | ||||
|  * PreferenceRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class PreferenceRequest | ||||
|  */ | ||||
| class PreferenceRequest extends Request | ||||
| { | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'data' => $this->get('data'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         return [ | ||||
|             'data' => 'required|between:1,65000', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| } | ||||
							
								
								
									
										203
									
								
								app/Api/V1/Requests/RecurrenceRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								app/Api/V1/Requests/RecurrenceRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RecurrenceRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use Carbon\Carbon; | ||||
| use FireflyIII\Rules\BelongsUser; | ||||
| use FireflyIII\Validation\RecurrenceValidation; | ||||
| use FireflyIII\Validation\TransactionValidation; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
| /** | ||||
|  * Class RecurrenceRequest | ||||
|  */ | ||||
| class RecurrenceRequest extends Request | ||||
| { | ||||
|     use RecurrenceValidation, TransactionValidation; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $return = [ | ||||
|             'recurrence'   => [ | ||||
|                 'type'         => $this->string('type'), | ||||
|                 'title'        => $this->string('title'), | ||||
|                 'description'  => $this->string('description'), | ||||
|                 'first_date'   => $this->date('first_date'), | ||||
|                 'repeat_until' => $this->date('repeat_until'), | ||||
|                 'repetitions'  => $this->integer('nr_of_repetitions'), | ||||
|                 'apply_rules'  => $this->boolean('apply_rules'), | ||||
|                 'active'       => $this->boolean('active'), | ||||
|             ], | ||||
|             'meta'         => [ | ||||
|                 'piggy_bank_id'   => $this->integer('piggy_bank_id'), | ||||
|                 'piggy_bank_name' => $this->string('piggy_bank_name'), | ||||
|                 'tags'            => explode(',', $this->string('tags')), | ||||
|             ], | ||||
|             'transactions' => $this->getTransactionData(), | ||||
|             'repetitions'  => $this->getRepetitionData(), | ||||
|         ]; | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $today = Carbon::now()->addDay(); | ||||
|  | ||||
|         return [ | ||||
|             'type'                                 => 'required|in:withdrawal,transfer,deposit', | ||||
|             'title'                                => 'required|between:1,255|uniqueObjectForUser:recurrences,title', | ||||
|             'description'                          => 'between:1,65000', | ||||
|             'first_date'                           => sprintf('required|date|after:%s', $today->format('Y-m-d')), | ||||
|             'repeat_until'                         => sprintf('date|after:%s', $today->format('Y-m-d')), | ||||
|             'nr_of_repetitions'                    => 'numeric|between:1,31', | ||||
|             'apply_rules'                          => 'required|boolean', | ||||
|             'active'                               => 'required|boolean', | ||||
|             'tags'                                 => 'between:1,64000', | ||||
|             'piggy_bank_id'                        => 'numeric', | ||||
|             'repetitions.*.type'                   => 'required|in:daily,weekly,ndom,monthly,yearly', | ||||
|             'repetitions.*.moment'                 => 'between:0,10', | ||||
|             'repetitions.*.skip'                   => 'required|numeric|between:0,31', | ||||
|             'repetitions.*.weekend'                => 'required|numeric|min:1|max:4', | ||||
|             'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code', | ||||
|             'transactions.*.currency_code'         => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id', | ||||
|             'transactions.*.foreign_amount'        => 'numeric|more:0', | ||||
|             'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'transactions.*.budget_id'             => ['mustExist:budgets,id', new BelongsUser], | ||||
|             'transactions.*.category_name'         => 'between:1,255|nullable', | ||||
|             'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.source_name'           => 'between:1,255|nullable', | ||||
|             'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.destination_name'      => 'between:1,255|nullable', | ||||
|             'transactions.*.amount'                => 'required|numeric|more:0', | ||||
|             'transactions.*.description'           => 'required|between:1,255', | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->validateOneTransaction($validator); | ||||
|                 $this->validateOneRepetition($validator); | ||||
|                 $this->validateRecurrenceRepetition($validator); | ||||
|                 $this->validateRepetitionMoment($validator); | ||||
|                 $this->validateForeignCurrencyInformation($validator); | ||||
|                 $this->validateAccountInformation($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * Returns the repetition data as it is found in the submitted data. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getRepetitionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         // repetition data: | ||||
|         /** @var array $repetitions */ | ||||
|         $repetitions = $this->get('repetitions'); | ||||
|         /** @var array $repetition */ | ||||
|         foreach ($repetitions as $repetition) { | ||||
|             $return[] = [ | ||||
|                 'type'    => $repetition['type'], | ||||
|                 'moment'  => $repetition['moment'], | ||||
|                 'skip'    => (int)$repetition['skip'], | ||||
|                 'weekend' => (int)$repetition['weekend'], | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the transaction data as it is found in the submitted data. It's a complex method according to code | ||||
|      * standards but it just has a lot of ??-statements because of the fields that may or may not exist. | ||||
|      * | ||||
|      * @return array | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         // transaction data: | ||||
|         /** @var array $transactions */ | ||||
|         $transactions = $this->get('transactions'); | ||||
|         /** @var array $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             $return[] = [ | ||||
|                 'amount'                => $transaction['amount'], | ||||
|                 'currency_id'           => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, | ||||
|                 'currency_code'         => $transaction['currency_code'] ?? null, | ||||
|                 'foreign_amount'        => $transaction['foreign_amount'] ?? null, | ||||
|                 'foreign_currency_id'   => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, | ||||
|                 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, | ||||
|                 'budget_id'             => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, | ||||
|                 'budget_name'           => $transaction['budget_name'] ?? null, | ||||
|                 'category_id'           => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, | ||||
|                 'category_name'         => $transaction['category_name'] ?? null, | ||||
|                 'source_id'             => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, | ||||
|                 'source_name'           => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, | ||||
|                 'destination_id'        => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, | ||||
|                 'destination_name'      => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, | ||||
|                 'description'           => $transaction['description'], | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										39
									
								
								app/Api/V1/Requests/Request.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								app/Api/V1/Requests/Request.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Request.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Http\Requests\Request as FireflyIIIRequest; | ||||
|  | ||||
| /** | ||||
|  * Class Request. | ||||
|  * | ||||
|  * Technically speaking this class does not have to be extended like this but who knows what the future brings. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.NumberOfChildren) | ||||
|  */ | ||||
| class Request extends FireflyIIIRequest | ||||
| { | ||||
|  | ||||
| } | ||||
							
								
								
									
										85
									
								
								app/Api/V1/Requests/RuleGroupRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								app/Api/V1/Requests/RuleGroupRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleGroupRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Models\RuleGroup; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Class RuleGroupRequest | ||||
|  */ | ||||
| class RuleGroupRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         return [ | ||||
|             'title'       => $this->string('title'), | ||||
|             'description' => $this->string('description'), | ||||
|             'active'      => $this->boolean('active'), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'title'       => 'required|between:1,100|uniqueObjectForUser:rule_groups,title', | ||||
|             'description' => 'between:1,5000|nullable', | ||||
|             'active'      => 'required|boolean', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 /** @var RuleGroup $ruleGroup */ | ||||
|                 $ruleGroup      = $this->route()->parameter('ruleGroup'); | ||||
|                 $rules['title'] = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										187
									
								
								app/Api/V1/Requests/RuleRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								app/Api/V1/Requests/RuleRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| <?php | ||||
| /** | ||||
|  * RuleRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class RuleRequest | ||||
|  */ | ||||
| class RuleRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'title'            => $this->string('title'), | ||||
|             'description'      => $this->string('description'), | ||||
|             'rule_group_id'    => $this->integer('rule_group_id'), | ||||
|             'rule_group_title' => $this->string('rule_group_title'), | ||||
|             'trigger'          => $this->string('trigger'), | ||||
|             'strict'           => $this->boolean('strict'), | ||||
|             'stop_processing'  => $this->boolean('stop_processing'), | ||||
|             'active'           => $this->boolean('active'), | ||||
|             'rule_triggers'    => $this->getRuleTriggers(), | ||||
|             'rule_actions'     => $this->getRuleActions(), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $validTriggers = array_keys(config('firefly.rule-triggers')); | ||||
|         $validActions  = array_keys(config('firefly.rule-actions')); | ||||
|  | ||||
|         // some actions require text: | ||||
|         $contextActions = implode(',', config('firefly.rule-actions-text')); | ||||
|  | ||||
|         $rules = [ | ||||
|             'title'                           => 'required|between:1,100|uniqueObjectForUser:rules,title', | ||||
|             'description'                     => 'between:1,5000|nullable', | ||||
|             'rule_group_id'                   => 'required|belongsToUser:rule_groups|required_without:rule_group_title', | ||||
|             'rule_group_title'                => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title', | ||||
|             'trigger'                         => 'required|in:store-journal,update-journal', | ||||
|             'rule_triggers.*.name'            => 'required|in:' . implode(',', $validTriggers), | ||||
|             'rule_triggers.*.stop_processing' => 'boolean', | ||||
|             'rule_triggers.*.value'           => 'required|min:1|ruleTriggerValue', | ||||
|             'rule_actions.*.name'             => 'required|in:' . implode(',', $validActions), | ||||
|             'rule_actions.*.value'            => 'required_if:rule_actions.*.type,' . $contextActions . '|ruleActionValue', | ||||
|             'rule_actions.*.stop_processing'  => 'boolean', | ||||
|             'strict'                          => 'required|boolean', | ||||
|             'stop_processing'                 => 'required|boolean', | ||||
|             'active'                          => 'required|boolean', | ||||
|         ]; | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->atLeastOneTrigger($validator); | ||||
|                 $this->atLeastOneAction($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds an error to the validator when there are no repetitions in the array of data. | ||||
|      * | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     protected function atLeastOneAction(Validator $validator): void | ||||
|     { | ||||
|         $data        = $validator->getData(); | ||||
|         $repetitions = $data['rule_actions'] ?? []; | ||||
|         // need at least one transaction | ||||
|         if (0 === \count($repetitions)) { | ||||
|             $validator->errors()->add('title', (string)trans('validation.at_least_one_action')); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds an error to the validator when there are no repetitions in the array of data. | ||||
|      * | ||||
|      * @param Validator $validator | ||||
|      */ | ||||
|     protected function atLeastOneTrigger(Validator $validator): void | ||||
|     { | ||||
|         $data        = $validator->getData(); | ||||
|         $repetitions = $data['rule_triggers'] ?? []; | ||||
|         // need at least one transaction | ||||
|         if (0 === \count($repetitions)) { | ||||
|             $validator->errors()->add('title', (string)trans('validation.at_least_one_trigger')); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getRuleActions(): array | ||||
|     { | ||||
|         $actions = $this->get('rule_actions'); | ||||
|         $return  = []; | ||||
|         if (\is_array($actions)) { | ||||
|             foreach ($actions as $action) { | ||||
|                 $return[] = [ | ||||
|                     'name'            => $action['name'], | ||||
|                     'value'           => $action['value'], | ||||
|                     'stop_processing' => 1 === (int)($action['stop-processing'] ?? '0'), | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getRuleTriggers(): array | ||||
|     { | ||||
|         $triggers = $this->get('rule_triggers'); | ||||
|         $return   = []; | ||||
|         if (\is_array($triggers)) { | ||||
|             foreach ($triggers as $trigger) { | ||||
|                 $return[] = [ | ||||
|                     'name'            => $trigger['name'], | ||||
|                     'value'           => $trigger['value'], | ||||
|                     'stop_processing' => 1 === (int)($trigger['stop-processing'] ?? '0'), | ||||
|                 ]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										197
									
								
								app/Api/V1/Requests/TransactionRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								app/Api/V1/Requests/TransactionRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * TransactionRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Rules\BelongsUser; | ||||
| use FireflyIII\Validation\TransactionValidation; | ||||
| use Illuminate\Validation\Validator; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class TransactionRequest | ||||
|  */ | ||||
| class TransactionRequest extends Request | ||||
| { | ||||
|     use TransactionValidation; | ||||
|  | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         // Only allow authenticated users | ||||
|         return auth()->check(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data. Is pretty complex because of all the ??-statements. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'type'               => $this->string('type'), | ||||
|             'date'               => $this->date('date'), | ||||
|             'description'        => $this->string('description'), | ||||
|             'piggy_bank_id'      => $this->integer('piggy_bank_id'), | ||||
|             'piggy_bank_name'    => $this->string('piggy_bank_name'), | ||||
|             'bill_id'            => $this->integer('bill_id'), | ||||
|             'bill_name'          => $this->string('bill_name'), | ||||
|             'tags'               => explode(',', $this->string('tags')), | ||||
|             'interest_date'      => $this->date('interest_date'), | ||||
|             'book_date'          => $this->date('book_date'), | ||||
|             'process_date'       => $this->date('process_date'), | ||||
|             'due_date'           => $this->date('due_date'), | ||||
|             'payment_date'       => $this->date('payment_date'), | ||||
|             'invoice_date'       => $this->date('invoice_date'), | ||||
|             'internal_reference' => $this->string('internal_reference'), | ||||
|             'notes'              => $this->string('notes'), | ||||
|             'original-source'    => sprintf('api-v%s', config('firefly.api_version')), | ||||
|             'transactions'       => $this->getTransactionData(), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             // basic fields for journal: | ||||
|             'type'                                 => 'required|in:withdrawal,deposit,transfer', | ||||
|             'date'                                 => 'required|date', | ||||
|             'description'                          => 'between:1,255', | ||||
|             'piggy_bank_id'                        => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser], | ||||
|             'piggy_bank_name'                      => ['between:1,255', 'nullable', new BelongsUser], | ||||
|             'bill_id'                              => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser], | ||||
|             'bill_name'                            => ['between:1,255', 'nullable', new BelongsUser], | ||||
|             'tags'                                 => 'between:1,255', | ||||
|  | ||||
|             // then, custom fields for journal | ||||
|             'interest_date'                        => 'date|nullable', | ||||
|             'book_date'                            => 'date|nullable', | ||||
|             'process_date'                         => 'date|nullable', | ||||
|             'due_date'                             => 'date|nullable', | ||||
|             'payment_date'                         => 'date|nullable', | ||||
|             'invoice_date'                         => 'date|nullable', | ||||
|             'internal_reference'                   => 'min:1,max:255|nullable', | ||||
|             'notes'                                => 'min:1,max:50000|nullable', | ||||
|  | ||||
|             // transaction rules (in array for splits): | ||||
|             'transactions.*.description'           => 'nullable|between:1,255', | ||||
|             'transactions.*.amount'                => 'required|numeric|more:0', | ||||
|             'transactions.*.currency_id'           => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code', | ||||
|             'transactions.*.currency_code'         => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id', | ||||
|             'transactions.*.foreign_amount'        => 'numeric|more:0', | ||||
|             'transactions.*.foreign_currency_id'   => 'numeric|exists:transaction_currencies,id', | ||||
|             'transactions.*.foreign_currency_code' => 'min:3|max:3|exists:transaction_currencies,code', | ||||
|             'transactions.*.budget_id'             => ['mustExist:budgets,id', new BelongsUser], | ||||
|             'transactions.*.budget_name'           => ['between:1,255', 'nullable', new BelongsUser], | ||||
|             'transactions.*.category_id'           => ['mustExist:categories,id', new BelongsUser], | ||||
|             'transactions.*.category_name'         => 'between:1,255|nullable', | ||||
|             'transactions.*.reconciled'            => 'boolean|nullable', | ||||
|             // basic rules will be expanded later. | ||||
|             'transactions.*.source_id'             => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.source_name'           => 'between:1,255|nullable', | ||||
|             'transactions.*.destination_id'        => ['numeric', 'nullable', new BelongsUser], | ||||
|             'transactions.*.destination_name'      => 'between:1,255|nullable', | ||||
|         ]; | ||||
|  | ||||
|         if ('PUT' === $this->method()) { | ||||
|             unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']); | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|  | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Configure the validator instance. | ||||
|      * | ||||
|      * @param  Validator $validator | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function withValidator(Validator $validator): void | ||||
|     { | ||||
|         $validator->after( | ||||
|             function (Validator $validator) { | ||||
|                 $this->validateOneTransaction($validator); | ||||
|                 $this->validateDescriptions($validator); | ||||
|                 $this->validateJournalDescription($validator); | ||||
|                 $this->validateSplitDescriptions($validator); | ||||
|                 $this->validateForeignCurrencyInformation($validator); | ||||
|                 $this->validateAccountInformation($validator); | ||||
|                 $this->validateSplitAccounts($validator); | ||||
|             } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get transaction data. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * @return array | ||||
|      */ | ||||
|     private function getTransactionData(): array | ||||
|     { | ||||
|         $return = []; | ||||
|         foreach ($this->get('transactions') as $index => $transaction) { | ||||
|             $return[] = [ | ||||
|                 'description'           => $transaction['description'] ?? null, | ||||
|                 'amount'                => $transaction['amount'], | ||||
|                 'currency_id'           => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, | ||||
|                 'currency_code'         => $transaction['currency_code'] ?? null, | ||||
|                 'foreign_amount'        => $transaction['foreign_amount'] ?? null, | ||||
|                 'foreign_currency_id'   => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, | ||||
|                 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, | ||||
|                 'budget_id'             => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, | ||||
|                 'budget_name'           => $transaction['budget_name'] ?? null, | ||||
|                 'category_id'           => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, | ||||
|                 'category_name'         => $transaction['category_name'] ?? null, | ||||
|                 'source_id'             => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, | ||||
|                 'source_name'           => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, | ||||
|                 'destination_id'        => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, | ||||
|                 'destination_name'      => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, | ||||
|                 'reconciled'            => $transaction['reconciled'] ?? false, | ||||
|                 'identifier'            => $index, | ||||
|             ]; | ||||
|         } | ||||
|  | ||||
|         return $return; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										101
									
								
								app/Api/V1/Requests/UserRequest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								app/Api/V1/Requests/UserRequest.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * UserRequest.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Api\V1\Requests; | ||||
|  | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Class UserRequest | ||||
|  */ | ||||
| class UserRequest extends Request | ||||
| { | ||||
|     /** | ||||
|      * Authorize logged in users. | ||||
|      * | ||||
|      * @return bool | ||||
|      */ | ||||
|     public function authorize(): bool | ||||
|     { | ||||
|         $result = false; | ||||
|         // Only allow authenticated users | ||||
|         if (auth()->check()) { | ||||
|             /** @var User $user */ | ||||
|             $user = auth()->user(); | ||||
|  | ||||
|             /** @var UserRepositoryInterface $repository */ | ||||
|             $repository = app(UserRepositoryInterface::class); | ||||
|  | ||||
|             if ($repository->hasRole($user, 'owner')) { | ||||
|                 $result = true; // @codeCoverageIgnore | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get all data from the request. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function getAll(): array | ||||
|     { | ||||
|         $data = [ | ||||
|             'email'        => $this->string('email'), | ||||
|             'blocked'      => $this->boolean('blocked'), | ||||
|             'blocked_code' => $this->string('blocked_code'), | ||||
|         ]; | ||||
|  | ||||
|         return $data; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The rules that the incoming request must be matched against. | ||||
|      * | ||||
|      * @return array | ||||
|      */ | ||||
|     public function rules(): array | ||||
|     { | ||||
|         $rules = [ | ||||
|             'email'        => 'required|email|unique:users,email,', | ||||
|             'blocked'      => 'required|boolean', | ||||
|             'blocked_code' => 'in:email_changed', | ||||
|         ]; | ||||
|         switch ($this->method()) { | ||||
|             default: | ||||
|                 break; | ||||
|             case 'PUT': | ||||
|             case 'PATCH': | ||||
|                 $user           = $this->route()->parameter('user'); | ||||
|                 $rules['email'] = 'required|email|unique:users,email,' . $user->id; | ||||
|                 break; | ||||
|         } | ||||
|  | ||||
|         return $rules; | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CreateExport.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,6 +18,9 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** @noinspection MultipleReturnStatementsInspection */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
| @@ -36,10 +39,13 @@ use Storage; | ||||
|  * Class CreateExport. | ||||
|  * | ||||
|  * Generates export from the command line. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class CreateExport extends Command | ||||
| { | ||||
|     use VerifiesAccessToken; | ||||
|  | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
| @@ -60,27 +66,18 @@ class CreateExport extends Command | ||||
|                             {--with_uploads : Include user\'s uploads?}'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five its fine. | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @return mixed | ||||
|      * @return int | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         if (!$this->verifyAccessToken()) { | ||||
|             $this->error('Invalid access token.'); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|         $this->line('Full export is running...'); | ||||
|         // make repositories | ||||
| @@ -94,15 +91,18 @@ class CreateExport extends Command | ||||
|         $journalRepository = app(JournalRepositoryInterface::class); | ||||
|  | ||||
|         // set user | ||||
|         $user = $userRepository->find(intval($this->option('user'))); | ||||
|         $user = $userRepository->findNull((int)$this->option('user')); | ||||
|         if (null === $user) { | ||||
|             return 1; | ||||
|         } | ||||
|         $jobRepository->setUser($user); | ||||
|         $journalRepository->setUser($user); | ||||
|         $accountRepository->setUser($user); | ||||
|  | ||||
|         // first date | ||||
|         $firstJournal = $journalRepository->first(); | ||||
|         $firstJournal = $journalRepository->firstNull(); | ||||
|         $first        = new Carbon; | ||||
|         if (null !== $firstJournal->id) { | ||||
|         if (null !== $firstJournal) { | ||||
|             $first = $firstJournal->date; | ||||
|         } | ||||
|  | ||||
| @@ -141,6 +141,6 @@ class CreateExport extends Command | ||||
|         $this->line('The export has finished! You can find the ZIP file in this location:'); | ||||
|         $this->line(storage_path(sprintf('export/%s', $fileName))); | ||||
|  | ||||
|         return; | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * CreateImport.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,24 +18,27 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** @noinspection MultipleReturnStatementsInspection */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
|  | ||||
| use Artisan; | ||||
| use Exception; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Import\Logging\CommandHandler; | ||||
| use FireflyIII\Import\Prerequisites\PrerequisitesInterface; | ||||
| use FireflyIII\Import\Routine\RoutineInterface; | ||||
| use FireflyIII\Import\Storage\ImportArrayStorage; | ||||
| use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\MessageBag; | ||||
| use Log; | ||||
| use Monolog\Formatter\LineFormatter; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Class CreateImport. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class CreateImport extends Command | ||||
| { | ||||
| @@ -54,150 +57,244 @@ class CreateImport extends Command | ||||
|      */ | ||||
|     protected $signature | ||||
|         = 'firefly:create-import | ||||
|                             {file : The file to import.} | ||||
|                             {configuration : The configuration file to use for the import.} | ||||
|                             {file? : The file to import.} | ||||
|                             {configuration? : The configuration file to use for the import.} | ||||
|                             {--type=csv : The file type of the import.} | ||||
|                             {--user= : The user ID that the import should import for.} | ||||
|                             {--provider=file : The file type of the import.} | ||||
|                             {--user=1 : The user ID that the import should import for.} | ||||
|                             {--token= : The user\'s access token.} | ||||
|                             {--start : Starts the job immediately.}'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the command. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly. | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         if (!$this->verifyAccessToken()) { | ||||
|             $this->error('Invalid access token.'); | ||||
|             $this->errorLine('Invalid access token.'); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|         /** @var UserRepositoryInterface $userRepository */ | ||||
|         $userRepository = app(UserRepositoryInterface::class); | ||||
|         $file           = $this->argument('file'); | ||||
|         $configuration  = $this->argument('configuration'); | ||||
|         $user           = $userRepository->find(intval($this->option('user'))); | ||||
|         $cwd            = getcwd(); | ||||
|         $type           = strtolower($this->option('type')); | ||||
|         $userRepository    = app(UserRepositoryInterface::class); | ||||
|         $file              = (string)$this->argument('file'); | ||||
|         $configuration     = (string)$this->argument('configuration'); | ||||
|         $user              = $userRepository->findNull((int)$this->option('user')); | ||||
|         $cwd               = getcwd(); | ||||
|         $provider          = strtolower((string)$this->option('provider')); | ||||
|         $configurationData = []; | ||||
|  | ||||
|         if (null === $user) { | ||||
|             $this->errorLine('User is NULL.'); | ||||
|  | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         if (!$this->validArguments()) { | ||||
|             return; | ||||
|             $this->errorLine('Invalid arguments.'); | ||||
|  | ||||
|             return 1; | ||||
|         } | ||||
|         if (\strlen($configuration) > 0) { | ||||
|             $configurationData = json_decode(file_get_contents($configuration), true); | ||||
|             if (null === $configurationData) { | ||||
|                 $this->errorLine(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd)); | ||||
|  | ||||
|                 return 1; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         $configurationData = json_decode(file_get_contents($configuration), true); | ||||
|         if (null === $configurationData) { | ||||
|             $this->error(sprintf('Firefly III cannot read the contents of configuration file "%s" (working directory: "%s").', $configuration, $cwd)); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         $this->line(sprintf('Going to create a job to import file: %s', $file)); | ||||
|         $this->line(sprintf('Using configuration file: %s', $configuration)); | ||||
|         $this->line(sprintf('Import into user: #%d (%s)', $user->id, $user->email)); | ||||
|         $this->line(sprintf('Type of import: %s', $type)); | ||||
|         $this->infoLine(sprintf('Going to create a job to import file: %s', $file)); | ||||
|         $this->infoLine(sprintf('Using configuration file: %s', $configuration)); | ||||
|         $this->infoLine(sprintf('Import into user: #%d (%s)', $user->id, $user->email)); | ||||
|         $this->infoLine(sprintf('Type of import: %s', $provider)); | ||||
|  | ||||
|         /** @var ImportJobRepositoryInterface $jobRepository */ | ||||
|         $jobRepository = app(ImportJobRepositoryInterface::class); | ||||
|         $jobRepository->setUser($user); | ||||
|         $job = $jobRepository->create($type); | ||||
|         $this->line(sprintf('Created job "%s"', $job->key)); | ||||
|         $importJob = $jobRepository->create($provider); | ||||
|         $this->infoLine(sprintf('Created job "%s"', $importJob->key)); | ||||
|  | ||||
|         Artisan::call('firefly:encrypt-file', ['file' => $file, 'key' => $job->key]); | ||||
|         $this->line('Stored import data...'); | ||||
|  | ||||
|         $jobRepository->setConfiguration($job, $configurationData); | ||||
|         $jobRepository->updateStatus($job, 'configured'); | ||||
|         $this->line('Stored configuration...'); | ||||
|  | ||||
|         if (true === $this->option('start')) { | ||||
|             $this->line('The import will start in a moment. This process is not visible...'); | ||||
|             Log::debug('Go for import!'); | ||||
|  | ||||
|             // normally would refer to other firefly:start-import but that doesn't seem to work all to well... | ||||
|             $monolog   = Log::getMonolog(); | ||||
|             $handler   = new CommandHandler($this); | ||||
|             $formatter = new LineFormatter(null, null, false, true); | ||||
|             $handler->setFormatter($formatter); | ||||
|             $monolog->pushHandler($handler); | ||||
|  | ||||
|             // start the actual routine: | ||||
|             $type      = 'csv' === $job->file_type ? 'file' : $job->file_type; | ||||
|             $key       = sprintf('import.routine.%s', $type); | ||||
|             $className = config($key); | ||||
|             if (null === $className || !class_exists($className)) { | ||||
|                 throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore | ||||
|         // make sure that job has no prerequisites. | ||||
|         if ((bool)config(sprintf('import.has_prereq.%s', $provider))) { | ||||
|             // make prerequisites thing. | ||||
|             $class = (string)config(sprintf('import.prerequisites.%s', $provider)); | ||||
|             if (!class_exists($class)) { | ||||
|                 throw new FireflyException(sprintf('No class to handle prerequisites for "%s".', $provider)); // @codeCoverageIgnore | ||||
|             } | ||||
|             /** @var RoutineInterface $routine */ | ||||
|             $routine = app($className); | ||||
|             $routine->setJob($job); | ||||
|             $routine->run(); | ||||
|             /** @var PrerequisitesInterface $object */ | ||||
|             $object = app($class); | ||||
|             $object->setUser($user); | ||||
|             if (!$object->isComplete()) { | ||||
|                 $this->errorLine(sprintf('Import provider "%s" has prerequisites that can only be filled in using the browser.', $provider)); | ||||
|  | ||||
|             // give feedback. | ||||
|             /** @var MessageBag $error */ | ||||
|             foreach ($routine->getErrors() as $index => $error) { | ||||
|                 $this->error(sprintf('Error importing line #%d: %s', $index, $error)); | ||||
|                 return 1; | ||||
|             } | ||||
|             $this->line( | ||||
|                 sprintf( | ||||
|                     'The import has finished. %d transactions have been imported out of %d records.', $routine->getJournals()->count(), $routine->getLines() | ||||
|                 ) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         // clear cache for user: | ||||
|         Preferences::setForUser($user, 'lastActivity', microtime()); | ||||
|         // store file as attachment. | ||||
|         if (\strlen($file) > 0) { | ||||
|             $messages = $jobRepository->storeCLIUpload($importJob, 'import_file', $file); | ||||
|             if ($messages->count() > 0) { | ||||
|                 $this->errorLine($messages->first()); | ||||
|  | ||||
|         return; | ||||
|                 return 1; | ||||
|             } | ||||
|             $this->infoLine('File content saved.'); | ||||
|         } | ||||
|  | ||||
|         $this->infoLine('Job configuration saved.'); | ||||
|         $jobRepository->setConfiguration($importJob, $configurationData); | ||||
|         $jobRepository->setStatus($importJob, 'ready_to_run'); | ||||
|  | ||||
|  | ||||
|         if (true === $this->option('start')) { | ||||
|             $this->infoLine('The import routine has started. The process is not visible. Please wait.'); | ||||
|             Log::debug('Go for import!'); | ||||
|  | ||||
|             // run it! | ||||
|             $key       = sprintf('import.routine.%s', $provider); | ||||
|             $className = config($key); | ||||
|             if (null === $className || !class_exists($className)) { | ||||
|                 // @codeCoverageIgnoreStart | ||||
|                 $this->errorLine(sprintf('No routine for provider "%s"', $provider)); | ||||
|  | ||||
|                 return 1; | ||||
|                 // @codeCoverageIgnoreEnd | ||||
|             } | ||||
|  | ||||
|             // keep repeating this call until job lands on "provider_finished" | ||||
|             $valid = ['provider_finished']; | ||||
|             $count = 0; | ||||
|             while (!\in_array($importJob->status, $valid, true) && $count < 6) { | ||||
|                 Log::debug(sprintf('Now in loop #%d.', $count + 1)); | ||||
|                 /** @var RoutineInterface $routine */ | ||||
|                 $routine = app($className); | ||||
|                 $routine->setImportJob($importJob); | ||||
|                 try { | ||||
|                     $routine->run(); | ||||
|                 } catch (FireflyException|Exception $e) { | ||||
|                     $message = 'The import routine crashed: ' . $e->getMessage(); | ||||
|                     Log::error($message); | ||||
|                     Log::error($e->getTraceAsString()); | ||||
|  | ||||
|                     // set job errored out: | ||||
|                     $jobRepository->setStatus($importJob, 'error'); | ||||
|                     $this->errorLine($message); | ||||
|  | ||||
|                     return 1; | ||||
|                 } | ||||
|                 $count++; | ||||
|             } | ||||
|             if ('provider_finished' === $importJob->status) { | ||||
|                 $this->infoLine('Import has finished. Please wait for storage of data.'); | ||||
|                 // set job to be storing data: | ||||
|                 $jobRepository->setStatus($importJob, 'storing_data'); | ||||
|  | ||||
|                 /** @var ImportArrayStorage $storage */ | ||||
|                 $storage = app(ImportArrayStorage::class); | ||||
|                 $storage->setImportJob($importJob); | ||||
|  | ||||
|                 try { | ||||
|                     $storage->store(); | ||||
|                 } catch (FireflyException|Exception $e) { | ||||
|                     $message = 'The import routine crashed: ' . $e->getMessage(); | ||||
|                     Log::error($message); | ||||
|                     Log::error($e->getTraceAsString()); | ||||
|  | ||||
|                     // set job errored out: | ||||
|                     $jobRepository->setStatus($importJob, 'error'); | ||||
|                     $this->errorLine($message); | ||||
|  | ||||
|                     return 1; | ||||
|                 } | ||||
|                 // set storage to be finished: | ||||
|                 $jobRepository->setStatus($importJob, 'storage_finished'); | ||||
|             } | ||||
|  | ||||
|             // give feedback: | ||||
|             $this->infoLine('Job has finished.'); | ||||
|             if (null !== $importJob->tag) { | ||||
|                 $this->infoLine(sprintf('%d transaction(s) have been imported.', $importJob->tag->transactionJournals->count())); | ||||
|                 $this->infoLine(sprintf('You can find your transactions under tag "%s"', $importJob->tag->tag)); | ||||
|             } | ||||
|  | ||||
|             if (null === $importJob->tag) { | ||||
|                 $this->errorLine('No transactions have been imported :(.'); | ||||
|             } | ||||
|             if (\count($importJob->errors) > 0) { | ||||
|                 $this->infoLine(sprintf('%d error(s) occurred:', \count($importJob->errors))); | ||||
|                 foreach ($importJob->errors as $err) { | ||||
|                     $this->errorLine('- ' . $err); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         // clear cache for user: | ||||
|         app('preferences')->setForUser($user, 'lastActivity', microtime()); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string     $message | ||||
|      * @param array|null $data | ||||
|      */ | ||||
|     private function errorLine(string $message, array $data = null): void | ||||
|     { | ||||
|         Log::error($message, $data ?? []); | ||||
|         $this->error($message); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param string $message | ||||
|      * @param array  $data | ||||
|      */ | ||||
|     private function infoLine(string $message, array $data = null): void | ||||
|     { | ||||
|         Log::info($message, $data ?? []); | ||||
|         $this->line($message); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Verify user inserts correct arguments. | ||||
|      * | ||||
|      * @noinspection MultipleReturnStatementsInspection | ||||
|      * @return bool | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly. | ||||
|      */ | ||||
|     private function validArguments(): bool | ||||
|     { | ||||
|         /** @var UserRepositoryInterface $userRepository */ | ||||
|         $userRepository = app(UserRepositoryInterface::class); | ||||
|         $file           = $this->argument('file'); | ||||
|         $configuration  = $this->argument('configuration'); | ||||
|         $user           = $userRepository->find(intval($this->option('user'))); | ||||
|         $cwd            = getcwd(); | ||||
|         $validTypes     = config('import.options.file.import_formats'); | ||||
|         $type           = strtolower($this->option('type')); | ||||
|         if (null === $user->id) { | ||||
|             $this->error(sprintf('There is no user with ID %d.', $this->option('user'))); | ||||
|         $file          = (string)$this->argument('file'); | ||||
|         $configuration = (string)$this->argument('configuration'); | ||||
|         $cwd           = getcwd(); | ||||
|         $validTypes    = config('import.options.file.import_formats'); | ||||
|         $type          = strtolower($this->option('type')); | ||||
|         $provider      = strtolower($this->option('provider')); | ||||
|         $enabled       = (bool)config(sprintf('import.enabled.%s', $provider)); | ||||
|  | ||||
|         if (false === $enabled) { | ||||
|             $this->errorLine(sprintf('Provider "%s" is not enabled.', $provider)); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (!in_array($type, $validTypes)) { | ||||
|             $this->error(sprintf('Cannot import file of type "%s"', $type)); | ||||
|         if ('file' === $provider && !\in_array($type, $validTypes, true)) { | ||||
|             $this->errorLine(sprintf('Cannot import file of type "%s"', $type)); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (!file_exists($file)) { | ||||
|             $this->error(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd)); | ||||
|         if ('file' === $provider && !file_exists($file)) { | ||||
|             $this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd)); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if (!file_exists($configuration)) { | ||||
|             $this->error(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd)); | ||||
|         if ('file' === $provider && !file_exists($configuration)) { | ||||
|             $this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd)); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|   | ||||
							
								
								
									
										67
									
								
								app/Console/Commands/Cron.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								app/Console/Commands/Cron.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| <?php | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
|  | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Support\Cronjobs\RecurringCronjob; | ||||
| use Illuminate\Console\Command; | ||||
|  | ||||
| /** | ||||
|  * Class Cron | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Cron extends Command | ||||
| { | ||||
|     /** | ||||
|      * The console command description. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $description = 'Runs all Firefly III cron-job related commands. Configure a cron job according to the official Firefly III documentation.'; | ||||
|     /** | ||||
|      * The name and signature of the console command. | ||||
|      * | ||||
|      * @var string | ||||
|      */ | ||||
|     protected $signature = 'firefly:cron'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
|     public function handle(): int | ||||
|     { | ||||
|         $recurring = new RecurringCronjob; | ||||
|         try { | ||||
|             $result = $recurring->fire(); | ||||
|         } catch (FireflyException $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|  | ||||
|             return 0; | ||||
|         } | ||||
|         if (false === $result) { | ||||
|             $this->line('The recurring transaction cron job did not fire.'); | ||||
|         } | ||||
|         if (true === $result) { | ||||
|             $this->line('The recurring transaction cron job fired successfully.'); | ||||
|         } | ||||
|  | ||||
|         $this->info('More feedback on the cron jobs can be found in the log files.'); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * DecryptAttachment.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,6 +18,9 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** @noinspection MultipleReturnStatementsInspection */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
| @@ -28,6 +31,8 @@ use Log; | ||||
|  | ||||
| /** | ||||
|  * Class DecryptAttachment. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class DecryptAttachment extends Command | ||||
| { | ||||
| @@ -47,54 +52,47 @@ class DecryptAttachment extends Command | ||||
|         = 'firefly:decrypt-attachment {id:The ID of the attachment.} {name:The file name of the attachment.}  | ||||
|     {directory:Where the file must be stored.}'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five its fine. | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * | ||||
|      * @return int | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         /** @var AttachmentRepositoryInterface $repository */ | ||||
|         $repository     = app(AttachmentRepositoryInterface::class); | ||||
|         $attachmentId   = intval($this->argument('id')); | ||||
|         $attachmentId   = (int)$this->argument('id'); | ||||
|         $attachment     = $repository->findWithoutUser($attachmentId); | ||||
|         $attachmentName = trim($this->argument('name')); | ||||
|         $storagePath    = realpath(trim($this->argument('directory'))); | ||||
|         if (null === $attachment->id) { | ||||
|         $attachmentName = trim((string)$this->argument('name')); | ||||
|         $storagePath    = realpath(trim((string)$this->argument('directory'))); | ||||
|         if (null === $attachment) { | ||||
|             $this->error(sprintf('No attachment with id #%d', $attachmentId)); | ||||
|             Log::error(sprintf('DecryptAttachment: No attachment with id #%d', $attachmentId)); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         if ($attachmentName !== $attachment->filename) { | ||||
|             $this->error('File name does not match.'); | ||||
|             Log::error('DecryptAttachment: File name does not match.'); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         if (!is_dir($storagePath)) { | ||||
|             $this->error(sprintf('Path "%s" is not a directory.', $storagePath)); | ||||
|             Log::error(sprintf('DecryptAttachment: Path "%s" is not a directory.', $storagePath)); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         if (!is_writable($storagePath)) { | ||||
|             $this->error(sprintf('Path "%s" is not writable.', $storagePath)); | ||||
|             Log::error(sprintf('DecryptAttachment: Path "%s" is not writable.', $storagePath)); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         $fullPath = $storagePath . DIRECTORY_SEPARATOR . $attachment->filename; | ||||
| @@ -104,10 +102,10 @@ class DecryptAttachment extends Command | ||||
|         if (false === $result) { | ||||
|             $this->error('Could not write to file.'); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|         $this->info(sprintf('%d bytes written. Exiting now..', $result)); | ||||
|  | ||||
|         return; | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * EncryptFile.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,15 +18,19 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
|  | ||||
| use Crypt; | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Services\Internal\File\EncryptService; | ||||
| use Illuminate\Console\Command; | ||||
|  | ||||
| /** | ||||
|  * Class EncryptFile. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class EncryptFile extends Command | ||||
| { | ||||
| @@ -44,31 +48,26 @@ class EncryptFile extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly:encrypt-file {file} {key}'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @throws \Illuminate\Contracts\Encryption\EncryptException | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         $file = e(strval($this->argument('file'))); | ||||
|         if (!file_exists($file)) { | ||||
|             $this->error(sprintf('File "%s" does not seem to exist.', $file)); | ||||
|         $code = 0; | ||||
|         $file = (string)$this->argument('file'); | ||||
|         $key  = (string)$this->argument('key'); | ||||
|         /** @var EncryptService $service */ | ||||
|         $service = app(EncryptService::class); | ||||
|  | ||||
|             return; | ||||
|         try { | ||||
|             $service->encrypt($file, $key); | ||||
|         } catch (FireflyException $e) { | ||||
|             $this->error($e->getMessage()); | ||||
|             $code = 1; | ||||
|         } | ||||
|         $content = file_get_contents($file); | ||||
|         $content = Crypt::encrypt($content); | ||||
|         $newName = e(strval($this->argument('key'))) . '.upload'; | ||||
|  | ||||
|         $path = storage_path('upload') . '/' . $newName; | ||||
|         file_put_contents($path, $content); | ||||
|         $this->line(sprintf('Encrypted "%s" and put it in "%s"', $file, $path)); | ||||
|         return $code; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Import.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,20 +18,25 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** @noinspection MultipleReturnStatementsInspection */ | ||||
| /** @noinspection PhpDynamicAsStaticMethodCallInspection */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
|  | ||||
| use FireflyIII\Exceptions\FireflyException; | ||||
| use FireflyIII\Import\Logging\CommandHandler; | ||||
| use FireflyIII\Import\Routine\RoutineInterface; | ||||
| use FireflyIII\Models\ImportJob; | ||||
| use FireflyIII\Models\Tag; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Support\MessageBag; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class Import. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Import extends Command | ||||
| { | ||||
| @@ -49,44 +54,35 @@ class Import extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly:start-import {key}'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Run the import routine. | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * | ||||
|      * @throws FireflyException | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         Log::debug('Start start-import command'); | ||||
|         $jobKey = $this->argument('key'); | ||||
|         $job    = ImportJob::where('key', $jobKey)->first(); | ||||
|         $jobKey = (string)$this->argument('key'); | ||||
|         /** @var ImportJob $job */ | ||||
|         $job = ImportJob::where('key', $jobKey)->first(); | ||||
|         if (null === $job) { | ||||
|             $this->error(sprintf('No job found with key "%s"', $jobKey)); | ||||
|             $this->errorLine(sprintf('No job found with key "%s"', $jobKey)); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|         if (!$this->isValid($job)) { | ||||
|             Log::error('Job is not valid for some reason. Exit.'); | ||||
|             $this->errorLine('Job is not valid for some reason. Exit.'); | ||||
|  | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         $this->line(sprintf('Going to import job with key "%s" of type "%s"', $job->key, $job->file_type)); | ||||
|  | ||||
|         $monolog = Log::getMonolog(); | ||||
|         $handler = new CommandHandler($this); | ||||
|         $monolog->pushHandler($handler); | ||||
|         $this->infoLine(sprintf('Going to import job with key "%s" of type "%s"', $job->key, $job->file_type)); | ||||
|  | ||||
|         // actually start job: | ||||
|         $type = 'csv' === $job->file_type ? 'file' : $job->file_type; | ||||
|         $key = sprintf('import.routine.%s', $type); | ||||
|         $type      = 'csv' === $job->file_type ? 'file' : $job->file_type; | ||||
|         $key       = sprintf('import.routine.%s', $type); | ||||
|         $className = config($key); | ||||
|         if (null === $className || !class_exists($className)) { | ||||
|             throw new FireflyException(sprintf('Cannot find import routine class for job of type "%s".', $type)); // @codeCoverageIgnore | ||||
| @@ -94,19 +90,52 @@ class Import extends Command | ||||
|  | ||||
|         /** @var RoutineInterface $routine */ | ||||
|         $routine = app($className); | ||||
|         $routine->setJob($job); | ||||
|         $routine->setImportJob($job); | ||||
|         $routine->run(); | ||||
|  | ||||
|         /** @var MessageBag $error */ | ||||
|         foreach ($routine->getErrors() as $index => $error) { | ||||
|             $this->error(sprintf('Error importing line #%d: %s', $index, $error)); | ||||
|         /** | ||||
|          * @var int    $index | ||||
|          * @var string $error | ||||
|          */ | ||||
|         foreach ($job->errors as $index => $error) { | ||||
|             $this->errorLine(sprintf('Error importing line #%d: %s', $index, $error)); | ||||
|         } | ||||
|  | ||||
|         $this->line( | ||||
|             sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->getJournals()->count(), $routine->getLines()) | ||||
|         ); | ||||
|         /** @var Tag $tag */ | ||||
|         $tag   = $job->tag()->first(); | ||||
|         $count = 0; | ||||
|         if (null === $tag) { | ||||
|             $count = $tag->transactionJournals()->count(); | ||||
|         } | ||||
|  | ||||
|         return; | ||||
|         $this->infoLine(sprintf('The import has finished. %d transactions have been imported.', $count)); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Displays an error. | ||||
|      * | ||||
|      * @param string     $message | ||||
|      * @param array|null $data | ||||
|      */ | ||||
|     private function errorLine(string $message, array $data = null): void | ||||
|     { | ||||
|         Log::error($message, $data ?? []); | ||||
|         $this->error($message); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Displays an informational message. | ||||
|      * | ||||
|      * @param string $message | ||||
|      * @param array  $data | ||||
|      */ | ||||
|     private function infoLine(string $message, array $data = null): void | ||||
|     { | ||||
|         Log::info($message, $data ?? []); | ||||
|         $this->line($message); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -119,15 +148,14 @@ class Import extends Command | ||||
|     private function isValid(ImportJob $job): bool | ||||
|     { | ||||
|         if (null === $job) { | ||||
|             Log::error('This job does not seem to exist.'); | ||||
|             $this->error('This job does not seem to exist.'); | ||||
|             $this->errorLine('This job does not seem to exist.'); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         if ('configured' !== $job->status) { | ||||
|             Log::error(sprintf('This job is not ready to be imported (status is %s).', $job->status)); | ||||
|             $this->error('This job is not ready to be imported.'); | ||||
|             $this->errorLine('This job is not ready to be imported.'); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * ScanAttachments.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,6 +18,9 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** @noinspection PhpDynamicAsStaticMethodCallInspection */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
| @@ -31,6 +34,8 @@ use Storage; | ||||
|  | ||||
| /** | ||||
|  * Class ScanAttachments. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class ScanAttachments extends Command | ||||
| { | ||||
| @@ -48,18 +53,10 @@ class ScanAttachments extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly:scan-attachments'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         $attachments = Attachment::get(); | ||||
|         $disk        = Storage::disk('upload'); | ||||
| @@ -69,13 +66,13 @@ class ScanAttachments extends Command | ||||
|             try { | ||||
|                 $content = $disk->get($fileName); | ||||
|             } catch (FileNotFoundException $e) { | ||||
|                 $this->error(sprintf('Could not find data for attachment #%d', $attachment->id)); | ||||
|                 $this->error(sprintf('Could not find data for attachment #%d: %s', $attachment->id, $e->getMessage())); | ||||
|                 continue; | ||||
|             } | ||||
|             try { | ||||
|                 $decrypted = Crypt::decrypt($content); | ||||
|             } catch (DecryptException $e) { | ||||
|                 $this->error(sprintf('Could not decrypt data of attachment #%d', $attachment->id)); | ||||
|                 $this->error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage())); | ||||
|                 continue; | ||||
|             } | ||||
|             $tmpfname = tempnam(sys_get_temp_dir(), 'FireflyIII'); | ||||
| @@ -87,5 +84,7 @@ class ScanAttachments extends Command | ||||
|             $attachment->save(); | ||||
|             $this->line(sprintf('Fixed attachment #%d', $attachment->id)); | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * UpgradeDatabase.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,35 +19,53 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** @noinspection MultipleReturnStatementsInspection */ | ||||
| /** @noinspection PhpStaticAsDynamicMethodCallInspection */ | ||||
| /** @noinspection PhpDynamicAsStaticMethodCallInspection */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
|  | ||||
| use DB; | ||||
| use Exception; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountMeta; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Attachment; | ||||
| use FireflyIII\Models\Bill; | ||||
| use FireflyIII\Models\BudgetLimit; | ||||
| use FireflyIII\Models\Note; | ||||
| use FireflyIII\Models\Preference; | ||||
| use FireflyIII\Models\Rule; | ||||
| use FireflyIII\Models\RuleAction; | ||||
| use FireflyIII\Models\RuleGroup; | ||||
| use FireflyIII\Models\RuleTrigger; | ||||
| use FireflyIII\Models\Transaction; | ||||
| use FireflyIII\Models\TransactionCurrency; | ||||
| use FireflyIII\Models\TransactionJournal; | ||||
| use FireflyIII\Models\TransactionJournalMeta; | ||||
| use FireflyIII\Models\TransactionType; | ||||
| use FireflyIII\Repositories\Account\AccountRepositoryInterface; | ||||
| use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; | ||||
| use FireflyIII\Repositories\Journal\JournalRepositoryInterface; | ||||
| use FireflyIII\User; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Database\QueryException; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
| use Preferences; | ||||
| use Schema; | ||||
| use UnexpectedValueException; | ||||
|  | ||||
| /** | ||||
|  * Class UpgradeDatabase. | ||||
|  * | ||||
|  * Upgrade user database. | ||||
|  * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  * | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) // it just touches a lot of things. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class UpgradeDatabase extends Command | ||||
| { | ||||
| @@ -63,20 +82,10 @@ class UpgradeDatabase extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly:upgrade-database'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      * | ||||
|      * @throws \Exception | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         $this->setTransactionIdentifier(); | ||||
|         $this->updateAccountCurrencies(); | ||||
| @@ -86,9 +95,161 @@ class UpgradeDatabase extends Command | ||||
|         $this->updateOtherCurrencies(); | ||||
|         $this->line('Done updating currency information..'); | ||||
|         $this->migrateNotes(); | ||||
|         $this->migrateAttachmentData(); | ||||
|         $this->migrateBillsToRules(); | ||||
|         $this->budgetLimitCurrency(); | ||||
|         $this->removeCCLiabilities(); | ||||
|  | ||||
|         $this->info('Firefly III database is up to date.'); | ||||
|  | ||||
|         return; | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Since it is one routine these warnings make sense and should be supressed. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      */ | ||||
|     public function migrateBillsToRules(): void | ||||
|     { | ||||
|         foreach (User::get() as $user) { | ||||
|             /** @var Preference $lang */ | ||||
|             $lang               = app('preferences')->getForUser($user, 'language', 'en_US'); | ||||
|             $groupName          = (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data); | ||||
|             $ruleGroup          = $user->ruleGroups()->where('title', $groupName)->first(); | ||||
|             $currencyPreference = app('preferences')->getForUser($user, 'currencyPreference', config('firefly.default_currency', 'EUR')); | ||||
|  | ||||
|             if (null === $currencyPreference) { | ||||
|                 $this->error('User has no currency preference. Impossible.'); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             $currency = TransactionCurrency::where('code', $currencyPreference->data)->first(); | ||||
|             if (null === $currency) { | ||||
|                 $this->line('Fall back to default currency in migrateBillsToRules().'); | ||||
|                 $currency = app('amount')->getDefaultCurrency(); | ||||
|             } | ||||
|  | ||||
|             if (null === $ruleGroup) { | ||||
|                 $array     = RuleGroup::get(['order'])->pluck('order')->toArray(); | ||||
|                 $order     = \count($array) > 0 ? max($array) + 1 : 1; | ||||
|                 $ruleGroup = RuleGroup::create( | ||||
|                     [ | ||||
|                         'user_id'     => $user->id, | ||||
|                         'title'       => (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data), | ||||
|                         'description' => (string)trans('firefly.rulegroup_for_bills_description', [], $lang->data), | ||||
|                         'order'       => $order, | ||||
|                         'active'      => 1, | ||||
|                     ] | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             // loop bills. | ||||
|             $order = 1; | ||||
|             /** @var Collection $collection */ | ||||
|             $collection = $user->bills()->get(); | ||||
|             /** @var Bill $bill */ | ||||
|             foreach ($collection as $bill) { | ||||
|                 if ('MIGRATED_TO_RULES' !== $bill->match) { | ||||
|                     $rule = Rule::create( | ||||
|                         [ | ||||
|                             'user_id'         => $user->id, | ||||
|                             'rule_group_id'   => $ruleGroup->id, | ||||
|                             'title'           => (string)trans('firefly.rule_for_bill_title', ['name' => $bill->name], $lang->data), | ||||
|                             'description'     => (string)trans('firefly.rule_for_bill_description', ['name' => $bill->name], $lang->data), | ||||
|                             'order'           => $order, | ||||
|                             'active'          => $bill->active, | ||||
|                             'stop_processing' => 1, | ||||
|                         ] | ||||
|                     ); | ||||
|                     // add default trigger | ||||
|                     RuleTrigger::create( | ||||
|                         [ | ||||
|                             'rule_id'         => $rule->id, | ||||
|                             'trigger_type'    => 'user_action', | ||||
|                             'trigger_value'   => 'store-journal', | ||||
|                             'active'          => 1, | ||||
|                             'stop_processing' => 0, | ||||
|                             'order'           => 1, | ||||
|                         ] | ||||
|                     ); | ||||
|                     // add trigger for description | ||||
|                     $match = implode(' ', explode(',', $bill->match)); | ||||
|                     RuleTrigger::create( | ||||
|                         [ | ||||
|                             'rule_id'         => $rule->id, | ||||
|                             'trigger_type'    => 'description_contains', | ||||
|                             'trigger_value'   => $match, | ||||
|                             'active'          => 1, | ||||
|                             'stop_processing' => 0, | ||||
|                             'order'           => 2, | ||||
|                         ] | ||||
|                     ); | ||||
|                     if ($bill->amount_max !== $bill->amount_min) { | ||||
|                         // add triggers for amounts: | ||||
|                         RuleTrigger::create( | ||||
|                             [ | ||||
|                                 'rule_id'         => $rule->id, | ||||
|                                 'trigger_type'    => 'amount_less', | ||||
|                                 'trigger_value'   => round($bill->amount_max, $currency->decimal_places), | ||||
|                                 'active'          => 1, | ||||
|                                 'stop_processing' => 0, | ||||
|                                 'order'           => 3, | ||||
|                             ] | ||||
|                         ); | ||||
|                         RuleTrigger::create( | ||||
|                             [ | ||||
|                                 'rule_id'         => $rule->id, | ||||
|                                 'trigger_type'    => 'amount_more', | ||||
|                                 'trigger_value'   => round((float)$bill->amount_min, $currency->decimal_places), | ||||
|                                 'active'          => 1, | ||||
|                                 'stop_processing' => 0, | ||||
|                                 'order'           => 4, | ||||
|                             ] | ||||
|                         ); | ||||
|                     } | ||||
|                     if ($bill->amount_max === $bill->amount_min) { | ||||
|                         RuleTrigger::create( | ||||
|                             [ | ||||
|                                 'rule_id'         => $rule->id, | ||||
|                                 'trigger_type'    => 'amount_exactly', | ||||
|                                 'trigger_value'   => round((float)$bill->amount_min, $currency->decimal_places), | ||||
|                                 'active'          => 1, | ||||
|                                 'stop_processing' => 0, | ||||
|                                 'order'           => 3, | ||||
|                             ] | ||||
|                         ); | ||||
|                     } | ||||
|  | ||||
|                     // create action | ||||
|                     RuleAction::create( | ||||
|                         [ | ||||
|                             'rule_id'         => $rule->id, | ||||
|                             'action_type'     => 'link_to_bill', | ||||
|                             'action_value'    => $bill->name, | ||||
|                             'order'           => 1, | ||||
|                             'active'          => 1, | ||||
|                             'stop_processing' => 0, | ||||
|                         ] | ||||
|                     ); | ||||
|  | ||||
|                     $order++; | ||||
|                     $bill->match = 'MIGRATED_TO_RULES'; | ||||
|                     $bill->save(); | ||||
|                     $this->line(sprintf('Updated bill #%d ("%s") so it will use rules.', $bill->id, $bill->name)); | ||||
|                 } | ||||
|  | ||||
|                 // give bills a currency when they dont have one. | ||||
|                 if (null === $bill->transaction_currency_id) { | ||||
|                     $this->line(sprintf('Gave bill #%d ("%s") a currency (%s).', $bill->id, $bill->name, $currency->name)); | ||||
|                     $bill->transactionCurrency()->associate($currency); | ||||
|                     $bill->save(); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -118,31 +279,36 @@ class UpgradeDatabase extends Command | ||||
|         $journalIds = array_unique($result->pluck('id')->toArray()); | ||||
|  | ||||
|         foreach ($journalIds as $journalId) { | ||||
|             $this->updateJournalidentifiers(intval($journalId)); | ||||
|             $this->updateJournalidentifiers((int)$journalId); | ||||
|         } | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Each (asset) account must have a reference to a preferred currency. If the account does not have one, it's forced upon the account. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's seven but it can't really be helped. | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     public function updateAccountCurrencies(): void | ||||
|     { | ||||
|         $accounts = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') | ||||
|                            ->whereIn('account_types.type', [AccountType::DEFAULT, AccountType::ASSET])->get(['accounts.*']); | ||||
|  | ||||
|         /** @var AccountRepositoryInterface $repository */ | ||||
|         $repository = app(AccountRepositoryInterface::class); | ||||
|         $accounts->each( | ||||
|             function (Account $account) { | ||||
|             function (Account $account) use ($repository) { | ||||
|                 $repository->setUser($account->user); | ||||
|                 // get users preference, fall back to system pref. | ||||
|                 $defaultCurrencyCode = Preferences::getForUser($account->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data; | ||||
|                 $defaultCurrencyCode = app('preferences')->getForUser($account->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data; | ||||
|                 $defaultCurrency     = TransactionCurrency::where('code', $defaultCurrencyCode)->first(); | ||||
|                 $accountCurrency     = intval($account->getMeta('currency_id')); | ||||
|                 $accountCurrency     = (int)$repository->getMetaValue($account, 'currency_id'); | ||||
|                 $openingBalance      = $account->getOpeningBalance(); | ||||
|                 $obCurrency          = intval($openingBalance->transaction_currency_id); | ||||
|                 $obCurrency          = (int)$openingBalance->transaction_currency_id; | ||||
|  | ||||
|                 if (null === $defaultCurrency) { | ||||
|                     throw new UnexpectedValueException('The default currency is NULL, and this is more or less impossible.'); | ||||
|                 } | ||||
|  | ||||
|                 // both 0? set to default currency: | ||||
|                 if (0 === $accountCurrency && 0 === $obCurrency) { | ||||
| @@ -175,7 +341,6 @@ class UpgradeDatabase extends Command | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -185,19 +350,22 @@ class UpgradeDatabase extends Command | ||||
|      * Both source and destination must match the respective currency preference of the related asset account. | ||||
|      * So FF3 must verify all transactions. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     public function updateOtherCurrencies(): void | ||||
|     { | ||||
|         /** @var CurrencyRepositoryInterface $repository */ | ||||
|         $repository = app(CurrencyRepositoryInterface::class); | ||||
|         $set        = TransactionJournal | ||||
|         /** @var AccountRepositoryInterface $accountRepos */ | ||||
|         $accountRepos = app(AccountRepositoryInterface::class); | ||||
|         $set          = TransactionJournal | ||||
|             ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|             ->whereIn('transaction_types.type', [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE]) | ||||
|             ->get(['transaction_journals.*']); | ||||
|  | ||||
|         $set->each( | ||||
|             function (TransactionJournal $journal) use ($repository) { | ||||
|             function (TransactionJournal $journal) use ($repository, $accountRepos) { | ||||
|                 // get the transaction with the asset account in it: | ||||
|                 /** @var Transaction $transaction */ | ||||
|                 $transaction = $journal->transactions() | ||||
| @@ -207,9 +375,13 @@ class UpgradeDatabase extends Command | ||||
|                 if (null === $transaction) { | ||||
|                     return; | ||||
|                 } | ||||
|                 $accountRepos->setUser($journal->user); | ||||
|                 /** @var Account $account */ | ||||
|                 $account      = $transaction->account; | ||||
|                 $currency     = $repository->find(intval($account->getMeta('currency_id'))); | ||||
|                 $account  = $transaction->account; | ||||
|                 $currency = $repository->findNull((int)$accountRepos->getMetaValue($account, 'currency_id')); | ||||
|                 if (null === $currency) { | ||||
|                     return; | ||||
|                 } | ||||
|                 $transactions = $journal->transactions()->get(); | ||||
|                 $transactions->each( | ||||
|                     function (Transaction $transaction) use ($currency) { | ||||
| @@ -219,8 +391,8 @@ class UpgradeDatabase extends Command | ||||
|                         } | ||||
|  | ||||
|                         // when mismatch in transaction: | ||||
|                         if (!(intval($transaction->transaction_currency_id) === intval($currency->id))) { | ||||
|                             $transaction->foreign_currency_id     = $transaction->transaction_currency_id; | ||||
|                         if (!((int)$transaction->transaction_currency_id === (int)$currency->id)) { | ||||
|                             $transaction->foreign_currency_id     = (int)$transaction->transaction_currency_id; | ||||
|                             $transaction->foreign_amount          = $transaction->amount; | ||||
|                             $transaction->transaction_currency_id = $currency->id; | ||||
|                             $transaction->save(); | ||||
| @@ -233,7 +405,6 @@ class UpgradeDatabase extends Command | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -246,7 +417,7 @@ class UpgradeDatabase extends Command | ||||
|      * Both source and destination must match the respective currency preference. So FF3 must verify ALL | ||||
|      * transactions. | ||||
|      */ | ||||
|     public function updateTransferCurrencies() | ||||
|     public function updateTransferCurrencies(): void | ||||
|     { | ||||
|         $set = TransactionJournal | ||||
|             ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
| @@ -268,26 +439,82 @@ class UpgradeDatabase extends Command | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     private function budgetLimitCurrency(): void | ||||
|     { | ||||
|         $budgetLimits = BudgetLimit::get(); | ||||
|         /** @var BudgetLimit $budgetLimit */ | ||||
|         foreach ($budgetLimits as $budgetLimit) { | ||||
|             if (null === $budgetLimit->transaction_currency_id) { | ||||
|                 $budget = $budgetLimit->budget; | ||||
|                 if (null !== $budget) { | ||||
|                     $user = $budget->user; | ||||
|                     if (null !== $user) { | ||||
|                         $currency                             = \Amount::getDefaultCurrencyByUser($user); | ||||
|                         $budgetLimit->transaction_currency_id = $currency->id; | ||||
|                         $budgetLimit->save(); | ||||
|                         $this->line( | ||||
|                             sprintf('Budget limit #%d (part of budget "%s") now has a currency setting (%s).', $budgetLimit->id, $budget->name, $currency->name) | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private function createNewTypes(): void | ||||
|     { | ||||
|         // create transaction type "Reconciliation". | ||||
|         $type = TransactionType::where('type', TransactionType::RECONCILIATION)->first(); | ||||
|         if (is_null($type)) { | ||||
|         if (null === $type) { | ||||
|             TransactionType::create(['type' => TransactionType::RECONCILIATION]); | ||||
|         } | ||||
|         $account = AccountType::where('type', AccountType::RECONCILIATION)->first(); | ||||
|         if (is_null($account)) { | ||||
|         if (null === $account) { | ||||
|             AccountType::create(['type' => AccountType::RECONCILIATION]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Move the description of each attachment (when not NULL) to the notes or to a new note object | ||||
|      * for all attachments. | ||||
|      */ | ||||
|     private function migrateAttachmentData(): void | ||||
|     { | ||||
|         $attachments = Attachment::get(); | ||||
|  | ||||
|         /** @var Attachment $att */ | ||||
|         foreach ($attachments as $att) { | ||||
|  | ||||
|             // move description: | ||||
|             $description = (string)$att->description; | ||||
|             if (\strlen($description) > 0) { | ||||
|                 // find or create note: | ||||
|                 $note = $att->notes()->first(); | ||||
|                 if (null === $note) { | ||||
|                     $note = new Note; | ||||
|                     $note->noteable()->associate($att); | ||||
|                 } | ||||
|                 $note->text = $description; | ||||
|                 $note->save(); | ||||
|  | ||||
|                 // clear description: | ||||
|                 $att->description = ''; | ||||
|                 $att->save(); | ||||
|  | ||||
|                 Log::debug(sprintf('Migrated attachment #%s description to note #%d', $att->id, $note->id)); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Move all the journal_meta notes to their note object counter parts. | ||||
|      * | ||||
|      * @throws \Exception | ||||
|      */ | ||||
|     private function migrateNotes(): void | ||||
|     { | ||||
|         /** @noinspection PhpUndefinedMethodInspection */ | ||||
|         $set = TransactionJournalMeta::whereName('notes')->get(); | ||||
|         /** @var TransactionJournalMeta $meta */ | ||||
|         foreach ($set as $meta) { | ||||
| @@ -301,7 +528,33 @@ class UpgradeDatabase extends Command | ||||
|             $note->text = $meta->data; | ||||
|             $note->save(); | ||||
|             Log::debug(sprintf('Migrated meta note #%d to Note #%d', $meta->id, $note->id)); | ||||
|             $meta->delete(); | ||||
|             try { | ||||
|                 $meta->delete(); | ||||
|             } catch (Exception $e) { | ||||
|                 Log::error(sprintf('Could not delete old meta entry #%d: %s', $meta->id, $e->getMessage())); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * | ||||
|      */ | ||||
|     private function removeCCLiabilities(): void | ||||
|     { | ||||
|         $ccType = AccountType::where('type', AccountType::CREDITCARD)->first(); | ||||
|         $debtType =AccountType::where('type', AccountType::DEBT)->first(); | ||||
|         if(null === $ccType || null === $debtType) { | ||||
|             return; | ||||
|         } | ||||
|         /** @var Collection $accounts */ | ||||
|         $accounts = Account::where('account_type_id', $ccType->id)->get(); | ||||
|         foreach($accounts as $account) { | ||||
|             $account->account_type_id = $debtType->id; | ||||
|             $account->save(); | ||||
|             $this->line(sprintf('Converted credit card liability account "%s" (#%d) to generic debt liability.', $account->name, $account->id)); | ||||
|         } | ||||
|         if($accounts->count() > 0) { | ||||
|             $this->info('Credit card liability types are no longer supported and have been converted to generic debts. See: http://bit.ly/FF3-credit-cards'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -314,10 +567,17 @@ class UpgradeDatabase extends Command | ||||
|     { | ||||
|         /** @var CurrencyRepositoryInterface $repository */ | ||||
|         $repository = app(CurrencyRepositoryInterface::class); | ||||
|         $currency   = $repository->find(intval($transaction->account->getMeta('currency_id'))); | ||||
|         $journal    = $transaction->transactionJournal; | ||||
|         /** @var AccountRepositoryInterface $accountRepos */ | ||||
|         $accountRepos = app(AccountRepositoryInterface::class); | ||||
|         $accountRepos->setUser($transaction->account->user); | ||||
|         $currency = $repository->findNull((int)$accountRepos->getMetaValue($transaction->account, 'currency_id')); | ||||
|         $journal  = $transaction->transactionJournal; | ||||
|  | ||||
|         if (!(intval($currency->id) === intval($journal->transaction_currency_id))) { | ||||
|         if (null === $currency) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         if (!((int)$currency->id === (int)$journal->transaction_currency_id)) { | ||||
|             $this->line( | ||||
|                 sprintf( | ||||
|                     'Transfer #%d ("%s") has been updated to use %s instead of %s.', | ||||
| @@ -331,7 +591,6 @@ class UpgradeDatabase extends Command | ||||
|             $journal->save(); | ||||
|         } | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -348,7 +607,7 @@ class UpgradeDatabase extends Command | ||||
|         /** @var Transaction $transaction */ | ||||
|         foreach ($transactions as $transaction) { | ||||
|             // find opposing: | ||||
|             $amount = bcmul(strval($transaction->amount), '-1'); | ||||
|             $amount = bcmul((string)$transaction->amount, '-1'); | ||||
|  | ||||
|             try { | ||||
|                 /** @var Transaction $opposing */ | ||||
| @@ -377,7 +636,6 @@ class UpgradeDatabase extends Command | ||||
|             ++$identifier; | ||||
|         } | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -386,11 +644,11 @@ class UpgradeDatabase extends Command | ||||
|      * | ||||
|      * The transaction that is sent to this function MUST be the source transaction (amount negative). | ||||
|      * | ||||
|      * Method is long and complex bit I'm taking it for granted. | ||||
|      * Method is long and complex but I'll allow it. https://imgur.com/gallery/dVDJiez | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      * @SuppressWarnings(PHPMD.NPathComplexity) | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * | ||||
|      * @param Transaction $transaction | ||||
|      */ | ||||
| @@ -398,30 +656,41 @@ class UpgradeDatabase extends Command | ||||
|     { | ||||
|         /** @var CurrencyRepositoryInterface $repository */ | ||||
|         $repository = app(CurrencyRepositoryInterface::class); | ||||
|         $currency   = $repository->find(intval($transaction->account->getMeta('currency_id'))); | ||||
|         /** @var AccountRepositoryInterface $accountRepos */ | ||||
|         $accountRepos = app(AccountRepositoryInterface::class); | ||||
|         /** @var JournalRepositoryInterface $journalRepos */ | ||||
|         $journalRepos = app(JournalRepositoryInterface::class); | ||||
|  | ||||
|         $accountRepos->setUser($transaction->account->user); | ||||
|         $journalRepos->setUser($transaction->account->user); | ||||
|         $currency = $repository->findNull((int)$accountRepos->getMetaValue($transaction->account, 'currency_id')); | ||||
|  | ||||
|         if (null === $currency) { | ||||
|             Log::error(sprintf('Account #%d ("%s") must have currency preference but has none.', $transaction->account->id, $transaction->account->name)); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // has no currency ID? Must have, so fill in using account preference: | ||||
|         if (null === $transaction->transaction_currency_id) { | ||||
|             $transaction->transaction_currency_id = intval($currency->id); | ||||
|             $transaction->transaction_currency_id = (int)$currency->id; | ||||
|             Log::debug(sprintf('Transaction #%d has no currency setting, now set to %s', $transaction->id, $currency->code)); | ||||
|             $transaction->save(); | ||||
|         } | ||||
|  | ||||
|         // does not match the source account (see above)? Can be fixed | ||||
|         // when mismatch in transaction and NO foreign amount is set: | ||||
|         if (!(intval($transaction->transaction_currency_id) === intval($currency->id)) && null === $transaction->foreign_amount) { | ||||
|         if (!((int)$transaction->transaction_currency_id === (int)$currency->id) && null === $transaction->foreign_amount) { | ||||
|             Log::debug( | ||||
|                 sprintf( | ||||
|                     'Transaction #%d has a currency setting (#%d) (%s) that should be #%d (%s). Amount remains %s, currency is changed.', | ||||
|                     'Transaction #%d has a currency setting #%d that should be #%d. Amount remains %s, currency is changed.', | ||||
|                     $transaction->id, | ||||
|                     $transaction->transaction_currency_id, | ||||
|                     $this->var_dump_ret(intval($transaction->transaction_currency_id)), | ||||
|                     $currency->id, | ||||
|                     $this->var_dump_ret(intval($currency->id)), | ||||
|                     $transaction->amount | ||||
|                 ) | ||||
|             ); | ||||
|             $transaction->transaction_currency_id = intval($currency->id); | ||||
|             $transaction->transaction_currency_id = (int)$currency->id; | ||||
|             $transaction->save(); | ||||
|         } | ||||
|  | ||||
| @@ -430,16 +699,16 @@ class UpgradeDatabase extends Command | ||||
|         $journal = $transaction->transactionJournal; | ||||
|         /** @var Transaction $opposing */ | ||||
|         $opposing         = $journal->transactions()->where('amount', '>', 0)->where('identifier', $transaction->identifier)->first(); | ||||
|         $opposingCurrency = $repository->find(intval($opposing->account->getMeta('currency_id'))); | ||||
|         $opposingCurrency = $repository->findNull((int)$accountRepos->getMetaValue($opposing->account, 'currency_id')); | ||||
|  | ||||
|         if (null === $opposingCurrency->id) { | ||||
|         if (null === $opposingCurrency) { | ||||
|             Log::error(sprintf('Account #%d ("%s") must have currency preference but has none.', $opposing->account->id, $opposing->account->name)); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // if the destination account currency is the same, both foreign_amount and foreign_currency_id must be NULL for both transactions: | ||||
|         if (intval($opposingCurrency->id) === intval($currency->id)) { | ||||
|         if ((int)$opposingCurrency->id === (int)$currency->id) { | ||||
|             // update both transactions to match: | ||||
|             $transaction->foreign_amount       = null; | ||||
|             $transaction->foreign_currency_id  = null; | ||||
| @@ -448,12 +717,21 @@ class UpgradeDatabase extends Command | ||||
|             $opposing->transaction_currency_id = $currency->id; | ||||
|             $transaction->save(); | ||||
|             $opposing->save(); | ||||
|             Log::debug(sprintf('Cleaned up transaction #%d and #%d', $transaction->id, $opposing->id)); | ||||
|             Log::debug( | ||||
|                 sprintf( | ||||
|                     'Currency for account "%s" is %s, and currency for account "%s" is also | ||||
|              %s, so %s #%d (#%d and #%d) has been verified to be to %s exclusively.', | ||||
|                     $opposing->account->name, $opposingCurrency->code, | ||||
|                     $transaction->account->name, $transaction->transactionCurrency->code, | ||||
|                     $journal->transactionType->type, $journal->id, | ||||
|                     $transaction->id, $opposing->id, $currency->code | ||||
|                 ) | ||||
|             ); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|         // if destination account currency is different, both transactions must have this currency as foreign currency id. | ||||
|         if (!(intval($opposingCurrency->id) === intval($currency->id))) { | ||||
|         if (!((int)$opposingCurrency->id === (int)$currency->id)) { | ||||
|             $transaction->foreign_currency_id = $opposingCurrency->id; | ||||
|             $opposing->foreign_currency_id    = $opposingCurrency->id; | ||||
|             $transaction->save(); | ||||
| @@ -463,31 +741,31 @@ class UpgradeDatabase extends Command | ||||
|  | ||||
|         // if foreign amount of one is null and the other is not, use this to restore: | ||||
|         if (null === $transaction->foreign_amount && null !== $opposing->foreign_amount) { | ||||
|             $transaction->foreign_amount = bcmul(strval($opposing->foreign_amount), '-1'); | ||||
|             $transaction->foreign_amount = bcmul((string)$opposing->foreign_amount, '-1'); | ||||
|             $transaction->save(); | ||||
|             Log::debug(sprintf('Restored foreign amount of transaction (1) #%d to %s', $transaction->id, $transaction->foreign_amount)); | ||||
|         } | ||||
|  | ||||
|         // if foreign amount of one is null and the other is not, use this to restore (other way around) | ||||
|         if (null === $opposing->foreign_amount && null !== $transaction->foreign_amount) { | ||||
|             $opposing->foreign_amount = bcmul(strval($transaction->foreign_amount), '-1'); | ||||
|             $opposing->foreign_amount = bcmul((string)$transaction->foreign_amount, '-1'); | ||||
|             $opposing->save(); | ||||
|             Log::debug(sprintf('Restored foreign amount of transaction (2) #%d to %s', $opposing->id, $opposing->foreign_amount)); | ||||
|         } | ||||
|  | ||||
|         // when both are zero, try to grab it from journal: | ||||
|         if (null === $opposing->foreign_amount && null === $transaction->foreign_amount) { | ||||
|             $foreignAmount = $journal->getMeta('foreign_amount'); | ||||
|             $foreignAmount = $journalRepos->getMetaField($journal, 'foreign_amount'); | ||||
|             if (null === $foreignAmount) { | ||||
|                 Log::debug(sprintf('Journal #%d has missing foreign currency data, forced to do 1:1 conversion :(.', $transaction->transaction_journal_id)); | ||||
|                 $transaction->foreign_amount = bcmul(strval($transaction->amount), '-1'); | ||||
|                 $opposing->foreign_amount    = bcmul(strval($opposing->amount), '-1'); | ||||
|                 $transaction->foreign_amount = bcmul((string)$transaction->amount, '-1'); | ||||
|                 $opposing->foreign_amount    = bcmul((string)$opposing->amount, '-1'); | ||||
|                 $transaction->save(); | ||||
|                 $opposing->save(); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|             $foreignPositive = app('steam')->positive(strval($foreignAmount)); | ||||
|             $foreignPositive = app('steam')->positive((string)$foreignAmount); | ||||
|             Log::debug( | ||||
|                 sprintf( | ||||
|                     'Journal #%d has missing foreign currency info, try to restore from meta-data ("%s").', | ||||
| @@ -501,22 +779,6 @@ class UpgradeDatabase extends Command | ||||
|             $opposing->save(); | ||||
|         } | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @param null $mixed | ||||
|      * | ||||
|      * @return string | ||||
|      */ | ||||
|     private function var_dump_ret($mixed = null): string | ||||
|     { | ||||
|         ob_start(); | ||||
|         var_dump($mixed); | ||||
|         $content = ob_get_contents(); | ||||
|         ob_end_clean(); | ||||
|  | ||||
|         return trim($content); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * UpgradeFireflyInstructions.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,6 +18,7 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
| @@ -26,6 +27,8 @@ use Illuminate\Console\Command; | ||||
|  | ||||
| /** | ||||
|  * Class UpgradeFireflyInstructions. | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class UpgradeFireflyInstructions extends Command | ||||
| { | ||||
| @@ -42,25 +45,19 @@ class UpgradeFireflyInstructions extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly:instructions {task}'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         if ('update' === $this->argument('task')) { | ||||
|         if ('update' === (string)$this->argument('task')) { | ||||
|             $this->updateInstructions(); | ||||
|         } | ||||
|         if ('install' === $this->argument('task')) { | ||||
|         if ('install' === (string)$this->argument('task')) { | ||||
|             $this->installInstructions(); | ||||
|         } | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -68,7 +65,7 @@ class UpgradeFireflyInstructions extends Command | ||||
|      * | ||||
|      * @param string $text | ||||
|      */ | ||||
|     private function boxed(string $text) | ||||
|     private function boxed(string $text): void | ||||
|     { | ||||
|         $parts = explode("\n", wordwrap($text)); | ||||
|         foreach ($parts as $string) { | ||||
| @@ -81,7 +78,7 @@ class UpgradeFireflyInstructions extends Command | ||||
|      * | ||||
|      * @param string $text | ||||
|      */ | ||||
|     private function boxedInfo(string $text) | ||||
|     private function boxedInfo(string $text): void | ||||
|     { | ||||
|         $parts = explode("\n", wordwrap($text)); | ||||
|         foreach ($parts as $string) { | ||||
| @@ -92,7 +89,7 @@ class UpgradeFireflyInstructions extends Command | ||||
|     /** | ||||
|      * Render instructions. | ||||
|      */ | ||||
|     private function installInstructions() | ||||
|     private function installInstructions(): void | ||||
|     { | ||||
|         /** @var string $version */ | ||||
|         $version = config('firefly.version'); | ||||
| @@ -100,8 +97,7 @@ class UpgradeFireflyInstructions extends Command | ||||
|         $text    = ''; | ||||
|         foreach (array_keys($config) as $compare) { | ||||
|             // if string starts with: | ||||
|             $len = strlen($compare); | ||||
|             if (substr($version, 0, $len) === $compare) { | ||||
|             if (0 === strpos($version, $compare)) { | ||||
|                 $text = $config[$compare]; | ||||
|             } | ||||
|         } | ||||
| @@ -126,7 +122,7 @@ class UpgradeFireflyInstructions extends Command | ||||
|     /** | ||||
|      * Show a line. | ||||
|      */ | ||||
|     private function showLine() | ||||
|     private function showLine(): void | ||||
|     { | ||||
|         $line = '+'; | ||||
|         for ($i = 0; $i < 78; ++$i) { | ||||
| @@ -139,7 +135,7 @@ class UpgradeFireflyInstructions extends Command | ||||
|     /** | ||||
|      * Render upgrade instructions. | ||||
|      */ | ||||
|     private function updateInstructions() | ||||
|     private function updateInstructions(): void | ||||
|     { | ||||
|         /** @var string $version */ | ||||
|         $version = config('firefly.version'); | ||||
| @@ -147,8 +143,7 @@ class UpgradeFireflyInstructions extends Command | ||||
|         $text    = ''; | ||||
|         foreach (array_keys($config) as $compare) { | ||||
|             // if string starts with: | ||||
|             $len = strlen($compare); | ||||
|             if (substr($version, 0, $len) === $compare) { | ||||
|             if (0 === strpos($version, $compare)) { | ||||
|                 $text = $config[$compare]; | ||||
|             } | ||||
|         } | ||||
|   | ||||
| @@ -1,8 +1,7 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * UseEncryption.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -19,6 +18,7 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
| @@ -28,6 +28,7 @@ use Illuminate\Support\Str; | ||||
|  | ||||
| /** | ||||
|  * Class UseEncryption. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class UseEncryption extends Command | ||||
| { | ||||
| @@ -44,23 +45,15 @@ class UseEncryption extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly:use-encryption'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         if (config('firefly.encryption') === true) { | ||||
|         if (true === config('firefly.encryption')) { | ||||
|             $this->info('Firefly III configuration calls for encrypted data.'); | ||||
|         } | ||||
|         if (config('firefly.encryption') === false) { | ||||
|         if (false === config('firefly.encryption')) { | ||||
|             $this->info('Firefly III configuration calls for unencrypted data.'); | ||||
|         } | ||||
|         $this->handleObjects('Account', 'name', 'encrypted'); | ||||
| @@ -70,6 +63,8 @@ class UseEncryption extends Command | ||||
|         $this->handleObjects('Category', 'name', 'encrypted'); | ||||
|         $this->handleObjects('PiggyBank', 'name', 'encrypted'); | ||||
|         $this->handleObjects('TransactionJournal', 'description', 'encrypted'); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -79,18 +74,21 @@ class UseEncryption extends Command | ||||
|      * @param string $field | ||||
|      * @param string $indicator | ||||
|      */ | ||||
|     public function handleObjects(string $class, string $field, string $indicator) | ||||
|     public function handleObjects(string $class, string $field, string $indicator): void | ||||
|     { | ||||
|         $fqn     = sprintf('FireflyIII\Models\%s', $class); | ||||
|         $encrypt = config('firefly.encryption') === true ? 0 : 1; | ||||
|         $set     = $fqn::where($indicator, $encrypt)->get(); | ||||
|         $encrypt = true === config('firefly.encryption') ? 0 : 1; | ||||
|         /** @noinspection PhpUndefinedMethodInspection */ | ||||
|         $set = $fqn::where($indicator, $encrypt)->get(); | ||||
|  | ||||
|         foreach ($set as $entry) { | ||||
|             $newName       = $entry->$field; | ||||
|             $entry->$field = $newName; | ||||
|             /** @noinspection PhpUndefinedMethodInspection */ | ||||
|             $entry->save(); | ||||
|         } | ||||
|  | ||||
|         /** @noinspection PhpUndefinedMethodInspection */ | ||||
|         $this->line(sprintf('Updated %d %s.', $set->count(), strtolower(Str::plural($class)))); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * VerifiesAccessToken.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,25 +18,26 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
|  | ||||
| use FireflyIII\Repositories\User\UserRepositoryInterface; | ||||
| use Log; | ||||
| use Preferences; | ||||
|  | ||||
| /** | ||||
|  * Trait VerifiesAccessToken. | ||||
|  * | ||||
|  * Verifies user access token for sensitive commands. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| trait VerifiesAccessToken | ||||
| { | ||||
|     /** | ||||
|      * Abstract method to make sure trait knows about method "option". | ||||
|      * | ||||
|      * @param null $key | ||||
|      * @param string|null $key | ||||
|      * | ||||
|      * @return mixed | ||||
|      */ | ||||
| @@ -49,18 +50,18 @@ trait VerifiesAccessToken | ||||
|      */ | ||||
|     protected function verifyAccessToken(): bool | ||||
|     { | ||||
|         $userId = intval($this->option('user')); | ||||
|         $token  = strval($this->option('token')); | ||||
|         $userId = (int)$this->option('user'); | ||||
|         $token  = (string)$this->option('token'); | ||||
|         /** @var UserRepositoryInterface $repository */ | ||||
|         $repository = app(UserRepositoryInterface::class); | ||||
|         $user       = $repository->find($userId); | ||||
|         $user       = $repository->findNull($userId); | ||||
|  | ||||
|         if (null === $user->id) { | ||||
|         if (null === $user) { | ||||
|             Log::error(sprintf('verifyAccessToken(): no such user for input "%d"', $userId)); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|         $accessToken = Preferences::getForUser($user, 'access_token', null); | ||||
|         $accessToken = app('preferences')->getForUser($user, 'access_token', null); | ||||
|         if (null === $accessToken) { | ||||
|             Log::error(sprintf('User #%d has no access token, so cannot access command line options.', $userId)); | ||||
|  | ||||
| @@ -68,7 +69,7 @@ trait VerifiesAccessToken | ||||
|         } | ||||
|         if (!($accessToken->data === $token)) { | ||||
|             Log::error(sprintf('Invalid access token for user #%d.', $userId)); | ||||
|             Log::error(sprintf('Token given is "%s", expected "%s".', $token, $accessToken->data)); | ||||
|             Log::error(sprintf('Token given is "%s", expected something else.', $token)); | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| <?php | ||||
| /** | ||||
|  * VerifyDatabase.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,6 +18,9 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| /** @noinspection PhpDynamicAsStaticMethodCallInspection */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console\Commands; | ||||
| @@ -27,6 +30,7 @@ use DB; | ||||
| use FireflyIII\Models\Account; | ||||
| use FireflyIII\Models\AccountType; | ||||
| use FireflyIII\Models\Budget; | ||||
| use FireflyIII\Models\Category; | ||||
| use FireflyIII\Models\LinkType; | ||||
| use FireflyIII\Models\PiggyBankEvent; | ||||
| use FireflyIII\Models\Transaction; | ||||
| @@ -37,14 +41,16 @@ use FireflyIII\User; | ||||
| use Illuminate\Console\Command; | ||||
| use Illuminate\Contracts\Encryption\DecryptException; | ||||
| use Illuminate\Database\Eloquent\Builder; | ||||
| use Preferences; | ||||
| use Log; | ||||
| use Schema; | ||||
| use stdClass; | ||||
|  | ||||
| /** | ||||
|  * Class VerifyDatabase. | ||||
|  * | ||||
|  * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) | ||||
|  * @SuppressWarnings(PHPMD.CouplingBetweenObjects) | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class VerifyDatabase extends Command | ||||
| { | ||||
| @@ -61,26 +67,18 @@ class VerifyDatabase extends Command | ||||
|      */ | ||||
|     protected $signature = 'firefly:verify'; | ||||
|  | ||||
|     /** | ||||
|      * Create a new command instance. | ||||
|      */ | ||||
|     public function __construct() | ||||
|     { | ||||
|         parent::__construct(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Execute the console command. | ||||
|      */ | ||||
|     public function handle() | ||||
|     public function handle(): int | ||||
|     { | ||||
|         // if table does not exist, return false | ||||
|         if (!Schema::hasTable('users')) { | ||||
|             return; | ||||
|             return 1; | ||||
|         } | ||||
|  | ||||
|         $this->reportObject('budget'); | ||||
|         $this->reportObject('category'); | ||||
|         $this->reportEmptyBudgets(); | ||||
|         $this->reportEmptyCategories(); | ||||
|         $this->reportObject('tag'); | ||||
|         $this->reportAccounts(); | ||||
|         $this->reportBudgetLimits(); | ||||
| @@ -95,21 +93,25 @@ class VerifyDatabase extends Command | ||||
|         $this->createLinkTypes(); | ||||
|         $this->createAccessTokens(); | ||||
|         $this->fixDoubleAmounts(); | ||||
|         $this->fixBadMeta(); | ||||
|         $this->removeBills(); | ||||
|  | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Create user access tokens, if not present already. | ||||
|      */ | ||||
|     private function createAccessTokens() | ||||
|     private function createAccessTokens(): void | ||||
|     { | ||||
|         $count = 0; | ||||
|         $users = User::get(); | ||||
|         /** @var User $user */ | ||||
|         foreach ($users as $user) { | ||||
|             $pref = Preferences::getForUser($user, 'access_token', null); | ||||
|             $pref = app('preferences')->getForUser($user, 'access_token', null); | ||||
|             if (null === $pref) { | ||||
|                 $token = $user->generateAccessToken(); | ||||
|                 Preferences::setForUser($user, 'access_token', $token); | ||||
|                 app('preferences')->setForUser($user, 'access_token', $token); | ||||
|                 $this->line(sprintf('Generated access token for user %s', $user->email)); | ||||
|                 ++$count; | ||||
|             } | ||||
| @@ -122,7 +124,7 @@ class VerifyDatabase extends Command | ||||
|     /** | ||||
|      * Create default link types if necessary. | ||||
|      */ | ||||
|     private function createLinkTypes() | ||||
|     private function createLinkTypes(): void | ||||
|     { | ||||
|         $count = 0; | ||||
|         $set   = [ | ||||
| @@ -148,7 +150,78 @@ class VerifyDatabase extends Command | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private function fixDoubleAmounts() | ||||
|     /** | ||||
|      * Fix the situation where the matching transactions of a journal somehow have non-matching categories or budgets. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     private function fixBadMeta(): void | ||||
|     { | ||||
|         // categories | ||||
|         $set     = Transaction | ||||
|             ::leftJoin('category_transaction', 'category_transaction.transaction_id', '=', 'transactions.id') | ||||
|             ->whereNull('transactions.deleted_at') | ||||
|             ->get(['transactions.id', 'transaction_journal_id', 'identifier', 'category_transaction.category_id', 'category_transaction.id as ct_id']); | ||||
|         $results = []; | ||||
|         foreach ($set as $obj) { | ||||
|             $key      = $obj->transaction_journal_id . '-' . $obj->identifier; | ||||
|             $category = (int)$obj->category_id; | ||||
|  | ||||
|             // value exists and is not category: | ||||
|             if (isset($results[$key]) && $results[$key] !== $category) { | ||||
|                 $this->error( | ||||
|                     sprintf( | ||||
|                         'Transaction #%d referred to the wrong category. Was category #%d but is fixed to be category #%d.', $obj->transaction_journal_id, | ||||
|                         $category, $results[$key] | ||||
|                     ) | ||||
|                 ); | ||||
|                 DB::table('category_transaction')->where('id', $obj->ct_id)->update(['category_id' => $results[$key]]); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             // value does not exist: | ||||
|             if ($category > 0 && !isset($results[$key])) { | ||||
|                 $results[$key] = $category; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // budgets | ||||
|         $set     = Transaction | ||||
|             ::leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id') | ||||
|             ->whereNull('transactions.deleted_at') | ||||
|             ->get(['transactions.id', 'transaction_journal_id', 'identifier', 'budget_transaction.budget_id', 'budget_transaction.id as ct_id']); | ||||
|         $results = []; | ||||
|         foreach ($set as $obj) { | ||||
|             $key    = $obj->transaction_journal_id . '-' . $obj->identifier; | ||||
|             $budget = (int)$obj->budget_id; | ||||
|  | ||||
|             // value exists and is not budget: | ||||
|             if (isset($results[$key]) && $results[$key] !== $budget) { | ||||
|                 $this->error( | ||||
|                     sprintf( | ||||
|                         'Transaction #%d referred to the wrong budget. Was budget #%d but is fixed to be budget #%d.', $obj->transaction_journal_id, $budget, | ||||
|                         $results[$key] | ||||
|                     ) | ||||
|                 ); | ||||
|                 DB::table('budget_transaction')->where('id', $obj->ct_id)->update(['budget_id' => $results[$key]]); | ||||
|  | ||||
|             } | ||||
|  | ||||
|             // value does not exist: | ||||
|             if ($budget > 0 && !isset($results[$key])) { | ||||
|                 $results[$key] = $budget; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Makes sure amounts are stored correctly. | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.CyclomaticComplexity) | ||||
|      * @SuppressWarnings(PHPMD.ExcessiveMethodLength) | ||||
|      */ | ||||
|     private function fixDoubleAmounts(): void | ||||
|     { | ||||
|         $count = 0; | ||||
|         // get invalid journals | ||||
| @@ -158,7 +231,7 @@ class VerifyDatabase extends Command | ||||
|                       ->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]); | ||||
|         /** @var stdClass $entry */ | ||||
|         foreach ($journals as $entry) { | ||||
|             if (0 !== bccomp(strval($entry->the_sum), '0')) { | ||||
|             if (0 !== bccomp((string)$entry->the_sum, '0')) { | ||||
|                 $errored[] = $entry->transaction_journal_id; | ||||
|             } | ||||
|         } | ||||
| @@ -171,7 +244,7 @@ class VerifyDatabase extends Command | ||||
|             // report about it | ||||
|             /** @var TransactionJournal $journal */ | ||||
|             $journal = TransactionJournal::find($journalId); | ||||
|             if (is_null($journal)) { | ||||
|             if (null === $journal) { | ||||
|                 continue; | ||||
|             } | ||||
|             if (TransactionType::OPENING_BALANCE === $journal->transactionType->type) { | ||||
| @@ -194,8 +267,23 @@ class VerifyDatabase extends Command | ||||
|         if (0 === $count) { | ||||
|             $this->info('Amount integrity OK!'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|         return; | ||||
|     /** | ||||
|      * Removes bills from journals that should not have bills. | ||||
|      */ | ||||
|     private function removeBills(): void | ||||
|     { | ||||
|         /** @var TransactionType $withdrawal */ | ||||
|         $withdrawal = TransactionType::where('type', TransactionType::WITHDRAWAL)->first(); | ||||
|         $journals   = TransactionJournal::whereNotNull('bill_id') | ||||
|                                         ->where('transaction_type_id', '!=', $withdrawal->id)->get(); | ||||
|         /** @var TransactionJournal $journal */ | ||||
|         foreach ($journals as $journal) { | ||||
|             $this->line(sprintf('Transaction journal #%d should not be linked to bill #%d.', $journal->id, $journal->bill_id)); | ||||
|             $journal->bill_id = null; | ||||
|             $journal->save(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -225,14 +313,12 @@ class VerifyDatabase extends Command | ||||
|                 return true; | ||||
|             } | ||||
|         ); | ||||
|  | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Reports on accounts with no transactions. | ||||
|      */ | ||||
|     private function reportAccounts() | ||||
|     private function reportAccounts(): void | ||||
|     { | ||||
|         $set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') | ||||
|                       ->leftJoin('users', 'accounts.user_id', '=', 'users.id') | ||||
| @@ -254,7 +340,7 @@ class VerifyDatabase extends Command | ||||
|     /** | ||||
|      * Reports on budgets with no budget limits (which makes them pointless). | ||||
|      */ | ||||
|     private function reportBudgetLimits() | ||||
|     private function reportBudgetLimits(): void | ||||
|     { | ||||
|         $set = Budget::leftJoin('budget_limits', 'budget_limits.budget_id', '=', 'budgets.id') | ||||
|                      ->leftJoin('users', 'budgets.user_id', '=', 'users.id') | ||||
| @@ -278,7 +364,7 @@ class VerifyDatabase extends Command | ||||
|     /** | ||||
|      * Reports on deleted accounts that still have not deleted transactions or journals attached to them. | ||||
|      */ | ||||
|     private function reportDeletedAccounts() | ||||
|     private function reportDeletedAccounts(): void | ||||
|     { | ||||
|         $set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') | ||||
|                       ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') | ||||
| @@ -297,7 +383,7 @@ class VerifyDatabase extends Command | ||||
|                       ); | ||||
|         /** @var stdClass $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $date = null === $entry->transaction_deleted_at ? $entry->journal_deleted_at : $entry->transaction_deleted_at; | ||||
|             $date = $entry->transaction_deleted_at ?? $entry->journal_deleted_at; | ||||
|             $this->error( | ||||
|                 'Error: Account #' . $entry->account_id . ' should have been deleted, but has not.' . | ||||
|                 ' Find it in the table called "accounts" and change the "deleted_at" field to: "' . $date . '"' | ||||
| @@ -305,10 +391,86 @@ class VerifyDatabase extends Command | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Report on budgets with no transactions or journals. | ||||
|      */ | ||||
|     private function reportEmptyBudgets(): void | ||||
|     { | ||||
|         $set = Budget::leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id') | ||||
|                      ->leftJoin('users', 'budgets.user_id', '=', 'users.id') | ||||
|                      ->distinct() | ||||
|                      ->whereNull('budget_transaction_journal.budget_id') | ||||
|                      ->whereNull('budgets.deleted_at') | ||||
|                      ->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']); | ||||
|  | ||||
|         /** @var stdClass $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $objName = $entry->name; | ||||
|             try { | ||||
|                 $objName = Crypt::decrypt($objName); | ||||
|             } catch (DecryptException $e) { | ||||
|                 // it probably was not encrypted. | ||||
|                 Log::debug(sprintf('Not a problem: %s', $e->getMessage())); | ||||
|             } | ||||
|  | ||||
|             // also count the transactions: | ||||
|             $countTransactions = DB::table('budget_transaction')->where('budget_id', $entry->id)->count(); | ||||
|  | ||||
|             if (0 === $countTransactions) { | ||||
|                 $line = sprintf( | ||||
|                     'User #%d (%s) has budget #%d ("%s") which has no transactions.', | ||||
|                     $entry->user_id, | ||||
|                     $entry->email, | ||||
|                     $entry->id, | ||||
|                     $objName | ||||
|                 ); | ||||
|                 $this->line($line); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Report on categories with no transactions or journals. | ||||
|      */ | ||||
|     private function reportEmptyCategories(): void | ||||
|     { | ||||
|         $set = Category::leftJoin('category_transaction_journal', 'categories.id', '=', 'category_transaction_journal.category_id') | ||||
|                        ->leftJoin('users', 'categories.user_id', '=', 'users.id') | ||||
|                        ->distinct() | ||||
|                        ->whereNull('category_transaction_journal.category_id') | ||||
|                        ->whereNull('categories.deleted_at') | ||||
|                        ->get(['categories.id', 'categories.name', 'categories.user_id', 'users.email']); | ||||
|  | ||||
|         /** @var stdClass $entry */ | ||||
|         foreach ($set as $entry) { | ||||
|             $objName = $entry->name; | ||||
|             try { | ||||
|                 $objName = Crypt::decrypt($objName); | ||||
|             } catch (DecryptException $e) { | ||||
|                 // it probably was not encrypted. | ||||
|                 Log::debug(sprintf('Not a problem: %s', $e->getMessage())); | ||||
|             } | ||||
|  | ||||
|             // also count the transactions: | ||||
|             $countTransactions = DB::table('category_transaction')->where('category_id', $entry->id)->count(); | ||||
|  | ||||
|             if (0 === $countTransactions) { | ||||
|                 $line = sprintf( | ||||
|                     'User #%d (%s) has category #%d ("%s") which has no transactions.', | ||||
|                     $entry->user_id, | ||||
|                     $entry->email, | ||||
|                     $entry->id, | ||||
|                     $objName | ||||
|                 ); | ||||
|                 $this->line($line); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Report on journals with bad account types linked to them. | ||||
|      */ | ||||
|     private function reportIncorrectJournals() | ||||
|     private function reportIncorrectJournals(): void | ||||
|     { | ||||
|         $configuration = [ | ||||
|             // a withdrawal can not have revenue account: | ||||
| @@ -350,7 +512,7 @@ class VerifyDatabase extends Command | ||||
|     /** | ||||
|      * Any deleted transaction journals that have transactions that are NOT deleted:. | ||||
|      */ | ||||
|     private function reportJournals() | ||||
|     private function reportJournals(): void | ||||
|     { | ||||
|         $count = 0; | ||||
|         $set   = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
| @@ -381,7 +543,7 @@ class VerifyDatabase extends Command | ||||
|     /** | ||||
|      * Report on journals without transactions. | ||||
|      */ | ||||
|     private function reportNoTransactions() | ||||
|     private function reportNoTransactions(): void | ||||
|     { | ||||
|         $count = 0; | ||||
|         $set   = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
| @@ -405,17 +567,18 @@ class VerifyDatabase extends Command | ||||
|      * | ||||
|      * @param string $name | ||||
|      */ | ||||
|     private function reportObject(string $name) | ||||
|     private function reportObject(string $name): void | ||||
|     { | ||||
|         $plural = str_plural($name); | ||||
|         $class  = sprintf('FireflyIII\Models\%s', ucfirst($name)); | ||||
|         $field  = 'tag' === $name ? 'tag' : 'name'; | ||||
|         $set    = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id') | ||||
|                         ->leftJoin('users', $plural . '.user_id', '=', 'users.id') | ||||
|                         ->distinct() | ||||
|                         ->whereNull($name . '_transaction_journal.' . $name . '_id') | ||||
|                         ->whereNull($plural . '.deleted_at') | ||||
|                         ->get([$plural . '.id', $plural . '.' . $field . ' as name', $plural . '.user_id', 'users.email']); | ||||
|         /** @noinspection PhpUndefinedMethodInspection */ | ||||
|         $set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id') | ||||
|                      ->leftJoin('users', $plural . '.user_id', '=', 'users.id') | ||||
|                      ->distinct() | ||||
|                      ->whereNull($name . '_transaction_journal.' . $name . '_id') | ||||
|                      ->whereNull($plural . '.deleted_at') | ||||
|                      ->get([$plural . '.id', $plural . '.' . $field . ' as name', $plural . '.user_id', 'users.email']); | ||||
|  | ||||
|         /** @var stdClass $entry */ | ||||
|         foreach ($set as $entry) { | ||||
| @@ -424,6 +587,7 @@ class VerifyDatabase extends Command | ||||
|                 $objName = Crypt::decrypt($objName); | ||||
|             } catch (DecryptException $e) { | ||||
|                 // it probably was not encrypted. | ||||
|                 Log::debug(sprintf('Not a problem: %s', $e->getMessage())); | ||||
|             } | ||||
|  | ||||
|             $line = sprintf( | ||||
| @@ -441,17 +605,18 @@ class VerifyDatabase extends Command | ||||
|     /** | ||||
|      * Reports for each user when the sum of their transactions is not zero. | ||||
|      */ | ||||
|     private function reportSum() | ||||
|     private function reportSum(): void | ||||
|     { | ||||
|         /** @var UserRepositoryInterface $userRepository */ | ||||
|         $userRepository = app(UserRepositoryInterface::class); | ||||
|  | ||||
|         /** @var User $user */ | ||||
|         foreach ($userRepository->all() as $user) { | ||||
|             $sum = strval($user->transactions()->sum('amount')); | ||||
|             $sum = (string)$user->transactions()->sum('amount'); | ||||
|             if (0 !== bccomp($sum, '0')) { | ||||
|                 $this->error('Error: Transactions for user #' . $user->id . ' (' . $user->email . ') are off by ' . $sum . '!'); | ||||
|             } else { | ||||
|             } | ||||
|             if (0 === bccomp($sum, '0')) { | ||||
|                 $this->info(sprintf('Amount integrity OK for user #%d', $user->id)); | ||||
|             } | ||||
|         } | ||||
| @@ -460,7 +625,7 @@ class VerifyDatabase extends Command | ||||
|     /** | ||||
|      * Reports on deleted transactions that are connected to a not deleted journal. | ||||
|      */ | ||||
|     private function reportTransactions() | ||||
|     private function reportTransactions(): void | ||||
|     { | ||||
|         $set = Transaction::leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') | ||||
|                           ->whereNotNull('transactions.deleted_at') | ||||
| @@ -481,7 +646,7 @@ class VerifyDatabase extends Command | ||||
|     /** | ||||
|      * Report on transfers that have budgets. | ||||
|      */ | ||||
|     private function reportTransfersBudgets() | ||||
|     private function reportTransfersBudgets(): void | ||||
|     { | ||||
|         $set = TransactionJournal::distinct() | ||||
|                                  ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Kernel.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,34 +19,29 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Console; | ||||
|  | ||||
| use Illuminate\Console\Scheduling\Schedule; | ||||
| use Illuminate\Foundation\Console\Kernel as ConsoleKernel; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * File to make sure commnds work. | ||||
|  * File to make sure commands work. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class Kernel extends ConsoleKernel | ||||
| { | ||||
|     /** | ||||
|      * The Artisan commands provided by your application. | ||||
|      * | ||||
|      * @var array | ||||
|      */ | ||||
|     protected $commands | ||||
|         = [ | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * Register the commands for the application. | ||||
|      */ | ||||
|     protected function commands() | ||||
|     protected function commands(): void | ||||
|     { | ||||
|         $this->load(__DIR__ . '/Commands'); | ||||
|  | ||||
|         /** @noinspection PhpIncludeInspection */ | ||||
|         require base_path('routes/console.php'); | ||||
|     } | ||||
|  | ||||
| @@ -53,10 +49,24 @@ class Kernel extends ConsoleKernel | ||||
|      * Define the application's command schedule. | ||||
|      * | ||||
|      * @param \Illuminate\Console\Scheduling\Schedule $schedule | ||||
|      * | ||||
|      * @SuppressWarnings(PHPMD.UnusedFormalParameter) | ||||
|      */ | ||||
|     protected function schedule(Schedule $schedule) | ||||
|     protected function schedule(Schedule $schedule): void | ||||
|     { | ||||
|         $schedule->call( | ||||
|             function () { | ||||
|                 Log::error('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions at https://firefly-iii.readthedocs.io/en/latest/'); | ||||
|                 echo "\n"; | ||||
|                 echo '------------'; | ||||
|                 echo "\n"; | ||||
|                 echo wordwrap('Firefly III no longer users the Laravel scheduler to do cron jobs! Please read the instructions here:'); | ||||
|                 echo "\n"; | ||||
|                 echo 'https://firefly-iii.readthedocs.io/en/latest/'; | ||||
|                 echo "\n\n"; | ||||
|                 echo 'Disable this cron job!'; | ||||
|                 echo "\n"; | ||||
|                 echo '------------'; | ||||
|                 echo "\n"; | ||||
|             } | ||||
|         )->everyMinute(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * AdminRequestedTestMessage.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,6 +19,7 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Events; | ||||
| @@ -28,18 +30,15 @@ use Log; | ||||
|  | ||||
| /** | ||||
|  * Class AdminRequestedTestMessage. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class AdminRequestedTestMessage extends Event | ||||
| { | ||||
|     use SerializesModels; | ||||
|  | ||||
|     /** | ||||
|      * @var string | ||||
|      */ | ||||
|     /** @var string The users IP address */ | ||||
|     public $ipAddress; | ||||
|     /** | ||||
|      * @var User | ||||
|      */ | ||||
|     /** @var User The user */ | ||||
|     public $user; | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * Event.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,12 +19,14 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Events; | ||||
|  | ||||
| /** | ||||
|  * Class Event. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| abstract class Event | ||||
| { | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * RegisteredUser.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,6 +19,7 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Events; | ||||
| @@ -27,18 +29,15 @@ use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class RegisteredUser. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class RegisteredUser extends Event | ||||
| { | ||||
|     use SerializesModels; | ||||
|  | ||||
|     /** | ||||
|      * @var string | ||||
|      */ | ||||
|     /** @var string The users IP address */ | ||||
|     public $ipAddress; | ||||
|     /** | ||||
|      * @var User | ||||
|      */ | ||||
|     /** @var User The user */ | ||||
|     public $user; | ||||
|  | ||||
|     /** | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * RequestedNewPassword.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -18,6 +19,7 @@ | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| declare(strict_types=1); | ||||
|  | ||||
| namespace FireflyIII\Events; | ||||
| @@ -27,22 +29,17 @@ use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class RequestedNewPassword. | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class RequestedNewPassword extends Event | ||||
| { | ||||
|     use SerializesModels; | ||||
|  | ||||
|     /** | ||||
|      * @var string | ||||
|      */ | ||||
|     /** @var string The users IP address */ | ||||
|     public $ipAddress; | ||||
|     /** | ||||
|      * @var string | ||||
|      */ | ||||
|     /** @var string The token */ | ||||
|     public $token; | ||||
|     /** | ||||
|      * @var User | ||||
|      */ | ||||
|     /** @var User The user */ | ||||
|     public $user; | ||||
|  | ||||
|     /** | ||||
|   | ||||
							
								
								
									
										68
									
								
								app/Events/RequestedReportOnJournals.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								app/Events/RequestedReportOnJournals.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| <?php | ||||
| declare(strict_types=1); | ||||
| /** | ||||
|  * RequestedReportOnJournals.php | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
|  * Firefly III is free software: you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation, either version 3 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * | ||||
|  * Firefly III is distributed in the hope that it will be useful, | ||||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
|  * GNU General Public License for more details. | ||||
|  * | ||||
|  * You should have received a copy of the GNU General Public License | ||||
|  * along with Firefly III. If not, see <http://www.gnu.org/licenses/>. | ||||
|  */ | ||||
|  | ||||
| namespace FireflyIII\Events; | ||||
|  | ||||
| use Illuminate\Broadcasting\InteractsWithSockets; | ||||
| use Illuminate\Broadcasting\PrivateChannel; | ||||
| use Illuminate\Foundation\Events\Dispatchable; | ||||
| use Illuminate\Queue\SerializesModels; | ||||
| use Illuminate\Support\Collection; | ||||
| use Log; | ||||
|  | ||||
| /** | ||||
|  * Class RequestedReportOnJournals | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class RequestedReportOnJournals | ||||
| { | ||||
|     use Dispatchable, InteractsWithSockets, SerializesModels; | ||||
|  | ||||
|     /** @var Collection The journals to report on. */ | ||||
|     public $journals; | ||||
|     /** @var int The ID of the user. */ | ||||
|     public $userId; | ||||
|  | ||||
|     /** | ||||
|      * Create a new event instance. | ||||
|      * | ||||
|      * @param int        $userId | ||||
|      * @param Collection $journals | ||||
|      */ | ||||
|     public function __construct(int $userId, Collection $journals) | ||||
|     { | ||||
|         Log::debug('In event RequestedReportOnJournals.'); | ||||
|         $this->userId   = $userId; | ||||
|         $this->journals = $journals; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Get the channels the event should broadcast on. | ||||
|      * | ||||
|      * @return \Illuminate\Broadcasting\Channel|array | ||||
|      */ | ||||
|     public function broadcastOn() | ||||
|     { | ||||
|         return new PrivateChannel('channel-name'); | ||||
|     } | ||||
| } | ||||
| @@ -1,7 +1,8 @@ | ||||
| <?php | ||||
|  | ||||
| /** | ||||
|  * RequestedVersionCheckStatus.php | ||||
|  * Copyright (c) 2017 thegrumpydictator@gmail.com | ||||
|  * Copyright (c) 2018 thegrumpydictator@gmail.com | ||||
|  * | ||||
|  * This file is part of Firefly III. | ||||
|  * | ||||
| @@ -29,14 +30,14 @@ use Illuminate\Queue\SerializesModels; | ||||
|  | ||||
| /** | ||||
|  * Class RequestedVersionCheckStatus | ||||
|  * | ||||
|  * @codeCoverageIgnore | ||||
|  */ | ||||
| class RequestedVersionCheckStatus extends Event | ||||
| { | ||||
|     use SerializesModels; | ||||
|  | ||||
|     /** | ||||
|      * @var User | ||||
|      */ | ||||
|     /** @var User The user */ | ||||
|     public $user; | ||||
|  | ||||
|     /** | ||||
| @@ -49,4 +50,4 @@ class RequestedVersionCheckStatus extends Event | ||||
|     { | ||||
|         $this->user = $user; | ||||
|     } | ||||
| } | ||||
| } | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user