Compare commits

...

1330 Commits

Author SHA1 Message Date
James Cole
aea6575358 Merge branch 'release/4.6.6' 2017-09-30 09:11:16 +02:00
James Cole
d0054e657e Updated composer file. 2017-09-30 09:03:13 +02:00
James Cole
d2e312e1c3 Update changelog. [skip ci] 2017-09-30 08:40:36 +02:00
James Cole
8678f9af65 Add redirect for tag thing. See #875 2017-09-29 16:54:23 +02:00
James Cole
cca29bcdfe Take redirect uri from controller class. 2017-09-29 16:53:09 +02:00
James Cole
40f2659b91 Smooth error catching. 2017-09-29 15:32:47 +02:00
James Cole
d306183c95 Catch exceptions in FixerIO 2017-09-29 15:32:35 +02:00
James Cole
a34d888024 Merge pull request #874 from firefly-iii/l10n_develop
New Crowdin translations
2017-09-29 15:02:54 +02:00
James Cole
2932689c53 New translations form.php (Dutch) 2017-09-29 14:50:26 +02:00
James Cole
b0b8a8cc25 New translations intro.php (Dutch) 2017-09-29 14:50:24 +02:00
James Cole
ce8056424f New translations bank.php (Dutch) 2017-09-29 14:50:23 +02:00
James Cole
1567a0181b Merge pull request #821 from firefly-iii/l10n_develop
New Crowdin translations
2017-09-29 14:49:39 +02:00
James Cole
b60ad97150 New translations firefly.php (Dutch) 2017-09-29 14:40:08 +02:00
James Cole
cc93e4442b New translations firefly.php (Spanish) 2017-09-29 14:30:58 +02:00
James Cole
1f4ec8211e New translations firefly.php (Slovenian) 2017-09-29 14:30:51 +02:00
James Cole
3a9cbcc565 New translations firefly.php (Portuguese, Brazilian) 2017-09-29 14:30:49 +02:00
James Cole
fe6cce7495 New translations firefly.php (Dutch) 2017-09-29 14:30:45 +02:00
James Cole
f98e24e443 New translations firefly.php (French) 2017-09-29 14:30:43 +02:00
James Cole
4ffbc0932c New translations firefly.php (Polish) 2017-09-29 14:30:40 +02:00
James Cole
9eec12a4de New translations firefly.php (German) 2017-09-29 14:30:37 +02:00
James Cole
40d1011c37 New translations firefly.php (Russian) 2017-09-29 14:30:23 +02:00
James Cole
aa4682af6a Expand budget box and clear some languages. 2017-09-29 14:22:40 +02:00
James Cole
47bea97c96 New translations firefly.php (Spanish) 2017-09-29 09:02:15 +02:00
James Cole
78b76d0f65 New translations firefly.php (Slovenian) 2017-09-29 09:02:05 +02:00
James Cole
3a70a85283 New translations firefly.php (Portuguese, Brazilian) 2017-09-29 09:01:59 +02:00
James Cole
aa7e6166c1 New translations firefly.php (Dutch) 2017-09-29 09:01:51 +02:00
James Cole
08dcd9407b New translations firefly.php (French) 2017-09-29 09:01:47 +02:00
James Cole
2c263d6e82 New translations firefly.php (Polish) 2017-09-29 09:01:41 +02:00
James Cole
ca9a4e44b4 New translations firefly.php (German) 2017-09-29 09:01:35 +02:00
James Cole
a1b74eaa8e New translations intro.php (Dutch) 2017-09-29 09:01:14 +02:00
James Cole
a3732a65c9 New translations intro.php (French) 2017-09-29 09:01:13 +02:00
James Cole
f6a162def1 New translations intro.php (German) 2017-09-29 09:01:11 +02:00
James Cole
7e96f212c6 New translations firefly.php (Russian) 2017-09-29 09:01:08 +02:00
James Cole
67c4ae5d49 New translations intro.php (Polish) 2017-09-29 09:01:01 +02:00
James Cole
c0ce65e71f New translations intro.php (Portuguese, Brazilian) 2017-09-29 09:00:59 +02:00
James Cole
77cc04d9b3 New translations intro.php (Russian) 2017-09-29 09:00:56 +02:00
James Cole
5c8ed110f5 New translations intro.php (Slovenian) 2017-09-29 09:00:54 +02:00
James Cole
3104ee1263 New translations intro.php (Spanish) 2017-09-29 09:00:53 +02:00
James Cole
76ed261441 A basic box for #786 2017-09-29 08:52:15 +02:00
James Cole
0b36facec3 New translations firefly.php (Spanish) 2017-09-28 09:01:14 +02:00
James Cole
2a4f6d6f1f New translations firefly.php (Slovenian) 2017-09-28 09:01:10 +02:00
James Cole
ffe9eaaae5 New translations firefly.php (Portuguese, Brazilian) 2017-09-28 09:01:07 +02:00
James Cole
2a2c6335a5 New translations firefly.php (Dutch) 2017-09-28 09:01:04 +02:00
James Cole
8b36c17e30 New translations firefly.php (French) 2017-09-28 09:01:00 +02:00
James Cole
dae3c4ccc7 New translations firefly.php (Polish) 2017-09-28 09:00:57 +02:00
James Cole
0514258290 New translations firefly.php (German) 2017-09-28 09:00:54 +02:00
James Cole
c5fdeacc87 New translations firefly.php (Russian) 2017-09-28 09:00:30 +02:00
James Cole
b11ea13b1d New translations bank.php (Portuguese, Brazilian) 2017-09-28 09:00:24 +02:00
James Cole
9823603a0c New translations bank.php (Russian) 2017-09-28 09:00:23 +02:00
James Cole
366a618d00 New translations bank.php (Slovenian) 2017-09-28 09:00:22 +02:00
James Cole
dee681ed2a New translations bank.php (Spanish) 2017-09-28 09:00:22 +02:00
James Cole
8c116862e2 New translations bank.php (Polish) 2017-09-28 09:00:20 +02:00
James Cole
9a86b907d7 New translations bank.php (German) 2017-09-28 09:00:19 +02:00
James Cole
b70861df30 New translations bank.php (French) 2017-09-28 09:00:18 +02:00
James Cole
f8a1e9b6d5 New translations bank.php (Dutch) 2017-09-28 09:00:17 +02:00
James Cole
aaac47ebfc Icons will not break [skip ci] 2017-09-28 08:59:59 +02:00
James Cole
fd1feadc67 Fix #826 2017-09-28 08:59:40 +02:00
James Cole
1fc54f5207 New translations form.php (Dutch) 2017-09-28 08:20:50 +02:00
James Cole
04efdf75db New translations form.php (French) 2017-09-28 08:20:49 +02:00
James Cole
eee4909755 New translations form.php (German) 2017-09-28 08:20:48 +02:00
James Cole
c8bf7e9c28 New translations form.php (Polish) 2017-09-28 08:20:35 +02:00
James Cole
07e2c1000c New translations form.php (Portuguese, Brazilian) 2017-09-28 08:20:34 +02:00
James Cole
e9afd21375 New translations form.php (Slovenian) 2017-09-28 08:20:31 +02:00
James Cole
b1ea6f5595 New translations form.php (Spanish) 2017-09-28 08:20:30 +02:00
James Cole
69b454da7d New translations form.php (Russian) 2017-09-28 08:20:17 +02:00
James Cole
c19c7c680b Small improvements to bunq import. 2017-09-28 08:17:32 +02:00
James Cole
12ceecd57b New translations firefly.php (Polish) 2017-09-27 15:52:11 +02:00
James Cole
75f64225ee New translations firefly.php (Portuguese, Brazilian) 2017-09-27 15:52:07 +02:00
James Cole
f157eff2c3 New translations firefly.php (Slovenian) 2017-09-27 15:52:01 +02:00
James Cole
95a185ec39 New translations firefly.php (Spanish) 2017-09-27 15:51:55 +02:00
James Cole
7963e511b9 New translations firefly.php (German) 2017-09-27 15:51:50 +02:00
James Cole
2608e1ae74 New translations firefly.php (French) 2017-09-27 15:51:43 +02:00
James Cole
13a6dd56a3 New translations firefly.php (Dutch) 2017-09-27 15:51:35 +02:00
James Cole
a7969dd4b4 New translations firefly.php (Russian) 2017-09-27 15:51:06 +02:00
James Cole
b80b026246 Fix tests. 2017-09-27 15:46:08 +02:00
James Cole
a1a93d9bbb Send test message from admin. 2017-09-27 15:45:55 +02:00
James Cole
12df3d7b8e New translations firefly.php (Polish) 2017-09-27 14:52:47 +02:00
James Cole
e564a4a0d3 New translations firefly.php (Portuguese, Brazilian) 2017-09-27 14:52:40 +02:00
James Cole
b2a9128b2b New translations firefly.php (Slovenian) 2017-09-27 14:52:33 +02:00
James Cole
866bcbf702 New translations firefly.php (Spanish) 2017-09-27 14:52:27 +02:00
James Cole
6d538dc568 New translations firefly.php (German) 2017-09-27 14:52:20 +02:00
James Cole
c5737c7fc9 New translations firefly.php (French) 2017-09-27 14:52:12 +02:00
James Cole
c60c0a93a4 New translations firefly.php (Dutch) 2017-09-27 14:52:02 +02:00
James Cole
ed7119bae5 New translations firefly.php (Russian) 2017-09-27 14:51:30 +02:00
James Cole
c9cb310a2f Remove crappy translation of link types. Still needs a solution. 2017-09-27 14:50:04 +02:00
James Cole
fdfe18a952 Fix code for boxes. 2017-09-27 14:42:12 +02:00
James Cole
5631daa173 New translations firefly.php (Polish) 2017-09-27 14:42:02 +02:00
James Cole
38aa22fa5f New translations firefly.php (Portuguese, Brazilian) 2017-09-27 14:41:55 +02:00
James Cole
eab7d400e5 New translations firefly.php (Slovenian) 2017-09-27 14:41:50 +02:00
James Cole
29e6fba089 New translations firefly.php (Spanish) 2017-09-27 14:41:44 +02:00
James Cole
979cb605f5 New translations firefly.php (German) 2017-09-27 14:41:39 +02:00
James Cole
be4db5983d New translations firefly.php (French) 2017-09-27 14:41:31 +02:00
James Cole
aabcbaa665 New translations firefly.php (Dutch) 2017-09-27 14:41:23 +02:00
James Cole
dc18db5a17 New translations firefly.php (Russian) 2017-09-27 14:40:56 +02:00
James Cole
fb140b1379 Missing language strings [skip ci] 2017-09-27 14:31:02 +02:00
James Cole
97be088716 Add FF version in CSS for easier updates [skip ci] 2017-09-27 08:49:59 +02:00
James Cole
3e39deec36 Updated website boxes. 2017-09-27 08:45:27 +02:00
James Cole
6f55049fb6 Complex but workable code for #865 2017-09-26 10:59:17 +02:00
James Cole
066d114dfe New translations firefly.php (Polish) 2017-09-26 09:21:11 +02:00
James Cole
acb8bd7244 New translations firefly.php (Portuguese, Brazilian) 2017-09-26 09:21:08 +02:00
James Cole
d75a1583cc New translations firefly.php (Slovenian) 2017-09-26 09:21:05 +02:00
James Cole
c553f9eee0 New translations firefly.php (Spanish) 2017-09-26 09:21:02 +02:00
James Cole
117059077f New translations firefly.php (German) 2017-09-26 09:20:58 +02:00
James Cole
c3555bae1f New translations firefly.php (French) 2017-09-26 09:20:55 +02:00
James Cole
2c7ab07b41 New translations firefly.php (Dutch) 2017-09-26 09:20:51 +02:00
James Cole
12f31ffb81 New translations form.php (Dutch) 2017-09-26 09:20:48 +02:00
James Cole
3cb4cc88e8 New translations form.php (French) 2017-09-26 09:20:47 +02:00
James Cole
82ea17d2eb New translations form.php (Spanish) 2017-09-26 09:20:43 +02:00
James Cole
61ac8adc7d New translations form.php (German) 2017-09-26 09:20:42 +02:00
James Cole
7681a2a544 New translations form.php (Polish) 2017-09-26 09:20:40 +02:00
James Cole
5a5bce953c New translations form.php (Portuguese, Brazilian) 2017-09-26 09:20:39 +02:00
James Cole
1263fd7b98 New translations form.php (Slovenian) 2017-09-26 09:20:38 +02:00
James Cole
c3ea62aa44 New translations firefly.php (Russian) 2017-09-26 09:20:29 +02:00
James Cole
82ebf92b06 New translations form.php (Russian) 2017-09-26 09:20:26 +02:00
James Cole
d99adb515a More code for #857 2017-09-26 09:15:21 +02:00
James Cole
5ca239e177 New translations firefly.php (Polish) 2017-09-26 09:01:19 +02:00
James Cole
b525893c39 New translations firefly.php (Portuguese, Brazilian) 2017-09-26 09:01:16 +02:00
James Cole
7cdc159a50 New translations firefly.php (Slovenian) 2017-09-26 09:01:13 +02:00
James Cole
0f441aef42 New translations firefly.php (Spanish) 2017-09-26 09:01:11 +02:00
James Cole
6497dc1701 New translations firefly.php (German) 2017-09-26 09:01:08 +02:00
James Cole
bbe13487d3 New translations firefly.php (French) 2017-09-26 09:01:05 +02:00
James Cole
8fc6f82a04 New translations firefly.php (Dutch) 2017-09-26 09:01:01 +02:00
James Cole
e791215bb8 New translations form.php (Dutch) 2017-09-26 09:00:59 +02:00
James Cole
db83d541b4 New translations form.php (French) 2017-09-26 09:00:58 +02:00
James Cole
08bc3e7596 New translations form.php (Spanish) 2017-09-26 09:00:55 +02:00
James Cole
9c47c6173f New translations form.php (German) 2017-09-26 09:00:53 +02:00
James Cole
1458300768 New translations form.php (Polish) 2017-09-26 09:00:52 +02:00
James Cole
1752ea527d New translations form.php (Portuguese, Brazilian) 2017-09-26 09:00:50 +02:00
James Cole
acea869a98 New translations form.php (Slovenian) 2017-09-26 09:00:49 +02:00
James Cole
91426b9491 New translations firefly.php (Russian) 2017-09-26 09:00:41 +02:00
James Cole
0491623313 New translations form.php (Russian) 2017-09-26 09:00:38 +02:00
James Cole
91e96aa4b9 New code for email address change in profile. See #857 2017-09-26 08:52:16 +02:00
James Cole
c099572fd8 New translations firefly.php (Polish) 2017-09-25 09:31:43 +02:00
James Cole
7d481efff9 New translations firefly.php (Portuguese, Brazilian) 2017-09-25 09:31:41 +02:00
James Cole
a210112dc6 New translations firefly.php (Slovenian) 2017-09-25 09:31:38 +02:00
James Cole
04e4eea735 New translations firefly.php (Spanish) 2017-09-25 09:31:35 +02:00
James Cole
3e0fb03a0b New translations firefly.php (German) 2017-09-25 09:31:32 +02:00
James Cole
17d042d4a2 New translations firefly.php (French) 2017-09-25 09:31:28 +02:00
James Cole
a54883ab91 New translations firefly.php (Dutch) 2017-09-25 09:31:24 +02:00
James Cole
dfb3f81b69 New translations firefly.php (Russian) 2017-09-25 09:31:10 +02:00
James Cole
ea1d543795 Fix #853 2017-09-25 09:28:16 +02:00
James Cole
c917d2b1c4 Improve readme [skip ci] 2017-09-25 07:40:49 +02:00
James Cole
96419fb359 Fix #847 2017-09-25 07:32:29 +02:00
James Cole
0b0e0054b3 Fix tests. 2017-09-25 07:01:52 +02:00
James Cole
1199a44f92 New translations firefly.php (Dutch) 2017-09-25 06:20:08 +02:00
James Cole
1a81cd45f2 Fix #866 2017-09-25 06:14:37 +02:00
James Cole
6134372101 New translations list.php (Dutch) 2017-09-25 06:10:05 +02:00
James Cole
4ec830a2e3 Fix list overview [skip ci] 2017-09-25 06:10:04 +02:00
James Cole
73df3040ca Fix list overview [skip ci] 2017-09-25 06:04:37 +02:00
James Cole
0dc5282898 New translations firefly.php (Polish) 2017-09-24 21:20:58 +02:00
James Cole
fafa0bfeef New translations firefly.php (Portuguese, Brazilian) 2017-09-24 21:20:55 +02:00
James Cole
e7e512e2f8 New translations firefly.php (Slovenian) 2017-09-24 21:20:52 +02:00
James Cole
467571d3bb New translations firefly.php (Spanish) 2017-09-24 21:20:50 +02:00
James Cole
11b01f0cd8 New translations firefly.php (German) 2017-09-24 21:20:47 +02:00
James Cole
f069ee1b0f New translations firefly.php (French) 2017-09-24 21:20:44 +02:00
James Cole
e51ff88671 New translations firefly.php (Dutch) 2017-09-24 21:20:42 +02:00
James Cole
ee68f1df3e New translations list.php (French) 2017-09-24 21:20:39 +02:00
James Cole
456ec4ee0a New translations list.php (German) 2017-09-24 21:20:37 +02:00
James Cole
9c17594c34 New translations list.php (Polish) 2017-09-24 21:20:36 +02:00
James Cole
2dfc37c1d8 New translations list.php (Portuguese, Brazilian) 2017-09-24 21:20:35 +02:00
James Cole
1d36221607 New translations list.php (Dutch) 2017-09-24 21:20:34 +02:00
James Cole
388c886552 New translations list.php (Slovenian) 2017-09-24 21:20:26 +02:00
James Cole
fde2dd1c92 New translations list.php (Spanish) 2017-09-24 21:20:25 +02:00
James Cole
42898846c6 New translations firefly.php (Russian) 2017-09-24 21:20:24 +02:00
James Cole
a475c99987 New translations list.php (Russian) 2017-09-24 21:20:21 +02:00
James Cole
ac0e2c9885 Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop
* 'develop' of https://github.com/firefly-iii/firefly-iii:
  New translation strings.
  Update JournalRepository.php
  Update Amount.php
  Update ImportStorage.php
  Fix #854
  Enable mod_ssl by default
2017-09-24 21:18:57 +02:00
James Cole
260ef1a07e Tag view update. 2017-09-24 21:18:43 +02:00
James Cole
9d59a9b83e New translations form.php (Dutch) 2017-09-21 09:00:21 +02:00
James Cole
c5434aba13 New translations firefly.php (Polish) 2017-09-21 07:00:59 +02:00
James Cole
dd33b96c12 New translations firefly.php (Portuguese, Brazilian) 2017-09-21 07:00:57 +02:00
James Cole
349e449cb8 New translations firefly.php (Slovenian) 2017-09-21 07:00:54 +02:00
James Cole
0524ca0297 New translations firefly.php (Spanish) 2017-09-21 07:00:51 +02:00
James Cole
7bdaf8bac3 New translations firefly.php (German) 2017-09-21 07:00:48 +02:00
James Cole
1dd62a1934 New translations firefly.php (French) 2017-09-21 07:00:45 +02:00
James Cole
0a4c4729cf New translations firefly.php (Dutch) 2017-09-21 07:00:42 +02:00
James Cole
daf4c2ad49 New translations form.php (Dutch) 2017-09-21 07:00:40 +02:00
James Cole
2e60ab8763 New translations form.php (French) 2017-09-21 07:00:39 +02:00
James Cole
62d58afb68 New translations form.php (Spanish) 2017-09-21 07:00:36 +02:00
James Cole
93cd7310f4 New translations form.php (German) 2017-09-21 07:00:34 +02:00
James Cole
1b8f4f7735 New translations form.php (Polish) 2017-09-21 07:00:33 +02:00
James Cole
d446c1c5e7 New translations form.php (Portuguese, Brazilian) 2017-09-21 07:00:32 +02:00
James Cole
d5bfe682fe New translations form.php (Slovenian) 2017-09-21 07:00:31 +02:00
James Cole
47fc3398e0 New translations firefly.php (Russian) 2017-09-21 07:00:24 +02:00
James Cole
62bd6d13d1 New translations form.php (Russian) 2017-09-21 07:00:21 +02:00
James Cole
9f1ea0807b Merge branch 'develop' of github.com:JC5/firefly-iii into develop 2017-09-21 06:51:31 +02:00
James Cole
9c5b639986 New translation strings. 2017-09-21 06:50:58 +02:00
James Cole
ec73607974 Update JournalRepository.php
Fix #860
2017-09-20 08:35:20 +02:00
James Cole
e442eb6ce2 Update Amount.php
Fix null pointer #854
2017-09-20 08:31:00 +02:00
James Cole
a7e5072c8e New translations firefly.php (Dutch) 2017-09-19 08:00:07 +02:00
James Cole
db9c0600a8 Update ImportStorage.php
Fix for #854
2017-09-19 07:51:16 +02:00
James Cole
cea1673058 New translations list.php (Dutch) 2017-09-18 14:40:07 +02:00
James Cole
3f93941dd9 Fix #854 2017-09-17 19:21:03 +02:00
James Cole
4fa33c892a Merge pull request #855 from ms32035/mod_ssl
Enable mod_ssl in docker container
2017-09-17 19:14:26 +02:00
Marcin Szymanski
fb3230845d Enable mod_ssl by default 2017-09-17 14:42:29 +01:00
James Cole
37250cbde3 Various code cleanup. 2017-09-16 09:24:48 +02:00
James Cole
3424ec1c27 Various code cleanup. 2017-09-16 07:41:03 +02:00
James Cole
fe9adba7fb Reinstate secure pw check and single user verification. 2017-09-16 07:18:15 +02:00
James Cole
b1135cee60 Various code cleanup 2017-09-16 07:17:58 +02:00
James Cole
d44347d7d6 New translations firefly.php (Polish) 2017-09-16 07:00:54 +02:00
James Cole
f04a28215e New translations firefly.php (Portuguese, Brazilian) 2017-09-16 07:00:51 +02:00
James Cole
7b54d93c52 New translations firefly.php (Slovenian) 2017-09-16 07:00:48 +02:00
James Cole
a61999baff New translations firefly.php (Spanish) 2017-09-16 07:00:46 +02:00
James Cole
fbeb4b60a3 New translations firefly.php (German) 2017-09-16 07:00:43 +02:00
James Cole
91b7c307b6 New translations firefly.php (French) 2017-09-16 07:00:40 +02:00
James Cole
92239322f9 New translations firefly.php (Dutch) 2017-09-16 07:00:37 +02:00
James Cole
128f9cc9eb New translations firefly.php (Russian) 2017-09-16 07:00:22 +02:00
James Cole
bbab89d884 Fixes #848 2017-09-16 06:52:53 +02:00
James Cole
6fd040d420 Fix null pointer exception. #846 2017-09-15 17:35:44 +02:00
James Cole
c8cec91a93 Add debug info to job change status [skip ci] 2017-09-15 07:00:53 +02:00
James Cole
38bb074751 Fix storage bug in #845 2017-09-15 06:26:09 +02:00
James Cole
337088b567 New translations firefly.php (Portuguese, Brazilian) 2017-09-14 21:21:18 +02:00
James Cole
1727273d98 New translations firefly.php (Spanish) 2017-09-14 21:21:14 +02:00
James Cole
adeb569d84 New translations firefly.php (German) 2017-09-14 21:21:11 +02:00
James Cole
dd8142e26a New translations firefly.php (French) 2017-09-14 21:21:08 +02:00
James Cole
50df395f72 New translations firefly.php (Dutch) 2017-09-14 21:21:04 +02:00
James Cole
519ca4b2af Improve export routine and cron job for #837 2017-09-14 21:17:19 +02:00
James Cole
f54b4c3abc Implement access token for command line things. 2017-09-14 18:27:22 +02:00
James Cole
43a66fd378 Export job. 2017-09-14 18:10:38 +02:00
James Cole
f4938cfed7 Debug text in import routine. 2017-09-14 18:10:31 +02:00
James Cole
6badf101d7 Small cosmetic changes to export routine. 2017-09-14 18:03:39 +02:00
James Cole
3d27f22d2e New translations firefly.php (Polish) 2017-09-14 17:51:05 +02:00
James Cole
acac5f8ea2 New translations firefly.php (Portuguese, Brazilian) 2017-09-14 17:51:02 +02:00
James Cole
1d1b3afab5 New translations firefly.php (Slovenian) 2017-09-14 17:50:59 +02:00
James Cole
ad2c6390a6 New translations firefly.php (Spanish) 2017-09-14 17:50:56 +02:00
James Cole
c16bcf7b57 New translations firefly.php (German) 2017-09-14 17:50:51 +02:00
James Cole
7ecf5804bc New translations firefly.php (French) 2017-09-14 17:50:48 +02:00
James Cole
b43e197dde New translations firefly.php (Dutch) 2017-09-14 17:50:44 +02:00
James Cole
48bd80d4c4 New translations firefly.php (Russian) 2017-09-14 17:50:28 +02:00
James Cole
fc67c9a476 Add missing translation for #843 2017-09-14 17:45:43 +02:00
James Cole
ca861e2a5d New translations list.php (French) 2017-09-14 17:42:53 +02:00
James Cole
a626f71b9f New translations list.php (German) 2017-09-14 17:42:52 +02:00
James Cole
d0f1509a9e New translations list.php (Polish) 2017-09-14 17:42:50 +02:00
James Cole
64194da2f2 New translations list.php (Portuguese, Brazilian) 2017-09-14 17:42:49 +02:00
James Cole
f4ac589eab New translations list.php (Dutch) 2017-09-14 17:42:48 +02:00
James Cole
96b2184d27 New translations list.php (Slovenian) 2017-09-14 17:42:39 +02:00
James Cole
e196ff7281 New translations list.php (Spanish) 2017-09-14 17:42:38 +02:00
James Cole
bc05afeabb New translations list.php (Russian) 2017-09-14 17:42:35 +02:00
James Cole
5e900736f8 Various code cleanup. 2017-09-14 17:40:02 +02:00
James Cole
761e9effae Fix tests 2017-09-14 17:34:22 +02:00
James Cole
e0f1211896 Update config to account for namespace. 2017-09-14 17:29:21 +02:00
James Cole
fc5494e7f4 Restore test env. file. 2017-09-14 17:10:33 +02:00
James Cole
45a05111e6 New translations firefly.php (Dutch) 2017-09-14 16:40:12 +02:00
James Cole
afe9d109b3 Small layout change [skip ci] 2017-09-14 16:13:25 +02:00
James Cole
768c7e53b4 Show message when locale is invalid. 2017-09-14 16:12:07 +02:00
James Cole
a20d9fa8f1 Add missing translations #843 2017-09-14 16:11:55 +02:00
James Cole
d60ae63153 New translations firefly.php (Polish) 2017-09-14 16:11:24 +02:00
James Cole
1a1c85b268 New translations firefly.php (Portuguese, Brazilian) 2017-09-14 16:11:20 +02:00
James Cole
dd3ddaa838 New translations firefly.php (Slovenian) 2017-09-14 16:11:16 +02:00
James Cole
56fcf73ce1 New translations firefly.php (Spanish) 2017-09-14 16:11:13 +02:00
James Cole
c9e7018490 Fix null pointer 2017-09-14 16:11:10 +02:00
James Cole
bc6a34bb47 New translations firefly.php (German) 2017-09-14 16:11:09 +02:00
James Cole
fcf350b06b New translations firefly.php (French) 2017-09-14 16:11:03 +02:00
James Cole
6c393fb8e0 New translations firefly.php (Dutch) 2017-09-14 16:10:57 +02:00
James Cole
d7ef5df8c3 New translations firefly.php (Russian) 2017-09-14 16:10:37 +02:00
James Cole
e250ffbd18 Add missing translations #843 2017-09-14 16:03:27 +02:00
James Cole
4b5f500dc1 Filter out opening balances. #839 2017-09-14 10:39:24 +02:00
James Cole
6d69832711 Extra big buttons for ##838 2017-09-14 10:32:58 +02:00
James Cole
233305ecb4 Change namespace of rules. 2017-09-13 07:49:58 +02:00
James Cole
78f9fbae40 New translations firefly.php (Polish) 2017-09-12 23:10:10 +02:00
James Cole
be46aa77f2 New translations firefly.php (Polish) 2017-09-12 22:41:07 +02:00
James Cole
e741ba2f65 New translations firefly.php (Portuguese, Brazilian) 2017-09-12 22:41:03 +02:00
James Cole
3203f7e1b7 New translations firefly.php (Slovenian) 2017-09-12 22:40:59 +02:00
James Cole
f4aa982247 New translations firefly.php (Spanish) 2017-09-12 22:40:55 +02:00
James Cole
27c1f1d0d5 New translations firefly.php (German) 2017-09-12 22:40:51 +02:00
James Cole
e291e32a29 New translations firefly.php (French) 2017-09-12 22:40:48 +02:00
James Cole
9072388dd0 New translations firefly.php (Dutch) 2017-09-12 22:40:44 +02:00
James Cole
5f4da0f6a4 New translations firefly.php (Russian) 2017-09-12 22:40:26 +02:00
James Cole
0583aa53a9 Fix typo [skip ci] #836 2017-09-12 22:30:48 +02:00
James Cole
1d3ace5f21 Fix for #835 2017-09-12 22:28:14 +02:00
James Cole
3e8fe70915 Update error handler. 2017-09-12 22:14:43 +02:00
James Cole
bf8ce5471e Fix bug in #836 2017-09-12 22:11:45 +02:00
James Cole
262f8a33c6 Fixed validation rules. 2017-09-12 21:44:31 +02:00
James Cole
4f934e54cf Easier upgrade, include FF version in JS 2017-09-12 19:59:07 +02:00
James Cole
158bf06efb Update version (is also a test) 2017-09-12 19:57:56 +02:00
James Cole
436017baee Introduce version to template. Rename Javascript URI 2017-09-12 19:57:41 +02:00
James Cole
05e55696bb New translations firefly.php (Polish) 2017-09-12 19:51:09 +02:00
James Cole
f825b5923c New translations firefly.php (Portuguese, Brazilian) 2017-09-12 19:51:06 +02:00
James Cole
9a9893236e New translations firefly.php (Slovenian) 2017-09-12 19:51:02 +02:00
James Cole
0ee843988f New translations firefly.php (Spanish) 2017-09-12 19:50:59 +02:00
James Cole
adf7e10879 New translations firefly.php (German) 2017-09-12 19:50:56 +02:00
James Cole
59e449c806 New translations firefly.php (French) 2017-09-12 19:50:52 +02:00
James Cole
cc05bfa181 New translations firefly.php (Dutch) 2017-09-12 19:50:49 +02:00
James Cole
b8c7aa68b4 New translations firefly.php (Russian) 2017-09-12 19:50:31 +02:00
James Cole
6e80b2f4c8 Update tests. 2017-09-12 19:47:29 +02:00
James Cole
ce205ab413 Various small fixes. 2017-09-12 18:24:42 +02:00
James Cole
626a9aac4b Update gitignore. 2017-09-12 18:24:19 +02:00
James Cole
73d85ca8c6 Update kernel so it works. 2017-09-12 18:24:12 +02:00
James Cole
96795fe197 New translations form.php (French) 2017-09-12 17:30:17 +02:00
James Cole
5cacf15322 New translations firefly.php (French) 2017-09-12 17:30:11 +02:00
James Cole
590ce971bf New translations firefly.php (French) 2017-09-12 17:20:12 +02:00
James Cole
7d5e93650b New translations firefly.php (French) 2017-09-12 15:20:12 +02:00
James Cole
561dc57c03 New translations firefly.php (French) 2017-09-12 15:10:14 +02:00
James Cole
625d626b25 New translations firefly.php (French) 2017-09-12 15:00:15 +02:00
James Cole
dcfec9bd89 New translations firefly.php (French) 2017-09-12 14:50:11 +02:00
James Cole
f1ff681b06 New translations firefly.php (French) 2017-09-12 14:40:14 +02:00
James Cole
9bc9aa0bb0 Add bcscale again. 2017-09-10 09:54:00 +02:00
James Cole
24ea20f769 Various changes to make things work again. 2017-09-10 09:46:50 +02:00
James Cole
1faa520168 Update composer files. 2017-09-10 08:43:03 +02:00
James Cole
7e30d761c5 No longer necessary 2017-09-10 08:42:48 +02:00
James Cole
750aa80b7c Updated docker example file. 2017-09-10 08:40:02 +02:00
James Cole
861941353b Update env example file. 2017-09-10 08:39:00 +02:00
James Cole
3fda7aa1e5 Update Kernel file to work with Laravel 5.5 2017-09-10 08:33:51 +02:00
James Cole
6f886e6eaa Changes required to make FF work again. 2017-09-10 08:30:27 +02:00
James Cole
9223f3ef71 Various updated files. 2017-09-09 22:32:11 +02:00
James Cole
6dbf4a3e49 New translations firefly.php (Polish) 2017-09-09 22:30:07 +02:00
James Cole
3b9b74b5ea Example test should point to /login 2017-09-09 22:11:33 +02:00
James Cole
418a6ab5ad This removes the bcscale thing which is very necessary. 2017-09-09 22:10:56 +02:00
James Cole
2268155994 Various files 2017-09-09 22:10:43 +02:00
James Cole
b219283d66 New validation thing is taking my namespace 2017-09-09 22:06:30 +02:00
James Cole
f077adaefd Separated providers. 2017-09-09 22:06:13 +02:00
James Cole
8823666aa9 CSRF middleware separated. 2017-09-09 22:03:54 +02:00
James Cole
ff9146ab91 Authentication in separate commit. 2017-09-09 22:03:27 +02:00
James Cole
c40be5299c Kernel middleware in separate commit. 2017-09-09 22:02:20 +02:00
James Cole
dcb2f45124 New translations firefly.php (Polish) 2017-09-09 22:00:55 +02:00
James Cole
f6322440cf New translations firefly.php (Portuguese, Brazilian) 2017-09-09 22:00:52 +02:00
James Cole
21e4108fd8 New translations firefly.php (Slovenian) 2017-09-09 22:00:49 +02:00
James Cole
8e33688268 New translations firefly.php (Spanish) 2017-09-09 22:00:47 +02:00
James Cole
a3fb2717cb New translations firefly.php (German) 2017-09-09 22:00:44 +02:00
James Cole
8017cf9d34 New translations firefly.php (French) 2017-09-09 22:00:41 +02:00
James Cole
8fe304e65b New translations firefly.php (Dutch) 2017-09-09 22:00:38 +02:00
James Cole
28485e461e New translations firefly.php (Russian) 2017-09-09 22:00:23 +02:00
James Cole
bf270745f0 Separate commit for error handler. 2017-09-09 21:57:45 +02:00
James Cole
d1e60cd546 First step towards Laravel 5.5 2017-09-09 21:57:24 +02:00
James Cole
834db4d02f New sentence for journal links. 2017-09-09 21:52:12 +02:00
James Cole
2f8d75eb73 Fix for #827 2017-09-09 18:44:05 +02:00
James Cole
53eef3fda7 Catch for #822 2017-09-09 18:37:47 +02:00
James Cole
0bcc010de8 Create link types when they do not exist in verify routine. #826 2017-09-09 18:36:17 +02:00
James Cole
b43bf35e98 Merge pull request #824 from DieBauer/823-dockerfile
Docker: Use working directory instead of hardcoded dist version
2017-09-09 18:22:59 +02:00
James Cole
769023e36c New translations firefly.php (Polish) 2017-09-09 17:20:07 +02:00
Jens Kat
2bf47f6d58 Use environment variable for install dir 2017-09-09 13:17:01 +02:00
Jens Kat
a3e1821ca0 Docker: Use working directory instead of hardcoded dist version
- By using the current (.) working directory, we can get the latest changes in the Docker image.
  If the building of Docker images is automated, it will automatically pick up the checked out version.
- Rearrange some Docker layers things that don't invalidate that much.
2017-09-09 12:51:37 +02:00
James Cole
dc1754bca7 New translations firefly.php (Polish) 2017-09-09 08:41:03 +02:00
James Cole
8879d76dd9 New translations firefly.php (Portuguese, Brazilian) 2017-09-09 08:41:01 +02:00
James Cole
cec99b83a0 New translations firefly.php (Slovenian) 2017-09-09 08:40:59 +02:00
James Cole
498873c208 New translations firefly.php (Spanish) 2017-09-09 08:40:56 +02:00
James Cole
80c8f131c8 New translations firefly.php (German) 2017-09-09 08:40:53 +02:00
James Cole
7344bd9054 New translations firefly.php (French) 2017-09-09 08:40:49 +02:00
James Cole
44b4e146eb New translations firefly.php (Dutch) 2017-09-09 08:40:45 +02:00
James Cole
e330eafc91 New translations form.php (Dutch) 2017-09-09 08:40:44 +02:00
James Cole
b9e7541cf6 New translations form.php (French) 2017-09-09 08:40:43 +02:00
James Cole
0d595d576a New translations list.php (French) 2017-09-09 08:40:41 +02:00
James Cole
ab602c98d9 New translations list.php (German) 2017-09-09 08:40:40 +02:00
James Cole
a0722fe022 New translations list.php (Polish) 2017-09-09 08:40:39 +02:00
James Cole
4454c0b911 New translations list.php (Portuguese, Brazilian) 2017-09-09 08:40:38 +02:00
James Cole
ae61064029 New translations list.php (Dutch) 2017-09-09 08:40:37 +02:00
James Cole
21168b8a49 New translations form.php (Spanish) 2017-09-09 08:40:36 +02:00
James Cole
077a3fb5a8 New translations form.php (German) 2017-09-09 08:40:35 +02:00
James Cole
8266cdba66 New translations form.php (Polish) 2017-09-09 08:40:34 +02:00
James Cole
aa0d3fd54c New translations form.php (Portuguese, Brazilian) 2017-09-09 08:40:32 +02:00
James Cole
86080ad871 New translations form.php (Slovenian) 2017-09-09 08:40:31 +02:00
James Cole
6b8144e8af New translations list.php (Slovenian) 2017-09-09 08:40:26 +02:00
James Cole
10ab561fbb New translations list.php (Spanish) 2017-09-09 08:40:24 +02:00
James Cole
5d3606c12d New translations firefly.php (Russian) 2017-09-09 08:40:23 +02:00
James Cole
e8d74bd735 New translations form.php (Russian) 2017-09-09 08:40:20 +02:00
James Cole
7c791d4fbf New translations list.php (Russian) 2017-09-09 08:40:19 +02:00
James Cole
ee2fba415a Remove unused translations. 2017-09-09 08:32:45 +02:00
James Cole
81bef28607 Merge branch 'release/4.6.5' 2017-09-09 07:21:53 +02:00
James Cole
d46ba4325f Updated composer file 2017-09-09 07:21:20 +02:00
James Cole
e044670c55 Merge pull request #789 from firefly-iii/l10n_develop
New Crowdin translations
2017-09-09 07:09:46 +02:00
James Cole
66c13f35e7 Various code cleanup. 2017-09-09 07:03:43 +02:00
James Cole
f2cb675267 New change log. [skip ci] 2017-09-09 06:57:03 +02:00
James Cole
6f9b69a032 Version upgrade. 2017-09-09 06:42:09 +02:00
James Cole
3a3eb4e84f Various code cleanup. 2017-09-09 06:41:45 +02:00
James Cole
c81955d84a New translations firefly.php (Dutch) 2017-09-09 06:30:07 +02:00
James Cole
0543733e3d Various code cleanup. 2017-09-09 06:28:21 +02:00
James Cole
336fb5f5a6 Fix #820 2017-09-09 06:25:20 +02:00
James Cole
6d592d45b0 New translations firefly.php (Polish) 2017-09-08 21:20:14 +02:00
James Cole
45d2467772 New translations firefly.php (Spanish) 2017-09-08 20:41:15 +02:00
James Cole
643248f9e4 New translations firefly.php (Slovenian) 2017-09-08 20:41:10 +02:00
James Cole
94b18798ed New translations firefly.php (Portuguese, Brazilian) 2017-09-08 20:41:07 +02:00
James Cole
4a18178a86 New translations firefly.php (Dutch) 2017-09-08 20:41:03 +02:00
James Cole
7bdde6822b New translations firefly.php (French) 2017-09-08 20:40:59 +02:00
James Cole
a118588fe7 New translations firefly.php (Polish) 2017-09-08 20:40:55 +02:00
James Cole
88bc81b9f5 New translations firefly.php (German) 2017-09-08 20:40:51 +02:00
James Cole
1af68843b0 New translations firefly.php (Russian) 2017-09-08 20:40:33 +02:00
James Cole
f704ade86b Fix #818 2017-09-08 20:37:46 +02:00
James Cole
2dff8aec69 Code for #819 2017-09-08 20:24:11 +02:00
James Cole
aae26c5da9 Can edit rule group #794 2017-09-08 20:12:55 +02:00
James Cole
2dbdcf73ed Possible fix for #724 2017-09-08 20:07:22 +02:00
James Cole
9960b063e7 New translations firefly.php (French) 2017-09-06 14:40:17 +02:00
James Cole
13834a276e New translations firefly.php (Dutch) 2017-09-06 08:50:12 +02:00
James Cole
a50945ad53 Fix #814 2017-09-05 20:50:19 +02:00
James Cole
068b9e388f New code for double transfer routine. #797 2017-09-05 06:43:33 +02:00
James Cole
6158288295 New translations firefly.php (German) 2017-09-03 21:00:07 +02:00
James Cole
b9fc298a0a New translations firefly.php (Polish) 2017-09-03 19:30:10 +02:00
James Cole
a697b0735f New translations firefly.php (Polish) 2017-09-03 19:20:09 +02:00
James Cole
6b82a8b29a New translations list.php (Dutch) 2017-09-03 18:30:44 +02:00
James Cole
158377a522 New translations list.php (French) 2017-09-03 18:30:43 +02:00
James Cole
3d32b8eb59 New translations list.php (German) 2017-09-03 18:30:34 +02:00
James Cole
9bc53c6644 New translations list.php (Polish) 2017-09-03 18:30:34 +02:00
James Cole
a1b9baae30 New translations list.php (Russian) 2017-09-03 18:30:28 +02:00
James Cole
6b6132b91b New translations validation.php (Russian) 2017-09-03 18:30:26 +02:00
James Cole
fdf26905c6 New translations list.php (Portuguese, Brazilian) 2017-09-03 18:30:22 +02:00
James Cole
8f3731dabe New translations list.php (Slovenian) 2017-09-03 18:30:21 +02:00
James Cole
e3521692ca New translations list.php (Spanish) 2017-09-03 18:30:19 +02:00
James Cole
dc8df37f5a New translations validation.php (Polish) 2017-09-03 18:30:17 +02:00
James Cole
141ae05cd6 New translations validation.php (Portuguese, Brazilian) 2017-09-03 18:30:16 +02:00
James Cole
584f4fb286 New translations validation.php (Slovenian) 2017-09-03 18:30:14 +02:00
James Cole
fdec8ab6a2 New translations validation.php (Spanish) 2017-09-03 18:30:13 +02:00
James Cole
3f79ffecaf New translations validation.php (German) 2017-09-03 18:30:12 +02:00
James Cole
5ee071fdc7 New translations validation.php (French) 2017-09-03 18:30:11 +02:00
James Cole
88e0985776 New translations validation.php (Dutch) 2017-09-03 18:30:08 +02:00
James Cole
a942313f85 Remove obsolete strings. 2017-09-03 18:20:08 +02:00
James Cole
f2446d46aa Code for #797 2017-09-03 18:19:58 +02:00
James Cole
78c8680300 Expand log for #797 2017-09-03 18:18:19 +02:00
James Cole
1cb979404b New translations form.php (Polish) 2017-09-03 17:00:09 +02:00
James Cole
44a017db99 New translations list.php (Polish) 2017-09-03 17:00:07 +02:00
James Cole
69a67ca977 New translations firefly.php (Polish) 2017-09-03 16:50:09 +02:00
James Cole
dd579cc19b New translations form.php (Polish) 2017-09-03 16:50:06 +02:00
James Cole
0346b09cb0 New translations firefly.php (Polish) 2017-09-03 16:40:07 +02:00
James Cole
eb15d2bbd8 New translations firefly.php (Polish) 2017-09-03 16:30:50 +02:00
James Cole
6a20f3113a New translations firefly.php (Polish) 2017-09-03 16:20:07 +02:00
James Cole
b4e8bb1e0f New translations firefly.php (Polish) 2017-09-03 16:10:09 +02:00
James Cole
83754960a6 Add messages for all levels. 2017-09-03 16:09:27 +02:00
James Cole
892f262261 Fix transaction controller tests 2017-09-03 16:06:37 +02:00
James Cole
0bccf0d734 New translations firefly.php (Polish) 2017-09-03 16:00:10 +02:00
James Cole
826dce324f New translations form.php (Polish) 2017-09-03 16:00:07 +02:00
James Cole
d9dad4387e Fix rule validation issues. 2017-09-03 15:57:13 +02:00
James Cole
62c4a9a7fc New translations firefly.php (Polish) 2017-09-03 15:50:06 +02:00
James Cole
386b069c83 New translations firefly.php (Polish) 2017-09-03 15:40:21 +02:00
James Cole
6a48c354b7 New translations firefly.php (Polish) 2017-09-03 15:30:07 +02:00
James Cole
ff0b1d0ec9 New translations firefly.php (Polish) 2017-09-03 15:20:09 +02:00
James Cole
ceaba5a11c New translations firefly.php (Polish) 2017-09-03 15:10:08 +02:00
James Cole
560bd6a92b New translations firefly.php (Polish) 2017-09-03 14:30:07 +02:00
James Cole
05103c0676 New translations firefly.php (Polish) 2017-09-03 14:20:07 +02:00
James Cole
88ea2aad28 New translations csv.php (Polish) 2017-09-03 14:10:06 +02:00
James Cole
55cd717df4 New translations demo.php (German) 2017-09-03 14:10:05 +02:00
James Cole
812e3d4a74 New translations firefly.php (Polish) 2017-09-03 14:00:17 +02:00
James Cole
5946e4b9b5 New translations firefly.php (German) 2017-09-03 14:00:14 +02:00
James Cole
ef54e0a845 New translations form.php (Polish) 2017-09-03 14:00:11 +02:00
James Cole
20597c5ee1 New translations help.php (German) 2017-09-03 14:00:09 +02:00
James Cole
057e76acd0 New translations breadcrumbs.php (Polish) 2017-09-03 14:00:08 +02:00
James Cole
3582d79530 New translations demo.php (German) 2017-09-03 14:00:07 +02:00
James Cole
1c72e742cf New translations validation.php (German) 2017-09-03 14:00:06 +02:00
James Cole
2ac582cd18 New translations firefly.php (German) 2017-09-03 13:50:08 +02:00
James Cole
e36302315c New translations form.php (German) 2017-09-03 13:50:06 +02:00
James Cole
e48d14e14a New translations firefly.php (German) 2017-09-03 13:40:10 +02:00
James Cole
608aa5c31e New translations firefly.php (Polish) 2017-09-03 13:40:07 +02:00
James Cole
533398115d New translations firefly.php (German) 2017-09-03 13:30:07 +02:00
James Cole
a8d69f850a New translations csv.php (German) 2017-09-03 13:20:08 +02:00
James Cole
98cb74e00c New translations firefly.php (German) 2017-09-03 13:20:07 +02:00
James Cole
49c5c9ba15 Include id in test. 2017-09-03 13:16:11 +02:00
James Cole
64979fd941 Add missing ID field. 2017-09-03 13:11:40 +02:00
James Cole
dccafee383 New translations firefly.php (German) 2017-09-03 13:10:07 +02:00
James Cole
0444ad5221 Debug message for #797 2017-09-03 13:02:19 +02:00
James Cole
693c6fb71b Debug message for #797 2017-09-03 13:00:36 +02:00
James Cole
d5bcaf42ac New translations firefly.php (German) 2017-09-03 13:00:07 +02:00
James Cole
b002635d1b Fixes #809 2017-09-03 12:56:45 +02:00
James Cole
19e3a10a28 Fixed #801 2017-09-03 12:50:29 +02:00
James Cole
1d87da7745 Fix nullpointer 2017-09-03 11:13:45 +02:00
James Cole
0840883546 New translations firefly.php (Spanish) 2017-09-03 11:10:53 +02:00
James Cole
9d283b85e2 New translations firefly.php (Slovenian) 2017-09-03 11:10:49 +02:00
James Cole
f031b6fa3f New translations firefly.php (Portuguese, Brazilian) 2017-09-03 11:10:47 +02:00
James Cole
4b03bc92c0 New translations firefly.php (Dutch) 2017-09-03 11:10:44 +02:00
James Cole
487c81eeb2 New translations firefly.php (French) 2017-09-03 11:10:41 +02:00
James Cole
26f71400e9 New translations firefly.php (Polish) 2017-09-03 11:10:39 +02:00
James Cole
daeb06ede8 New translations firefly.php (German) 2017-09-03 11:10:36 +02:00
James Cole
fe9705d33e New translations firefly.php (Russian) 2017-09-03 11:10:24 +02:00
James Cole
25ea1c8f5f Add text for empty box #800 2017-09-03 11:02:18 +02:00
James Cole
80a2fd485e New translations firefly.php (Spanish) 2017-09-03 11:00:54 +02:00
James Cole
18f8b102c3 New translations firefly.php (Slovenian) 2017-09-03 11:00:50 +02:00
James Cole
b99c8dd32a New translations firefly.php (Portuguese, Brazilian) 2017-09-03 11:00:47 +02:00
James Cole
52f1d96cfb New translations firefly.php (Dutch) 2017-09-03 11:00:44 +02:00
James Cole
c143d54c97 New translations firefly.php (French) 2017-09-03 11:00:41 +02:00
James Cole
ac3881779c New translations firefly.php (Polish) 2017-09-03 11:00:38 +02:00
James Cole
65e0700f2c New translations firefly.php (German) 2017-09-03 11:00:36 +02:00
James Cole
733cee5c8c New translations firefly.php (Russian) 2017-09-03 11:00:23 +02:00
James Cole
6b09466819 Implement #803 2017-09-03 10:51:02 +02:00
James Cole
b29c0f9d74 New translations auth.php (Dutch) 2017-09-03 10:42:27 +02:00
James Cole
5d239b896c New translations firefly.php (Spanish) 2017-09-03 10:42:26 +02:00
James Cole
52770a970b New translations form.php (French) 2017-09-03 10:42:23 +02:00
James Cole
bbf923b849 New translations form.php (German) 2017-09-03 10:42:21 +02:00
James Cole
d735c5d10b New translations firefly.php (Slovenian) 2017-09-03 10:42:20 +02:00
James Cole
2417224991 New translations firefly.php (Portuguese, Brazilian) 2017-09-03 10:42:18 +02:00
James Cole
d515bda868 New translations csv.php (Spanish) 2017-09-03 10:42:14 +02:00
James Cole
8e332119e3 New translations firefly.php (Dutch) 2017-09-03 10:42:13 +02:00
James Cole
5ac3dccb37 New translations firefly.php (French) 2017-09-03 10:42:11 +02:00
James Cole
e9354e1b6a New translations firefly.php (Polish) 2017-09-03 10:42:08 +02:00
James Cole
8700393e61 New translations firefly.php (German) 2017-09-03 10:42:06 +02:00
James Cole
8d76eaf633 New translations form.php (Polish) 2017-09-03 10:42:04 +02:00
James Cole
99b6eb3cd9 New translations form.php (Portuguese, Brazilian) 2017-09-03 10:42:02 +02:00
James Cole
36ffa46441 New translations help.php (Slovenian) 2017-09-03 10:42:01 +02:00
James Cole
d110fea710 New translations help.php (Spanish) 2017-09-03 10:41:59 +02:00
James Cole
09bd94d44e New translations list.php (Dutch) 2017-09-03 10:41:58 +02:00
James Cole
3b8b45d12d New translations list.php (French) 2017-09-03 10:41:57 +02:00
James Cole
39045fe2fc New translations help.php (Portuguese, Brazilian) 2017-09-03 10:41:56 +02:00
James Cole
b7e7c82bd7 New translations help.php (Polish) 2017-09-03 10:41:55 +02:00
James Cole
473eeaa206 New translations form.php (Slovenian) 2017-09-03 10:41:54 +02:00
James Cole
36b93d6d2b New translations help.php (Dutch) 2017-09-03 10:41:52 +02:00
James Cole
f24feb62c8 New translations help.php (German) 2017-09-03 10:41:51 +02:00
James Cole
69b82a5043 New translations help.php (French) 2017-09-03 10:41:50 +02:00
James Cole
547db2f27b New translations csv.php (Slovenian) 2017-09-03 10:41:48 +02:00
James Cole
6b6599eb79 New translations csv.php (Portuguese, Brazilian) 2017-09-03 10:41:47 +02:00
James Cole
fcad295809 New translations breadcrumbs.php (German) 2017-09-03 10:41:45 +02:00
James Cole
9a1e3701a3 New translations breadcrumbs.php (Polish) 2017-09-03 10:41:44 +02:00
James Cole
ba3b82cc87 New translations breadcrumbs.php (Portuguese, Brazilian) 2017-09-03 10:41:43 +02:00
James Cole
c768949034 New translations breadcrumbs.php (Dutch) 2017-09-03 10:41:42 +02:00
James Cole
4749c854bc New translations auth.php (Spanish) 2017-09-03 10:41:41 +02:00
James Cole
3887231051 New translations auth.php (French) 2017-09-03 10:41:40 +02:00
James Cole
3078adac2d New translations auth.php (German) 2017-09-03 10:41:39 +02:00
James Cole
ec40d91f85 New translations auth.php (Polish) 2017-09-03 10:41:38 +02:00
James Cole
399cb3bc3f New translations auth.php (Slovenian) 2017-09-03 10:41:37 +02:00
James Cole
fe2bba2c40 New translations auth.php (Portuguese, Brazilian) 2017-09-03 10:41:35 +02:00
James Cole
2bbdd76ee1 New translations breadcrumbs.php (Slovenian) 2017-09-03 10:41:34 +02:00
James Cole
a8ace43470 New translations breadcrumbs.php (Spanish) 2017-09-03 10:41:33 +02:00
James Cole
9c5c5b56ef New translations csv.php (Dutch) 2017-09-03 10:41:32 +02:00
James Cole
109b9000d2 New translations csv.php (French) 2017-09-03 10:41:30 +02:00
James Cole
2194cd9da1 New translations csv.php (German) 2017-09-03 10:41:27 +02:00
James Cole
ac2834954c New translations csv.php (Polish) 2017-09-03 10:41:26 +02:00
James Cole
136043bb23 New translations config.php (Spanish) 2017-09-03 10:41:24 +02:00
James Cole
459c0fc136 New translations config.php (Slovenian) 2017-09-03 10:41:23 +02:00
James Cole
22ab01c9ff New translations config.php (Dutch) 2017-09-03 10:41:22 +02:00
James Cole
cb7466247c New translations config.php (French) 2017-09-03 10:41:21 +02:00
James Cole
a87b1fca1b New translations config.php (German) 2017-09-03 10:41:20 +02:00
James Cole
0d4b971bd0 New translations config.php (Portuguese, Brazilian) 2017-09-03 10:41:18 +02:00
James Cole
2b6fe7cae7 New translations config.php (Polish) 2017-09-03 10:41:18 +02:00
James Cole
beb1ac4c9d New translations list.php (German) 2017-09-03 10:41:16 +02:00
James Cole
923cdcde16 New translations list.php (Polish) 2017-09-03 10:41:15 +02:00
James Cole
4ff4ca642c New translations csv.php (Russian) 2017-09-03 10:41:14 +02:00
James Cole
a968525d3f New translations firefly.php (Russian) 2017-09-03 10:41:12 +02:00
James Cole
f73a23db97 New translations form.php (Russian) 2017-09-03 10:41:09 +02:00
James Cole
4437cb67b9 New translations help.php (Russian) 2017-09-03 10:41:08 +02:00
James Cole
abfb47674c New translations config.php (Russian) 2017-09-03 10:41:06 +02:00
James Cole
f4deaf78e7 New translations breadcrumbs.php (Russian) 2017-09-03 10:41:05 +02:00
James Cole
38f588da1d New translations demo.php (Polish) 2017-09-03 10:41:04 +02:00
James Cole
d7be6fc9f6 New translations demo.php (Portuguese, Brazilian) 2017-09-03 10:41:02 +02:00
James Cole
dd4b640424 New translations demo.php (Slovenian) 2017-09-03 10:41:01 +02:00
James Cole
ffbe400e33 New translations auth.php (Russian) 2017-09-03 10:41:00 +02:00
James Cole
533ea67278 New translations demo.php (Spanish) 2017-09-03 10:40:59 +02:00
James Cole
9ad0bea76d New translations list.php (Russian) 2017-09-03 10:40:57 +02:00
James Cole
7d6bc09f18 New translations pagination.php (Russian) 2017-09-03 10:40:56 +02:00
James Cole
40a8a5a8e7 New translations intro.php (Portuguese, Brazilian) 2017-09-03 10:40:55 +02:00
James Cole
47c0a2cf03 New translations intro.php (Russian) 2017-09-03 10:40:54 +02:00
James Cole
2c787dd96d New translations intro.php (Slovenian) 2017-09-03 10:40:53 +02:00
James Cole
de340130b8 New translations intro.php (Polish) 2017-09-03 10:40:51 +02:00
James Cole
abc71e4cd6 New translations intro.php (German) 2017-09-03 10:40:50 +02:00
James Cole
444c2af5b0 New translations passwords.php (Russian) 2017-09-03 10:40:49 +02:00
James Cole
07277b7282 New translations validation.php (Russian) 2017-09-03 10:40:47 +02:00
James Cole
41f1bb1dbd New translations demo.php (Russian) 2017-09-03 10:40:45 +02:00
James Cole
ee337b9476 New translations intro.php (Dutch) 2017-09-03 10:40:44 +02:00
James Cole
1cbe63e293 New translations demo.php (German) 2017-09-03 10:40:42 +02:00
James Cole
eae3bf4d0e New translations demo.php (French) 2017-09-03 10:40:42 +02:00
James Cole
7502497827 New translations pagination.php (Portuguese, Brazilian) 2017-09-03 10:40:40 +02:00
James Cole
a66541fd04 New translations pagination.php (Slovenian) 2017-09-03 10:40:38 +02:00
James Cole
522d99477c New translations pagination.php (Spanish) 2017-09-03 10:40:37 +02:00
James Cole
3a4869205d New translations passwords.php (Dutch) 2017-09-03 10:40:36 +02:00
James Cole
5ae49e8e3e New translations pagination.php (Polish) 2017-09-03 10:40:35 +02:00
James Cole
915321db61 New translations pagination.php (German) 2017-09-03 10:40:34 +02:00
James Cole
bcd5b580cb New translations list.php (Portuguese, Brazilian) 2017-09-03 10:40:32 +02:00
James Cole
70226a24c9 New translations list.php (Slovenian) 2017-09-03 10:40:30 +02:00
James Cole
dd4995e02b New translations list.php (Spanish) 2017-09-03 10:40:29 +02:00
James Cole
46d3b70154 New translations pagination.php (French) 2017-09-03 10:40:28 +02:00
James Cole
540c03670b New translations pagination.php (Dutch) 2017-09-03 10:40:27 +02:00
James Cole
8037e4a4c4 New translations passwords.php (French) 2017-09-03 10:40:26 +02:00
James Cole
15a13be329 New translations passwords.php (German) 2017-09-03 10:40:24 +02:00
James Cole
9509825552 New translations validation.php (Polish) 2017-09-03 10:40:23 +02:00
James Cole
e46ef2f92c New translations validation.php (Portuguese, Brazilian) 2017-09-03 10:40:22 +02:00
James Cole
dc21afe14a New translations validation.php (Slovenian) 2017-09-03 10:40:21 +02:00
James Cole
7667c0fa4a New translations demo.php (Dutch) 2017-09-03 10:40:20 +02:00
James Cole
7f747cd4ef New translations validation.php (Spanish) 2017-09-03 10:40:18 +02:00
James Cole
1e3693101b New translations validation.php (German) 2017-09-03 10:40:17 +02:00
James Cole
d31640734c New translations validation.php (French) 2017-09-03 10:40:16 +02:00
James Cole
ce3478041a New translations passwords.php (Polish) 2017-09-03 10:40:15 +02:00
James Cole
ad2752a62c New translations passwords.php (Portuguese, Brazilian) 2017-09-03 10:40:13 +02:00
James Cole
d29ebdbf26 New translations passwords.php (Slovenian) 2017-09-03 10:40:12 +02:00
James Cole
491b3547b5 New translations validation.php (Dutch) 2017-09-03 10:40:11 +02:00
James Cole
71cb8fe038 New translations passwords.php (Spanish) 2017-09-03 10:40:10 +02:00
James Cole
816b291ed3 Code for #805 2017-09-03 10:39:05 +02:00
James Cole
b9f6119c68 Fix rule title. 2017-09-03 10:38:41 +02:00
James Cole
c87d7458fc New lines for triggers. 2017-09-03 10:16:53 +02:00
James Cole
aed5ef3fba Sort triggers and actions 2017-09-03 10:16:45 +02:00
James Cole
523824225e Fix test coverage 2017-09-03 10:09:27 +02:00
James Cole
2a2a18f378 Add new triggers 2017-09-03 10:09:10 +02:00
James Cole
c29fb13941 Commit changes. 2017-09-03 10:08:56 +02:00
James Cole
30549da044 Merge pull request #806 from pkoziol/develop
Fix formatting when currency symbol is separated and follows amount
2017-09-03 09:45:21 +02:00
James Cole
e81775fbce Merge pull request #807 from pkoziol/issue-799
Fix reseting action type when editing rule
2017-09-03 09:45:07 +02:00
James Cole
e7520a82c4 Merge pull request #808 from pkoziol/issue-798
Fix search that worked only for lowercase queries
2017-09-03 09:44:43 +02:00
James Cole
cf0e089616 New translations firefly.php (French) 2017-09-02 22:10:14 +02:00
James Cole
df8207bd9f New translations firefly.php (French) 2017-09-02 22:00:18 +02:00
James Cole
d65d555d63 New translations intro.php (French) 2017-09-02 22:00:15 +02:00
James Cole
159920296a New translations breadcrumbs.php (French) 2017-09-02 22:00:14 +02:00
James Cole
bfd7e009cc New translations intro.php (French) 2017-09-02 21:50:06 +02:00
koziolek
682f9283a6 Fix search that worked only for lowercase queries
firefly-iii/firefly-iii#798
2017-09-02 20:38:56 +02:00
koziolek
bbe8a97945 Fix reseting action type when editing rule
firefly-iii/firefly-iii#799
2017-09-02 20:30:55 +02:00
koziolek
f93d11643f Fix formatting when currency symbol is separated and follows amount 2017-09-02 20:11:37 +02:00
James Cole
78bae33433 Remove experimental multi period thing. 2017-09-02 07:40:39 +02:00
James Cole
7cab89a291 Remove experimental multi period thing. 2017-09-02 07:40:05 +02:00
James Cole
95e91b9af8 Fix tests 2017-09-01 21:54:17 +02:00
James Cole
5e08461385 Fix broken dev installation. 2017-09-01 21:22:55 +02:00
James Cole
632d95f1fb Should fix rule, category and other name checks. #793 2017-09-01 11:20:51 +02:00
James Cole
edd1b25330 Revert "Should fix rule, category and other name checks. #793"
This reverts commit ffaf48dda7.
2017-09-01 11:19:49 +02:00
Dorigo
ffaf48dda7 Should fix rule, category and other name checks. #793 2017-09-01 11:15:36 +02:00
James Cole
0e465ade48 Merge pull request #792 from jleeong/master
Fixing Dockerization of application
2017-09-01 08:48:11 +02:00
James Cole
ab80803f0f Fix order for bills. 2017-09-01 06:28:26 +02:00
jleeong
88d3db4dc8 Fixed dockerization 2017-08-31 12:05:43 -07:00
James Cole
da4dbb7319 New translations form.php (Spanish) 2017-08-31 17:10:14 +02:00
James Cole
808b405dd6 New translations intro.php (Spanish) 2017-08-31 17:10:12 +02:00
James Cole
a429aaa6fd New translations intro.php (Spanish) 2017-08-31 17:00:08 +02:00
James Cole
8db9641480 Experimental multi-budget overview. 2017-08-31 07:29:23 +02:00
James Cole
8dec769d64 Add newlines to files [skip ci] 2017-08-31 06:47:18 +02:00
James Cole
06ad377729 New translations form.php (Dutch) 2017-08-31 06:20:07 +02:00
James Cole
569f736831 Merge pull request #778 from firefly-iii/l10n_develop
New Crowdin translations
2017-08-31 06:07:31 +02:00
James Cole
7702ed027b Expand view for #780 2017-08-30 07:40:39 +02:00
James Cole
7c068afe05 New translations form.php (Dutch) 2017-08-30 07:21:13 +02:00
James Cole
211d136b7a New translations form.php (French) 2017-08-30 07:21:12 +02:00
James Cole
434e0653fe New translations form.php (German) 2017-08-30 07:21:10 +02:00
James Cole
cb134a7e13 New translations form.php (Polish) 2017-08-30 07:20:51 +02:00
James Cole
08db90f606 New translations form.php (Portuguese, Brazilian) 2017-08-30 07:20:49 +02:00
James Cole
964d552d28 New translations list.php (Dutch) 2017-08-30 07:20:47 +02:00
James Cole
40d3d9906a New translations list.php (French) 2017-08-30 07:20:46 +02:00
James Cole
122467799f New translations form.php (Slovenian) 2017-08-30 07:20:45 +02:00
James Cole
b1ca56a296 New translations form.php (Spanish) 2017-08-30 07:20:43 +02:00
James Cole
cb3504642c New translations list.php (German) 2017-08-30 07:20:34 +02:00
James Cole
a8f10bbb09 New translations list.php (Polish) 2017-08-30 07:20:33 +02:00
James Cole
b75849d4ab New translations form.php (Russian) 2017-08-30 07:20:30 +02:00
James Cole
0c88bea772 New translations list.php (Russian) 2017-08-30 07:20:26 +02:00
James Cole
7aaddf2a60 New translations list.php (Portuguese, Brazilian) 2017-08-30 07:20:19 +02:00
James Cole
35d6db5e73 New translations list.php (Slovenian) 2017-08-30 07:20:17 +02:00
James Cole
6642e93581 New translations list.php (Spanish) 2017-08-30 07:20:16 +02:00
James Cole
4aaacf8e2e Ask for CC number when asset is a CC. #784 2017-08-30 07:14:35 +02:00
James Cole
0a8e6e9f07 Code for #784 2017-08-30 07:10:06 +02:00
James Cole
062272a6e8 Format translations [skip ci] 2017-08-30 07:09:52 +02:00
James Cole
d610302e79 Code for #782 2017-08-30 07:00:17 +02:00
James Cole
69846bfb18 New translations firefly.php (Spanish) 2017-08-29 09:50:10 +02:00
James Cole
c4bca4c214 New translations firefly.php (Spanish) 2017-08-29 09:40:13 +02:00
James Cole
14a8c686c0 New translations firefly.php (Spanish) 2017-08-29 09:30:09 +02:00
James Cole
c6cc750166 New translations firefly.php (Spanish) 2017-08-29 09:20:12 +02:00
James Cole
3cce84dfa7 New translations firefly.php (Spanish) 2017-08-28 19:00:14 +02:00
James Cole
c8f4c6bd49 New translations form.php (Spanish) 2017-08-28 19:00:12 +02:00
James Cole
17501c6cad New translations help.php (Spanish) 2017-08-28 18:50:05 +02:00
James Cole
aa64e7947e New translations help.php (Spanish) 2017-08-28 18:40:07 +02:00
James Cole
9adfbf1668 New translations csv.php (Spanish) 2017-08-28 18:40:06 +02:00
James Cole
c6f2d4a0c4 New translations list.php (Spanish) 2017-08-28 18:30:08 +02:00
James Cole
4b7fc7b80b New translations breadcrumbs.php (Spanish) 2017-08-28 18:20:07 +02:00
James Cole
5c30146ee0 New translations firefly.php (German) 2017-08-28 13:30:12 +02:00
James Cole
28af10444d New translations form.php (German) 2017-08-28 13:30:09 +02:00
James Cole
a6f0faa058 New translations list.php (German) 2017-08-28 13:30:07 +02:00
James Cole
b6227e633c Fix tests 2017-08-27 11:07:14 +02:00
James Cole
47dd8610c6 New translations breadcrumbs.php (Russian) 2017-08-27 11:00:05 +02:00
James Cole
6ffdbcafc5 New translations csv.php (German) 2017-08-27 09:20:06 +02:00
James Cole
d89f45d534 New translations validation.php (German) 2017-08-27 09:20:05 +02:00
James Cole
f014828423 New translations csv.php (German) 2017-08-27 09:10:10 +02:00
James Cole
f26c672421 New translations breadcrumbs.php (German) 2017-08-27 09:10:08 +02:00
James Cole
b1b9804aca New translations firefly.php (German) 2017-08-27 09:10:06 +02:00
James Cole
5c2c947785 New translations firefly.php (Dutch) 2017-08-27 09:00:07 +02:00
James Cole
1319cb2e4e Improving bunq import. 2017-08-27 08:54:58 +02:00
James Cole
1ecf3d04d9 Fix attachment count 2017-08-27 08:53:48 +02:00
James Cole
b8d4776671 Remove unused code. 2017-08-26 21:28:14 +02:00
James Cole
43b829bf02 New translations firefly.php (Spanish) 2017-08-26 15:02:58 +02:00
James Cole
6c150f9d06 New translations firefly.php (Slovenian) 2017-08-26 15:02:54 +02:00
James Cole
bf818e1ede New translations firefly.php (Portuguese, Brazilian) 2017-08-26 15:02:51 +02:00
James Cole
4022b6b9cd New translations firefly.php (Dutch) 2017-08-26 15:02:48 +02:00
James Cole
ab5ff6446e New translations firefly.php (French) 2017-08-26 15:02:46 +02:00
James Cole
ef4bc0ca0c New translations firefly.php (Polish) 2017-08-26 15:02:44 +02:00
James Cole
07e31d6745 New translations firefly.php (German) 2017-08-26 15:02:42 +02:00
James Cole
e0bcbb0396 New translations firefly.php (Russian) 2017-08-26 15:00:20 +02:00
James Cole
6a5bdebb7c New translations firefly.php (Spanish) 2017-08-26 14:52:56 +02:00
James Cole
bfcc1d8f03 New translations firefly.php (Slovenian) 2017-08-26 14:52:53 +02:00
James Cole
eed6d6c49d New translations firefly.php (Portuguese, Brazilian) 2017-08-26 14:52:50 +02:00
James Cole
cf05970ccf New translations firefly.php (Dutch) 2017-08-26 14:52:47 +02:00
James Cole
fa6e82dd25 New translations firefly.php (French) 2017-08-26 14:52:45 +02:00
James Cole
16aaa0b5a6 New translations firefly.php (Polish) 2017-08-26 14:52:43 +02:00
James Cole
70e146aedd New translations firefly.php (German) 2017-08-26 14:52:40 +02:00
James Cole
338d7587b2 New translations firefly.php (Russian) 2017-08-26 14:50:21 +02:00
James Cole
50837af607 Expand tag view. 2017-08-26 14:50:08 +02:00
James Cole
989e931edf Add language string [skip ci] 2017-08-26 14:44:19 +02:00
James Cole
9238efbd3a Fix tag cloud 2017-08-26 14:44:05 +02:00
James Cole
ea2af2378d Expand budget pages to work with new date view. 2017-08-26 14:30:41 +02:00
James Cole
094ddfcf5f Fix rounding for amounts. 2017-08-26 10:01:48 +02:00
James Cole
7329098ed8 Fix rounding for amounts. 2017-08-26 10:00:08 +02:00
James Cole
0f229e4d7b Improved extraction of bunq data. 2017-08-26 06:21:22 +02:00
James Cole
b08eccd076 New translations firefly.php (French) 2017-08-25 18:30:07 +02:00
James Cole
4e6e7c0562 New translations firefly.php (Dutch) 2017-08-25 16:30:41 +02:00
James Cole
eb331104df New translations firefly.php (Spanish) 2017-08-25 16:11:01 +02:00
James Cole
d6b664375e New translations firefly.php (Slovenian) 2017-08-25 16:10:56 +02:00
James Cole
90c4f449e8 New translations firefly.php (Portuguese, Brazilian) 2017-08-25 16:10:53 +02:00
James Cole
d5e8f5810d New translations firefly.php (Dutch) 2017-08-25 16:10:50 +02:00
James Cole
6215ec8cf6 New translations firefly.php (French) 2017-08-25 16:10:48 +02:00
James Cole
f484785395 New translations firefly.php (Polish) 2017-08-25 16:10:45 +02:00
James Cole
4eb93dd139 New translations firefly.php (German) 2017-08-25 16:10:42 +02:00
James Cole
2da3f74057 New translations firefly.php (Russian) 2017-08-25 16:10:25 +02:00
James Cole
4b2abb6f25 Add ability to translate links. 2017-08-25 16:03:36 +02:00
James Cole
c38429d3a3 New translations firefly.php (Slovenian) 2017-08-25 07:37:27 +02:00
James Cole
d78a5d1225 New translations firefly.php (Spanish) 2017-08-25 07:37:25 +02:00
James Cole
907ff89609 New translations form.php (Chinese Traditional) 2017-08-25 07:37:23 +02:00
James Cole
7758dcaaba New translations firefly.php (Portuguese, Brazilian) 2017-08-25 07:37:20 +02:00
James Cole
ed6da918e1 New translations firefly.php (Polish) 2017-08-25 07:37:18 +02:00
James Cole
30373db89c New translations csv.php (Spanish) 2017-08-25 07:37:16 +02:00
James Cole
7e032fdbb3 New translations firefly.php (Chinese Traditional) 2017-08-25 07:37:15 +02:00
James Cole
d232a7abbb New translations firefly.php (German) 2017-08-25 07:37:11 +02:00
James Cole
6b6b9ae242 New translations firefly.php (French) 2017-08-25 07:37:08 +02:00
James Cole
241bcce6c1 New translations form.php (German) 2017-08-25 07:37:06 +02:00
James Cole
f490d9ebe8 New translations form.php (Polish) 2017-08-25 07:37:04 +02:00
James Cole
fb09843e5a New translations help.php (Slovenian) 2017-08-25 07:37:03 +02:00
James Cole
ab95698181 New translations help.php (Spanish) 2017-08-25 07:37:02 +02:00
James Cole
28b3134ae2 New translations list.php (Chinese Traditional) 2017-08-25 07:37:01 +02:00
James Cole
ec47c9cd00 New translations form.php (Slovenian) 2017-08-25 07:36:59 +02:00
James Cole
5e062908a5 New translations form.php (Portuguese, Brazilian) 2017-08-25 07:36:58 +02:00
James Cole
d0cefd7005 New translations form.php (Spanish) 2017-08-25 07:36:57 +02:00
James Cole
c1276e789a New translations csv.php (Slovenian) 2017-08-25 07:36:54 +02:00
James Cole
7ac4cd4665 New translations csv.php (Portuguese, Brazilian) 2017-08-25 07:36:54 +02:00
James Cole
1797bf8108 New translations breadcrumbs.php (French) 2017-08-25 07:36:52 +02:00
James Cole
8c32e619cb New translations breadcrumbs.php (German) 2017-08-25 07:36:51 +02:00
James Cole
a0d800bbb9 New translations breadcrumbs.php (Portuguese, Brazilian) 2017-08-25 07:36:50 +02:00
James Cole
0f276f10ee New translations breadcrumbs.php (Polish) 2017-08-25 07:36:49 +02:00
James Cole
473c6aad84 New translations breadcrumbs.php (Chinese Traditional) 2017-08-25 07:36:48 +02:00
James Cole
f9b60fef85 New translations breadcrumbs.php (Slovenian) 2017-08-25 07:36:46 +02:00
James Cole
f7ea140018 New translations breadcrumbs.php (Spanish) 2017-08-25 07:36:44 +02:00
James Cole
0287416aa5 New translations csv.php (Chinese Traditional) 2017-08-25 07:36:43 +02:00
James Cole
0dfcfbb97e New translations csv.php (Polish) 2017-08-25 07:36:41 +02:00
James Cole
d82c386402 New translations csv.php (German) 2017-08-25 07:36:40 +02:00
James Cole
3c3a32b1fa New translations config.php (Chinese Traditional) 2017-08-25 07:36:39 +02:00
James Cole
8e2f78226a New translations list.php (German) 2017-08-25 07:36:36 +02:00
James Cole
617360c631 New translations breadcrumbs.php (Russian) 2017-08-25 07:36:35 +02:00
James Cole
0f2bd34a62 New translations csv.php (Russian) 2017-08-25 07:36:34 +02:00
James Cole
23a028f011 New translations form.php (Russian) 2017-08-25 07:36:33 +02:00
James Cole
6c8da850a7 New translations firefly.php (Russian) 2017-08-25 07:36:31 +02:00
James Cole
1bf5ae2d3d New translations demo.php (Polish) 2017-08-25 07:36:28 +02:00
James Cole
37a25625de New translations demo.php (Slovenian) 2017-08-25 07:36:27 +02:00
James Cole
206887bc71 New translations list.php (Russian) 2017-08-25 07:36:25 +02:00
James Cole
1e8551da4a New translations intro.php (Polish) 2017-08-25 07:36:24 +02:00
James Cole
6dd88d25dd New translations intro.php (Portuguese, Brazilian) 2017-08-25 07:36:23 +02:00
James Cole
81089e989b New translations intro.php (Russian) 2017-08-25 07:36:22 +02:00
James Cole
8a4355e786 New translations intro.php (Spanish) 2017-08-25 07:36:21 +02:00
James Cole
20947bc8c1 New translations intro.php (Slovenian) 2017-08-25 07:36:20 +02:00
James Cole
da0436c60e New translations intro.php (German) 2017-08-25 07:36:18 +02:00
James Cole
04af43a9fa New translations intro.php (French) 2017-08-25 07:36:17 +02:00
James Cole
9a2d87eb42 New translations validation.php (Russian) 2017-08-25 07:36:15 +02:00
James Cole
cb66925f22 New translations demo.php (Russian) 2017-08-25 07:36:14 +02:00
James Cole
c7b6688250 New translations intro.php (Chinese Traditional) 2017-08-25 07:36:13 +02:00
James Cole
129dacbfe2 New translations demo.php (Chinese Traditional) 2017-08-25 07:36:12 +02:00
James Cole
568ef92f79 New translations list.php (Portuguese, Brazilian) 2017-08-25 07:36:09 +02:00
James Cole
75671dc982 New translations list.php (Polish) 2017-08-25 07:36:02 +02:00
James Cole
4d55dbea6c New translations list.php (Slovenian) 2017-08-25 07:36:01 +02:00
James Cole
67b7f90c26 New translations list.php (Spanish) 2017-08-25 07:35:59 +02:00
James Cole
3efd112d8b New translations validation.php (German) 2017-08-25 07:35:58 +02:00
James Cole
df5830b5f9 New translations validation.php (Portuguese, Brazilian) 2017-08-25 07:35:56 +02:00
James Cole
a6d8b985b2 New translations validation.php (Slovenian) 2017-08-25 07:35:54 +02:00
James Cole
e76a6dc00f New translations validation.php (Chinese Traditional) 2017-08-25 07:35:52 +02:00
James Cole
77ee046b3f New translations firefly.php (Slovenian) 2017-08-25 07:08:15 +02:00
James Cole
464f86eb1d New translations firefly.php (Spanish) 2017-08-25 07:08:13 +02:00
James Cole
b9bbd2872e New translations form.php (Chinese Traditional) 2017-08-25 07:08:10 +02:00
James Cole
7a70b8234c New translations firefly.php (Portuguese, Brazilian) 2017-08-25 07:08:08 +02:00
James Cole
e6bf9faa3e New translations firefly.php (Polish) 2017-08-25 07:08:05 +02:00
James Cole
ede7b1b35c New translations csv.php (Spanish) 2017-08-25 07:08:02 +02:00
James Cole
6c095d8efa New translations firefly.php (Chinese Traditional) 2017-08-25 07:08:00 +02:00
James Cole
95bb8fa6ec New translations firefly.php (German) 2017-08-25 07:07:57 +02:00
James Cole
bbe8fff1e6 New translations firefly.php (French) 2017-08-25 07:07:54 +02:00
James Cole
5dc4cf4c17 New translations form.php (German) 2017-08-25 07:07:51 +02:00
James Cole
5b135ada24 New translations form.php (Polish) 2017-08-25 07:07:50 +02:00
James Cole
65b3dab916 New translations help.php (Slovenian) 2017-08-25 07:07:49 +02:00
James Cole
e2643ead1a New translations help.php (Spanish) 2017-08-25 07:07:48 +02:00
James Cole
0dcfddc169 New translations list.php (Chinese Traditional) 2017-08-25 07:07:47 +02:00
James Cole
b36589b2e6 New translations form.php (Slovenian) 2017-08-25 07:07:45 +02:00
James Cole
57bea64ad4 New translations form.php (Portuguese, Brazilian) 2017-08-25 07:07:44 +02:00
James Cole
5b5bbd29c3 New translations form.php (Spanish) 2017-08-25 07:07:43 +02:00
James Cole
e80822f1c5 New translations csv.php (Slovenian) 2017-08-25 07:07:41 +02:00
James Cole
c7978150c4 New translations csv.php (Portuguese, Brazilian) 2017-08-25 07:07:39 +02:00
James Cole
70ed0af475 New translations breadcrumbs.php (French) 2017-08-25 07:07:38 +02:00
James Cole
57d196fdce New translations breadcrumbs.php (German) 2017-08-25 07:07:37 +02:00
James Cole
8dd61e1f86 New translations breadcrumbs.php (Portuguese, Brazilian) 2017-08-25 07:07:36 +02:00
James Cole
d36801c589 New translations breadcrumbs.php (Polish) 2017-08-25 07:07:35 +02:00
James Cole
9f62df36dc New translations breadcrumbs.php (Chinese Traditional) 2017-08-25 07:07:34 +02:00
James Cole
aa66cfaae7 New translations breadcrumbs.php (Slovenian) 2017-08-25 07:07:32 +02:00
James Cole
e36abd2dfb New translations breadcrumbs.php (Spanish) 2017-08-25 07:07:31 +02:00
James Cole
9d5a021b1e New translations csv.php (Chinese Traditional) 2017-08-25 07:07:30 +02:00
James Cole
5ddad51911 New translations csv.php (Polish) 2017-08-25 07:07:29 +02:00
James Cole
ef5a950ecb New translations csv.php (German) 2017-08-25 07:07:28 +02:00
James Cole
8419cfae2b New translations config.php (Chinese Traditional) 2017-08-25 07:07:26 +02:00
James Cole
289e144521 New translations list.php (German) 2017-08-25 07:07:24 +02:00
James Cole
97ab06ea22 New translations breadcrumbs.php (Russian) 2017-08-25 07:07:23 +02:00
James Cole
3d06fba918 New translations csv.php (Russian) 2017-08-25 07:07:22 +02:00
James Cole
f9aa33315a New translations form.php (Russian) 2017-08-25 07:07:21 +02:00
James Cole
8eb6092f91 New translations firefly.php (Russian) 2017-08-25 07:07:20 +02:00
James Cole
06a50a5e45 New translations demo.php (Polish) 2017-08-25 07:07:17 +02:00
James Cole
4759713d9d New translations demo.php (Slovenian) 2017-08-25 07:07:16 +02:00
James Cole
7061730abc New translations list.php (Russian) 2017-08-25 07:07:15 +02:00
James Cole
f62dee262c New translations intro.php (Polish) 2017-08-25 07:07:14 +02:00
James Cole
df3a4d0d45 New translations intro.php (Portuguese, Brazilian) 2017-08-25 07:07:13 +02:00
James Cole
33d1fc085b New translations intro.php (Russian) 2017-08-25 07:07:12 +02:00
James Cole
c5eb3923c1 New translations intro.php (Spanish) 2017-08-25 07:07:10 +02:00
James Cole
596dd03bb4 New translations intro.php (Slovenian) 2017-08-25 07:07:09 +02:00
James Cole
d72bdcfe9b New translations intro.php (German) 2017-08-25 07:07:08 +02:00
James Cole
0c3174c2b5 New translations intro.php (French) 2017-08-25 07:07:07 +02:00
James Cole
6abb219499 New translations validation.php (Russian) 2017-08-25 07:07:06 +02:00
James Cole
eea1ddc288 New translations demo.php (Russian) 2017-08-25 07:07:05 +02:00
James Cole
42cbb7b723 New translations intro.php (Chinese Traditional) 2017-08-25 07:07:03 +02:00
James Cole
a06097b012 New translations demo.php (Chinese Traditional) 2017-08-25 07:07:02 +02:00
James Cole
d7b8115724 New translations list.php (Portuguese, Brazilian) 2017-08-25 07:07:00 +02:00
James Cole
c7703cd70c New translations list.php (Polish) 2017-08-25 07:06:59 +02:00
James Cole
8dec3717eb New translations list.php (Slovenian) 2017-08-25 07:06:57 +02:00
James Cole
c0673b10b5 New translations list.php (Spanish) 2017-08-25 07:06:56 +02:00
James Cole
91c3f2fb2d New translations validation.php (German) 2017-08-25 07:06:55 +02:00
James Cole
f83afd82d1 New translations validation.php (Portuguese, Brazilian) 2017-08-25 07:06:53 +02:00
James Cole
cf2cda6694 New translations validation.php (Slovenian) 2017-08-25 07:06:52 +02:00
James Cole
455c6e0d39 New translations validation.php (Chinese Traditional) 2017-08-25 07:06:48 +02:00
James Cole
72b7900ce2 Merge pull request #762 from firefly-iii/l10n_develop
New Crowdin translations
2017-08-25 07:04:51 +02:00
James Cole
dba3d89027 Update form for linking. 2017-08-25 06:58:28 +02:00
James Cole
8e4a480f05 New translations intro.php (Dutch) 2017-08-25 06:50:05 +02:00
James Cole
7fe2ed81e2 New translations intro.php (Dutch) 2017-08-25 06:40:14 +02:00
James Cole
58db856b9d New translations intro.php (Polish) 2017-08-25 06:27:25 +02:00
James Cole
62a854c2ea New translations intro.php (Portuguese, Brazilian) 2017-08-25 06:27:24 +02:00
James Cole
acb15e5209 New translations intro.php (Russian) 2017-08-25 06:27:22 +02:00
James Cole
ebf4395bc9 New translations intro.php (Spanish) 2017-08-25 06:27:21 +02:00
James Cole
8af45e8091 New translations intro.php (Slovenian) 2017-08-25 06:27:20 +02:00
James Cole
32d6951c34 New translations intro.php (German) 2017-08-25 06:27:18 +02:00
James Cole
a172762558 New translations intro.php (French) 2017-08-25 06:27:17 +02:00
James Cole
7abedd176f New translations intro.php (Dutch) 2017-08-25 06:27:15 +02:00
James Cole
f63be8a47d New translations intro.php (Chinese Traditional) 2017-08-25 06:27:14 +02:00
James Cole
86aa27d92c Fix language string [skip ci] 2017-08-25 06:23:01 +02:00
James Cole
972480269a Updated strings [skip ci] 2017-08-25 06:21:26 +02:00
James Cole
b829e5c0f6 New translations intro.php (Dutch) 2017-08-25 06:20:06 +02:00
James Cole
fe4b3c6f36 New translations firefly.php (Dutch) 2017-08-24 21:40:49 +02:00
James Cole
cad3921c95 New translations intro.php (Polish) 2017-08-24 21:40:27 +02:00
James Cole
24a84de463 New translations intro.php (Portuguese, Brazilian) 2017-08-24 21:40:25 +02:00
James Cole
3abf949e3f New translations intro.php (Russian) 2017-08-24 21:40:24 +02:00
James Cole
b561d86410 New translations intro.php (Spanish) 2017-08-24 21:40:22 +02:00
James Cole
59ff1ff856 New translations intro.php (Slovenian) 2017-08-24 21:40:21 +02:00
James Cole
88a911f6b7 New translations intro.php (German) 2017-08-24 21:40:20 +02:00
James Cole
55aa3f1198 New translations intro.php (French) 2017-08-24 21:40:19 +02:00
James Cole
a6f78aad73 New translations intro.php (Dutch) 2017-08-24 21:40:17 +02:00
James Cole
54bfbf174b New translations intro.php (Chinese Traditional) 2017-08-24 21:40:16 +02:00
James Cole
be6757c290 Fix some strings [skip ci] 2017-08-24 21:36:26 +02:00
James Cole
dda2080d01 New translations firefly.php (Slovenian) 2017-08-24 21:31:03 +02:00
James Cole
8ba63338fc New translations firefly.php (Spanish) 2017-08-24 21:31:00 +02:00
James Cole
8ebb39b8d5 New translations firefly.php (Portuguese, Brazilian) 2017-08-24 21:30:55 +02:00
James Cole
0f230834a1 New translations firefly.php (Polish) 2017-08-24 21:30:52 +02:00
James Cole
2dc41df0c8 New translations firefly.php (Chinese Traditional) 2017-08-24 21:30:49 +02:00
James Cole
995b879a28 New translations firefly.php (Dutch) 2017-08-24 21:30:46 +02:00
James Cole
b72e8559f6 New translations firefly.php (German) 2017-08-24 21:30:44 +02:00
James Cole
733b5c62af New translations firefly.php (French) 2017-08-24 21:30:41 +02:00
James Cole
b192b5366a New translations firefly.php (Russian) 2017-08-24 21:30:24 +02:00
James Cole
14aa261aca Remove unused translations. 2017-08-24 21:23:48 +02:00
James Cole
14a218e319 New translations breadcrumbs.php (Dutch) 2017-08-24 19:50:07 +02:00
James Cole
4ac5f25279 Expand config for links. 2017-08-24 19:47:31 +02:00
James Cole
c37ade8f5b Catch link error. 2017-08-24 19:42:23 +02:00
James Cole
1a179c7a45 New translations form.php (Dutch) 2017-08-24 18:41:00 +02:00
James Cole
237983cecf New translations breadcrumbs.php (Dutch) 2017-08-24 18:40:40 +02:00
James Cole
c1985b2fa2 New translations breadcrumbs.php (French) 2017-08-24 18:40:39 +02:00
James Cole
fc13df9a09 New translations breadcrumbs.php (German) 2017-08-24 18:40:37 +02:00
James Cole
8389b87556 New translations breadcrumbs.php (Portuguese, Brazilian) 2017-08-24 18:40:36 +02:00
James Cole
b77a783f94 New translations breadcrumbs.php (Polish) 2017-08-24 18:40:35 +02:00
James Cole
cdffd4a995 New translations breadcrumbs.php (Chinese Traditional) 2017-08-24 18:40:34 +02:00
James Cole
e75d17ed24 New translations breadcrumbs.php (Slovenian) 2017-08-24 18:40:32 +02:00
James Cole
087b4d5c7f New translations breadcrumbs.php (Spanish) 2017-08-24 18:40:31 +02:00
James Cole
7ce631d529 New translations breadcrumbs.php (Russian) 2017-08-24 18:40:26 +02:00
James Cole
829d3680d9 Broken translation. 2017-08-24 18:39:46 +02:00
James Cole
dbad6e4e8c New translations firefly.php (French) 2017-08-24 16:20:10 +02:00
James Cole
7453f89827 New translations form.php (French) 2017-08-23 23:10:06 +02:00
James Cole
3d639c7d45 New translations firefly.php (Slovenian) 2017-08-23 21:31:26 +02:00
James Cole
9348316b12 New translations firefly.php (Spanish) 2017-08-23 21:31:23 +02:00
James Cole
d7d874d48c New translations form.php (Chinese Traditional) 2017-08-23 21:31:20 +02:00
James Cole
7aec367a3c New translations form.php (French) 2017-08-23 21:31:19 +02:00
James Cole
6a29c64f08 New translations form.php (Dutch) 2017-08-23 21:31:18 +02:00
James Cole
0ee825212e New translations firefly.php (Portuguese, Brazilian) 2017-08-23 21:31:16 +02:00
James Cole
8dfd2b9b07 New translations firefly.php (Polish) 2017-08-23 21:31:13 +02:00
James Cole
343909f87a New translations firefly.php (Chinese Traditional) 2017-08-23 21:31:10 +02:00
James Cole
5e85d5ef32 New translations firefly.php (Dutch) 2017-08-23 21:31:07 +02:00
James Cole
1b14d7aa2d New translations firefly.php (German) 2017-08-23 21:31:04 +02:00
James Cole
139282a39e New translations firefly.php (French) 2017-08-23 21:31:02 +02:00
James Cole
e9724d8b41 New translations form.php (German) 2017-08-23 21:30:58 +02:00
James Cole
adc9f92125 New translations form.php (Polish) 2017-08-23 21:30:57 +02:00
James Cole
1c93153d83 New translations form.php (Slovenian) 2017-08-23 21:30:54 +02:00
James Cole
c73a32f76d New translations form.php (Portuguese, Brazilian) 2017-08-23 21:30:53 +02:00
James Cole
068af6b0d5 New translations form.php (Spanish) 2017-08-23 21:30:51 +02:00
James Cole
01a2d5e017 New translations breadcrumbs.php (Dutch) 2017-08-23 21:30:48 +02:00
James Cole
ca9f0fde9b New translations breadcrumbs.php (French) 2017-08-23 21:30:47 +02:00
James Cole
b16a9053b4 New translations breadcrumbs.php (German) 2017-08-23 21:30:45 +02:00
James Cole
5e6e7ed152 New translations breadcrumbs.php (Portuguese, Brazilian) 2017-08-23 21:30:44 +02:00
James Cole
93d1c06892 New translations breadcrumbs.php (Polish) 2017-08-23 21:30:43 +02:00
James Cole
e22745d1ff New translations breadcrumbs.php (Chinese Traditional) 2017-08-23 21:30:42 +02:00
James Cole
3308bc8a0f New translations breadcrumbs.php (Slovenian) 2017-08-23 21:30:38 +02:00
James Cole
f94193ad53 New translations breadcrumbs.php (Spanish) 2017-08-23 21:30:37 +02:00
James Cole
6f5eb45144 New translations breadcrumbs.php (Russian) 2017-08-23 21:30:32 +02:00
James Cole
9bfa7acdee New translations form.php (Russian) 2017-08-23 21:30:31 +02:00
James Cole
e38b259094 New translations firefly.php (Russian) 2017-08-23 21:30:29 +02:00
James Cole
394e92d538 Improvements for #616 and others. 2017-08-23 21:21:42 +02:00
James Cole
02ee9451d8 New translations firefly.php (Polish) 2017-08-23 21:10:09 +02:00
James Cole
093fe22ab5 New translations firefly.php (Polish) 2017-08-23 21:00:09 +02:00
James Cole
2bb4d7c8b9 New translations firefly.php (Polish) 2017-08-23 20:50:07 +02:00
James Cole
ea2732b38c New translations firefly.php (Polish) 2017-08-23 20:40:46 +02:00
James Cole
6bb3cf5719 New translations firefly.php (Polish) 2017-08-23 20:30:19 +02:00
James Cole
54e277e773 New translations firefly.php (Polish) 2017-08-23 20:20:10 +02:00
James Cole
dec29b3e22 New translations firefly.php (Polish) 2017-08-23 20:10:09 +02:00
James Cole
9974f71f3e New translations list.php (Polish) 2017-08-23 20:10:06 +02:00
James Cole
25256601a6 New translations validation.php (Polish) 2017-08-23 20:00:06 +02:00
James Cole
d3e9fe37eb New translations config.php (Polish) 2017-08-23 19:50:07 +02:00
James Cole
9ccbebdc4f New translations breadcrumbs.php (Polish) 2017-08-23 19:20:06 +02:00
James Cole
73ddd239aa New translations firefly.php (French) 2017-08-23 00:20:08 +02:00
James Cole
598eec219f New translations firefly.php (French) 2017-08-23 00:10:18 +02:00
James Cole
f2f6239b59 New translations firefly.php (French) 2017-08-23 00:00:19 +02:00
James Cole
ce53cdd4a4 New translations firefly.php (French) 2017-08-22 23:50:08 +02:00
James Cole
4a97a6403d New translations firefly.php (French) 2017-08-22 23:10:07 +02:00
James Cole
6ec397b934 New translations firefly.php (French) 2017-08-22 23:00:17 +02:00
James Cole
23be3afc9d New translations list.php (French) 2017-08-22 14:50:07 +02:00
James Cole
bf6b12cf57 New translations form.php (French) 2017-08-22 14:50:06 +02:00
James Cole
3936251363 New translations firefly.php (French) 2017-08-22 14:40:09 +02:00
James Cole
b50d97c3b7 New translations firefly.php (French) 2017-08-22 14:30:16 +02:00
James Cole
ef29d4efe8 New translations firefly.php (French) 2017-08-22 14:20:13 +02:00
James Cole
92ddf9bb2d New translations firefly.php (Polish) 2017-08-22 14:10:44 +02:00
James Cole
875d5d50b8 New translations firefly.php (French) 2017-08-22 14:10:39 +02:00
James Cole
83fa13ea4b New translations firefly.php (Chinese Traditional) 2017-08-22 14:10:35 +02:00
James Cole
8b24716372 New translations firefly.php (Portuguese, Brazilian) 2017-08-22 14:10:31 +02:00
James Cole
670ac4a34f New translations firefly.php (Slovenian) 2017-08-22 14:10:27 +02:00
James Cole
82eb923689 New translations firefly.php (Spanish) 2017-08-22 14:10:21 +02:00
James Cole
18aeda4713 New translations firefly.php (German) 2017-08-21 19:00:49 +02:00
James Cole
a388493030 New translations firefly.php (French) 2017-08-21 19:00:46 +02:00
James Cole
c3f8573950 New translations firefly.php (Russian) 2017-08-21 19:00:29 +02:00
James Cole
36778bb87e New translations firefly.php (Dutch) 2017-08-21 19:00:23 +02:00
James Cole
1a89e379a4 Language fix [skip ci] 2017-08-21 18:55:25 +02:00
James Cole
0aae349816 Missing translations 2017-08-21 18:53:02 +02:00
James Cole
434291b592 New translations firefly.php (Slovenian) 2017-08-21 18:21:12 +02:00
James Cole
668ceda86c New translations firefly.php (Spanish) 2017-08-21 18:21:09 +02:00
James Cole
e3ef729adf New translations firefly.php (Portuguese, Brazilian) 2017-08-21 18:21:04 +02:00
James Cole
baafba1774 New translations firefly.php (Polish) 2017-08-21 18:21:01 +02:00
James Cole
2ccf82749f New translations firefly.php (Chinese Traditional) 2017-08-21 18:20:58 +02:00
James Cole
5663fd386a New translations firefly.php (Dutch) 2017-08-21 18:20:55 +02:00
James Cole
6d1ebf3952 New translations firefly.php (German) 2017-08-21 18:20:52 +02:00
James Cole
0ea28c646a New translations firefly.php (French) 2017-08-21 18:20:49 +02:00
James Cole
fab5dc64e9 New translations firefly.php (Russian) 2017-08-21 18:20:31 +02:00
James Cole
a5013ecbc3 Expand link view and more features #616 2017-08-21 18:16:15 +02:00
James Cole
5f82e947b2 New translations demo.php (Dutch) 2017-08-21 17:20:12 +02:00
James Cole
d00b9515de fix #770 2017-08-21 17:11:18 +02:00
James Cole
eebbbdd0dc New translations list.php (Dutch) 2017-08-21 10:50:16 +02:00
James Cole
46adb7644a New translations firefly.php (Dutch) 2017-08-21 10:40:18 +02:00
James Cole
49e7b4f4ea New translations form.php (Dutch) 2017-08-21 10:40:15 +02:00
James Cole
55b1c533cf Fix division by zero. [skip ci] 2017-08-21 08:48:02 +02:00
James Cole
f1a7f30167 Fix division by zero. [skip ci] 2017-08-21 08:47:03 +02:00
James Cole
9f5c2b74eb Fix division by zero. 2017-08-21 08:44:04 +02:00
James Cole
78b44af7a2 New translations firefly.php (Slovenian) 2017-08-21 07:21:12 +02:00
James Cole
a8442ca0bb New translations firefly.php (Spanish) 2017-08-21 07:21:10 +02:00
James Cole
926b1ae28b New translations form.php (Chinese Traditional) 2017-08-21 07:21:08 +02:00
James Cole
109c1ce245 New translations form.php (French) 2017-08-21 07:21:06 +02:00
James Cole
637ccf1b2a New translations form.php (Dutch) 2017-08-21 07:21:05 +02:00
James Cole
a428aedf14 New translations firefly.php (Portuguese, Brazilian) 2017-08-21 07:21:04 +02:00
James Cole
2747049986 New translations firefly.php (Polish) 2017-08-21 07:21:02 +02:00
James Cole
9a52fcf66d New translations firefly.php (Chinese Traditional) 2017-08-21 07:20:59 +02:00
James Cole
a2b2e01e39 New translations firefly.php (Dutch) 2017-08-21 07:20:57 +02:00
James Cole
be48a2ed91 New translations firefly.php (German) 2017-08-21 07:20:54 +02:00
James Cole
245db56771 New translations firefly.php (French) 2017-08-21 07:20:52 +02:00
James Cole
ba4616371b New translations form.php (German) 2017-08-21 07:20:50 +02:00
James Cole
62a3bbbcf5 New translations form.php (Polish) 2017-08-21 07:20:48 +02:00
James Cole
235c7a3bb8 New translations list.php (Dutch) 2017-08-21 07:20:46 +02:00
James Cole
9a1219c70c New translations list.php (Chinese Traditional) 2017-08-21 07:20:45 +02:00
James Cole
5e692e10bc New translations form.php (Slovenian) 2017-08-21 07:20:43 +02:00
James Cole
22b6916ac2 New translations form.php (Portuguese, Brazilian) 2017-08-21 07:20:42 +02:00
James Cole
e628ec6ff0 New translations form.php (Spanish) 2017-08-21 07:20:41 +02:00
James Cole
863f812dbb New translations list.php (French) 2017-08-21 07:20:33 +02:00
James Cole
21dbf0f14b New translations list.php (German) 2017-08-21 07:20:32 +02:00
James Cole
9c392461e8 New translations form.php (Russian) 2017-08-21 07:20:30 +02:00
James Cole
5b9178b18d New translations firefly.php (Russian) 2017-08-21 07:20:29 +02:00
James Cole
7f4a80f17f New translations list.php (Russian) 2017-08-21 07:20:25 +02:00
James Cole
2798837450 New translations list.php (Portuguese, Brazilian) 2017-08-21 07:20:19 +02:00
James Cole
381ca70517 New translations list.php (Polish) 2017-08-21 07:20:18 +02:00
James Cole
fe2beaf96a New translations list.php (Slovenian) 2017-08-21 07:20:17 +02:00
James Cole
c962ec34c8 New translations list.php (Spanish) 2017-08-21 07:20:16 +02:00
James Cole
ff390fcb7c Less complex links 2017-08-21 07:14:41 +02:00
James Cole
35ab4a5ff4 Management of links and first form for link storing #616 2017-08-21 07:13:03 +02:00
James Cole
cac498fd9e New translations firefly.php (Slovenian) 2017-08-20 14:50:58 +02:00
James Cole
06fcf8f079 New translations firefly.php (Spanish) 2017-08-20 14:50:55 +02:00
James Cole
5dad1fe2af New translations firefly.php (Portuguese, Brazilian) 2017-08-20 14:50:51 +02:00
James Cole
81ae860134 New translations firefly.php (Polish) 2017-08-20 14:50:48 +02:00
James Cole
91558049d9 New translations firefly.php (Chinese Traditional) 2017-08-20 14:50:45 +02:00
James Cole
aa78948c90 New translations firefly.php (Dutch) 2017-08-20 14:50:43 +02:00
James Cole
7cbe0768f2 New translations firefly.php (German) 2017-08-20 14:50:41 +02:00
James Cole
05be2fe25a New translations firefly.php (French) 2017-08-20 14:50:38 +02:00
James Cole
59f46b8265 New translations firefly.php (Russian) 2017-08-20 14:50:24 +02:00
James Cole
c5cdd748fc Make sure tests work again. 2017-08-20 14:36:14 +02:00
James Cole
6fcbe5a37f Various HTML fixes. 2017-08-20 12:43:31 +02:00
James Cole
4d595c1380 More link types for #616 2017-08-20 12:42:51 +02:00
James Cole
7684e966fc First code for #616 2017-08-20 12:41:31 +02:00
James Cole
40639dfa37 New view for tags 2017-08-20 12:40:14 +02:00
James Cole
5769d0121e New translations intro.php (Dutch) 2017-08-20 12:40:06 +02:00
James Cole
1d6f3fc57f Update composer file. 2017-08-20 12:39:31 +02:00
James Cole
2609f3425b Fix #738 2017-08-19 21:59:13 +02:00
James Cole
bd924b993b This fixes part of #738 (not everything). 2017-08-19 18:24:04 +02:00
James Cole
c4fe9a6a51 More code for bunq import, must now wait for reply from bunq itself 2017-08-19 16:46:06 +02:00
James Cole
4694e31e35 Expand bunq related code. 2017-08-19 09:22:44 +02:00
James Cole
ca0f09c8f7 Various cleanup. 2017-08-18 23:02:29 +02:00
James Cole
684c9773c9 Can now register with Bunq and get device server ID. 2017-08-18 21:09:22 +02:00
James Cole
df443aa34c Add copyright things. 2017-08-18 21:08:51 +02:00
James Cole
33e381b5da New translations form.php (Spanish) 2017-08-18 17:50:07 +02:00
James Cole
4b5d363f55 New translations validation.php (Spanish) 2017-08-18 17:50:06 +02:00
James Cole
4c3dbc6deb New translations validation.php (Spanish) 2017-08-18 17:40:06 +02:00
James Cole
519ad64e1d New translations validation.php (Spanish) 2017-08-18 17:30:06 +02:00
James Cole
93068659e5 Bunq code. 2017-08-18 17:08:30 +02:00
James Cole
4b46a3d298 Update composer.lock file. 2017-08-18 15:38:33 +02:00
James Cole
3e64028e29 Reinstate export javascript 2017-08-18 15:38:23 +02:00
James Cole
9b17715175 Fix the unit tests. 2017-08-18 15:32:11 +02:00
James Cole
7d8876f03c new export routine 2017-08-18 15:14:44 +02:00
James Cole
b955486f14 Updated export routine. 2017-08-18 14:45:42 +02:00
James Cole
6068cfbd70 New translations intro.php (Dutch) 2017-08-18 08:00:06 +02:00
James Cole
9cda8c8bcf New translations csv.php (Spanish) 2017-08-17 20:10:13 +02:00
James Cole
b7522288b5 New translations breadcrumbs.php (Spanish) 2017-08-17 20:00:18 +02:00
James Cole
18bc91734f New translations firefly.php (Spanish) 2017-08-17 20:00:16 +02:00
James Cole
ef21ac3d5a New translations firefly.php (Spanish) 2017-08-17 19:50:08 +02:00
James Cole
08af0aab75 New translations form.php (Spanish) 2017-08-17 19:50:06 +02:00
James Cole
a29292e018 New translations form.php (Spanish) 2017-08-17 19:40:06 +02:00
James Cole
ebb37c09e5 New translations form.php (Spanish) 2017-08-17 19:32:05 +02:00
James Cole
6666d1a2f4 Add debug information to getAmount routine. 2017-08-15 21:12:49 +02:00
James Cole
431bcf20ea Add list button [skip ci] #763 2017-08-15 17:37:48 +02:00
James Cole
7b3ef0e3ab Fix #764 2017-08-15 17:34:34 +02:00
James Cole
34894fb76b Add some comments [skip ci] 2017-08-15 17:26:43 +02:00
James Cole
e5afcbd013 New translations firefly.php (French) 2017-08-15 16:50:07 +02:00
James Cole
253a98143c New translations firefly.php (French) 2017-08-15 16:40:08 +02:00
James Cole
59a7feafef New translations firefly.php (French) 2017-08-15 16:30:08 +02:00
James Cole
0b2c3d7ca8 New translations firefly.php (French) 2017-08-15 10:10:22 +02:00
James Cole
bd8afc67dd New translations firefly.php (French) 2017-08-15 10:00:14 +02:00
James Cole
08e5b018b8 New translations csv.php (French) 2017-08-15 01:20:08 +02:00
James Cole
3d58a0c0f3 New translations firefly.php (French) 2017-08-15 01:20:07 +02:00
James Cole
56f7ca388d New translations firefly.php (French) 2017-08-15 01:10:06 +02:00
James Cole
ddf0ee9972 New translations firefly.php (French) 2017-08-15 01:00:07 +02:00
James Cole
298e6d38a0 New translations firefly.php (French) 2017-08-15 00:50:07 +02:00
James Cole
7bb5d243a0 New translations firefly.php (French) 2017-08-15 00:40:07 +02:00
James Cole
207b0194c2 New translations firefly.php (French) 2017-08-15 00:30:07 +02:00
James Cole
f1081e058c New translations firefly.php (French) 2017-08-15 00:20:07 +02:00
James Cole
7974319c73 New translations firefly.php (French) 2017-08-15 00:10:08 +02:00
James Cole
e84b37fc66 New translations firefly.php (French) 2017-08-14 23:50:14 +02:00
James Cole
4219edc089 New translations firefly.php (French) 2017-08-14 23:40:07 +02:00
James Cole
244dcc0465 New translations demo.php (French) 2017-08-14 19:10:07 +02:00
James Cole
5e423a8ede New translations list.php (French) 2017-08-14 18:10:11 +02:00
James Cole
fe24c8971f New translations breadcrumbs.php (French) 2017-08-14 18:10:10 +02:00
James Cole
2410c767f8 New translations form.php (French) 2017-08-14 18:10:09 +02:00
James Cole
a785fd27ec New translations validation.php (French) 2017-08-14 18:10:07 +02:00
James Cole
5d3df4579e New translations list.php (French) 2017-08-14 18:00:13 +02:00
James Cole
3182256580 New translations csv.php (French) 2017-08-14 18:00:11 +02:00
James Cole
84b5c3c789 New translations csv.php (French) 2017-08-14 17:50:12 +02:00
James Cole
4a1a70fa46 New translations csv.php (French) 2017-08-14 17:41:49 +02:00
James Cole
fe457d149c New translations csv.php (French) 2017-08-14 17:00:07 +02:00
James Cole
9a29747bbf New translations csv.php (French) 2017-08-14 16:50:08 +02:00
James Cole
c04eb6dc2a New translations csv.php (French) 2017-08-14 16:20:06 +02:00
James Cole
5a9a6a4680 New translations csv.php (French) 2017-08-14 16:10:14 +02:00
James Cole
1633994fbd Slight change in amount handler. #760 2017-08-13 15:30:39 +02:00
James Cole
f9c85d4d81 Catch the error in #760 2017-08-13 12:37:09 +02:00
James Cole
ec636c95a1 Improve update and verify routines. 2017-08-13 12:30:28 +02:00
James Cole
2915fae942 Merge branch 'release/4.6.4' 2017-08-13 09:04:40 +02:00
James Cole
f9b5468481 Last minute fixes for import routine. 2017-08-13 08:49:45 +02:00
James Cole
287f37eba5 Remove unused parameters. 2017-08-13 08:24:58 +02:00
James Cole
26740668da Import transfer error 2017-08-12 21:23:19 +02:00
James Cole
bdd72f0d30 Fix path for tag controller. 2017-08-12 21:22:59 +02:00
James Cole
7e79f25949 Merge languages. 2017-08-12 19:47:46 +02:00
James Cole
2d917e166c Merge pull request #755 from firefly-iii/l10n_develop
New Crowdin translations
2017-08-12 19:47:26 +02:00
James Cole
ad4a811d0a Small bug fixes [skip ci] 2017-08-12 19:11:24 +02:00
James Cole
ab1aa97af4 Read me says 7.1 too. [skip ci] 2017-08-12 19:11:11 +02:00
James Cole
018941c5b3 Actually use journal [skip ci] 2017-08-12 19:05:29 +02:00
James Cole
cc1439fb7b Revamped import routine. 2017-08-12 19:03:42 +02:00
James Cole
f684a2900b Include default currency. 2017-08-12 16:42:29 +02:00
James Cole
83b721a322 Small bug fix in map / roles. 2017-08-12 16:41:05 +02:00
James Cole
a879528ed8 Back to basics. 2017-08-12 16:40:51 +02:00
James Cole
accbff3ccb Small cleanup in CSV processor 2017-08-12 16:12:30 +02:00
James Cole
0375f77b73 Prevent asset account from being found by opposing account. #719 2017-08-12 13:49:40 +02:00
James Cole
9d01162f42 New translations auth.php (Chinese Traditional) 2017-08-12 10:42:10 +02:00
James Cole
3436dc1564 New translations firefly.php (Slovenian) 2017-08-12 10:42:09 +02:00
James Cole
089293079f New translations firefly.php (Spanish) 2017-08-12 10:42:06 +02:00
James Cole
00e2cd7c04 New translations form.php (Chinese Traditional) 2017-08-12 10:42:04 +02:00
James Cole
f5abb933b0 New translations form.php (French) 2017-08-12 10:42:03 +02:00
James Cole
848386bbaf New translations form.php (Dutch) 2017-08-12 10:42:01 +02:00
James Cole
5562a3c2ae New translations firefly.php (Portuguese, Brazilian) 2017-08-12 10:42:00 +02:00
James Cole
9e8738660b New translations firefly.php (Polish) 2017-08-12 10:41:57 +02:00
James Cole
178772d50d New translations firefly.php (Chinese Traditional) 2017-08-12 10:41:55 +02:00
James Cole
8d7f29c7c9 New translations firefly.php (Dutch) 2017-08-12 10:41:52 +02:00
James Cole
255f87f1c3 New translations firefly.php (German) 2017-08-12 10:41:50 +02:00
James Cole
975354d081 New translations firefly.php (French) 2017-08-12 10:41:48 +02:00
James Cole
ec6890ced1 New translations form.php (German) 2017-08-12 10:41:46 +02:00
James Cole
290efb4b62 New translations form.php (Polish) 2017-08-12 10:41:44 +02:00
James Cole
ab3ea76244 New translations help.php (Portuguese, Brazilian) 2017-08-12 10:41:43 +02:00
James Cole
21d07aef15 New translations help.php (Slovenian) 2017-08-12 10:41:42 +02:00
James Cole
6031cd02b9 New translations help.php (Spanish) 2017-08-12 10:41:41 +02:00
James Cole
2cdb4cab12 New translations list.php (Dutch) 2017-08-12 10:41:41 +02:00
James Cole
679217f2ef New translations list.php (Chinese Traditional) 2017-08-12 10:41:40 +02:00
James Cole
3aacc0a258 New translations help.php (Polish) 2017-08-12 10:41:39 +02:00
James Cole
254cf6cc5b New translations help.php (German) 2017-08-12 10:41:38 +02:00
James Cole
c06095259a New translations form.php (Slovenian) 2017-08-12 10:41:37 +02:00
James Cole
30fd98c8d7 New translations form.php (Portuguese, Brazilian) 2017-08-12 10:41:36 +02:00
James Cole
3a410f04fe New translations form.php (Spanish) 2017-08-12 10:41:35 +02:00
James Cole
4a0a58cdc1 New translations help.php (Chinese Traditional) 2017-08-12 10:41:34 +02:00
James Cole
c834f93539 New translations help.php (French) 2017-08-12 10:41:33 +02:00
James Cole
35bdb84e57 New translations help.php (Dutch) 2017-08-12 10:41:32 +02:00
James Cole
36a3a09fcc New translations breadcrumbs.php (Dutch) 2017-08-12 10:41:30 +02:00
James Cole
2c07b490e8 New translations breadcrumbs.php (French) 2017-08-12 10:41:29 +02:00
James Cole
5790311cbd New translations breadcrumbs.php (German) 2017-08-12 10:41:29 +02:00
James Cole
fde3322117 New translations breadcrumbs.php (Portuguese, Brazilian) 2017-08-12 10:41:28 +02:00
James Cole
5664e133d1 New translations breadcrumbs.php (Polish) 2017-08-12 10:41:27 +02:00
James Cole
a1dc38a83f New translations breadcrumbs.php (Chinese Traditional) 2017-08-12 10:41:26 +02:00
James Cole
df974f93ee New translations auth.php (Spanish) 2017-08-12 10:41:25 +02:00
James Cole
3dde64cdac New translations auth.php (French) 2017-08-12 10:41:24 +02:00
James Cole
6b4887df0f New translations auth.php (Dutch) 2017-08-12 10:41:23 +02:00
James Cole
ca8ef3961e New translations auth.php (German) 2017-08-12 10:41:22 +02:00
James Cole
114e0e5b1e New translations auth.php (Polish) 2017-08-12 10:41:22 +02:00
James Cole
c7a247cbba New translations auth.php (Slovenian) 2017-08-12 10:41:21 +02:00
James Cole
3a641a7020 New translations auth.php (Portuguese, Brazilian) 2017-08-12 10:41:20 +02:00
James Cole
0977859bf5 New translations breadcrumbs.php (Slovenian) 2017-08-12 10:41:19 +02:00
James Cole
a644253ee9 New translations breadcrumbs.php (Spanish) 2017-08-12 10:41:18 +02:00
James Cole
3403356be8 New translations config.php (Spanish) 2017-08-12 10:41:16 +02:00
James Cole
4a9ec0d0d4 New translations config.php (Slovenian) 2017-08-12 10:41:15 +02:00
James Cole
250c5c0745 New translations config.php (Dutch) 2017-08-12 10:41:14 +02:00
James Cole
120b5880b1 New translations config.php (Chinese Traditional) 2017-08-12 10:41:13 +02:00
James Cole
18eff73795 New translations config.php (French) 2017-08-12 10:41:12 +02:00
James Cole
89b9dbb1b4 New translations config.php (German) 2017-08-12 10:41:12 +02:00
James Cole
dde4b3ab93 New translations config.php (Portuguese, Brazilian) 2017-08-12 10:41:11 +02:00
James Cole
b1cc655ba5 New translations config.php (Polish) 2017-08-12 10:41:10 +02:00
James Cole
5645a12d5b New translations list.php (French) 2017-08-12 10:41:09 +02:00
James Cole
ce1a935c06 New translations list.php (German) 2017-08-12 10:41:08 +02:00
James Cole
58b90ad6c9 New translations breadcrumbs.php (Russian) 2017-08-12 10:41:07 +02:00
James Cole
4740e63e76 New translations config.php (Russian) 2017-08-12 10:41:06 +02:00
James Cole
319932c734 New translations form.php (Russian) 2017-08-12 10:41:05 +02:00
James Cole
7cf415288a New translations firefly.php (Russian) 2017-08-12 10:41:03 +02:00
James Cole
fe67c1db8f New translations auth.php (Russian) 2017-08-12 10:41:01 +02:00
James Cole
09afbd89b8 New translations demo.php (Spanish) 2017-08-12 10:41:00 +02:00
James Cole
824f7d827c New translations demo.php (French) 2017-08-12 10:40:59 +02:00
James Cole
3a8ca56f95 New translations demo.php (German) 2017-08-12 10:40:58 +02:00
James Cole
137e3fd083 New translations demo.php (Polish) 2017-08-12 10:40:57 +02:00
James Cole
1285944b1f New translations demo.php (Slovenian) 2017-08-12 10:40:56 +02:00
James Cole
cd8e9deab7 New translations demo.php (Portuguese, Brazilian) 2017-08-12 10:40:56 +02:00
James Cole
de424eac64 New translations help.php (Russian) 2017-08-12 10:40:55 +02:00
James Cole
d106a09766 New translations list.php (Russian) 2017-08-12 10:40:54 +02:00
James Cole
963e8ccd2c New translations intro.php (Polish) 2017-08-12 10:40:53 +02:00
James Cole
3474b8f2d0 New translations intro.php (Portuguese, Brazilian) 2017-08-12 10:40:52 +02:00
James Cole
e27b449ae9 New translations intro.php (Russian) 2017-08-12 10:40:51 +02:00
James Cole
7656818456 New translations intro.php (Spanish) 2017-08-12 10:40:50 +02:00
James Cole
d214be1215 New translations intro.php (Slovenian) 2017-08-12 10:40:49 +02:00
James Cole
c8678c3ee5 New translations intro.php (German) 2017-08-12 10:40:48 +02:00
James Cole
108ee40c3f New translations intro.php (French) 2017-08-12 10:40:47 +02:00
James Cole
de51d205dc New translations passwords.php (Russian) 2017-08-12 10:40:46 +02:00
James Cole
1f76246edc New translations pagination.php (Russian) 2017-08-12 10:40:45 +02:00
James Cole
f91974b766 New translations validation.php (Russian) 2017-08-12 10:40:44 +02:00
James Cole
df85936145 New translations demo.php (Russian) 2017-08-12 10:40:43 +02:00
James Cole
f39aa0f52a New translations intro.php (Dutch) 2017-08-12 10:40:42 +02:00
James Cole
180812394b New translations intro.php (Chinese Traditional) 2017-08-12 10:40:41 +02:00
James Cole
291fa9597f New translations demo.php (Dutch) 2017-08-12 10:40:40 +02:00
James Cole
6c4d8c25fc New translations demo.php (Chinese Traditional) 2017-08-12 10:40:39 +02:00
James Cole
bf4b32a8e9 New translations pagination.php (Polish) 2017-08-12 10:40:39 +02:00
James Cole
2e9dac7678 New translations pagination.php (Portuguese, Brazilian) 2017-08-12 10:40:38 +02:00
James Cole
369314c1cb New translations pagination.php (Slovenian) 2017-08-12 10:40:37 +02:00
James Cole
6ab86898af New translations passwords.php (Chinese Traditional) 2017-08-12 10:40:36 +02:00
James Cole
f3aa65d219 New translations pagination.php (Spanish) 2017-08-12 10:40:35 +02:00
James Cole
edf4f19de9 New translations pagination.php (German) 2017-08-12 10:40:34 +02:00
James Cole
91eaaae6d7 New translations pagination.php (French) 2017-08-12 10:40:34 +02:00
James Cole
ca0ae5a165 New translations list.php (Portuguese, Brazilian) 2017-08-12 10:40:33 +02:00
James Cole
86d788d294 New translations list.php (Polish) 2017-08-12 10:40:32 +02:00
James Cole
e345cea9be New translations list.php (Slovenian) 2017-08-12 10:40:31 +02:00
James Cole
779f7841c2 New translations list.php (Spanish) 2017-08-12 10:40:30 +02:00
James Cole
15fdca46b8 New translations pagination.php (Dutch) 2017-08-12 10:40:29 +02:00
James Cole
97e099c70f New translations pagination.php (Chinese Traditional) 2017-08-12 10:40:28 +02:00
James Cole
d5a58bb763 New translations passwords.php (Dutch) 2017-08-12 10:40:26 +02:00
James Cole
2774df0d30 New translations passwords.php (French) 2017-08-12 10:40:25 +02:00
James Cole
93a1799a4b New translations validation.php (German) 2017-08-12 10:40:24 +02:00
James Cole
f65f051c7c New translations validation.php (Polish) 2017-08-12 10:40:23 +02:00
James Cole
c46952dd4e New translations validation.php (Portuguese, Brazilian) 2017-08-12 10:40:22 +02:00
James Cole
1dad6b6118 New translations validation.php (Spanish) 2017-08-12 10:40:22 +02:00
James Cole
e964621f2c New translations validation.php (Slovenian) 2017-08-12 10:40:21 +02:00
James Cole
46ae62f693 New translations validation.php (French) 2017-08-12 10:40:20 +02:00
James Cole
7d578f5852 New translations validation.php (Dutch) 2017-08-12 10:40:19 +02:00
James Cole
467f257ad3 New translations passwords.php (Polish) 2017-08-12 10:40:18 +02:00
James Cole
55186c0a49 New translations passwords.php (German) 2017-08-12 10:40:17 +02:00
James Cole
1a0a4f7112 New translations passwords.php (Portuguese, Brazilian) 2017-08-12 10:40:16 +02:00
James Cole
658290ae80 New translations passwords.php (Slovenian) 2017-08-12 10:40:15 +02:00
James Cole
cb9f29c6fc New translations validation.php (Chinese Traditional) 2017-08-12 10:40:15 +02:00
James Cole
d8f4955292 New translations passwords.php (Spanish) 2017-08-12 10:40:13 +02:00
James Cole
9803932324 Various code clean up. 2017-08-12 10:27:45 +02:00
James Cole
a3a416b5e2 New composer file 2017-08-12 09:15:09 +02:00
James Cole
1453a318fe Merge branch 'develop' of https://github.com/firefly-iii/firefly-iii into develop
* 'develop' of https://github.com/firefly-iii/firefly-iii: (23 commits)
  New translations firefly.php (Dutch)
  New translations firefly.php (Chinese Traditional)
  New translations firefly.php (Dutch)
  New translations firefly.php (Polish)
  New translations firefly.php (Portuguese, Brazilian)
  New translations firefly.php (Slovenian)
  New translations firefly.php (Spanish)
  New translations firefly.php (German)
  New translations firefly.php (French)
  New translations firefly.php (Russian)
  New translations firefly.php (Dutch)
  New translations validation.php (Dutch)
  New translations form.php (Dutch)
  New translations csv.php (Dutch)
  New translations firefly.php (Slovenian)
  New translations firefly.php (Spanish)
  New translations firefly.php (Portuguese, Brazilian)
  New translations firefly.php (Polish)
  New translations firefly.php (Chinese Traditional)
  New translations firefly.php (Dutch)
  ...
2017-08-12 09:14:54 +02:00
James Cole
9ffa01d318 Merge pull request #754 from firefly-iii/l10n_develop
New Crowdin translations
2017-08-12 09:14:18 +02:00
James Cole
29b779c873 Remove intro popup. 2017-08-12 09:06:13 +02:00
James Cole
598307f676 Update change log 2017-08-12 09:06:02 +02:00
James Cole
aa9d546bf5 New translations firefly.php (Dutch) 2017-08-12 08:20:30 +02:00
James Cole
f2ef245eca New translations firefly.php (Chinese Traditional) 2017-08-12 08:10:24 +02:00
James Cole
458606381e New translations firefly.php (Dutch) 2017-08-12 08:10:21 +02:00
James Cole
244f174dc9 New translations firefly.php (Polish) 2017-08-12 08:10:19 +02:00
James Cole
8a577f3197 New translations firefly.php (Portuguese, Brazilian) 2017-08-12 08:10:17 +02:00
James Cole
2f1b24cc14 New translations firefly.php (Slovenian) 2017-08-12 08:10:13 +02:00
James Cole
d5f836db7a New translations firefly.php (Spanish) 2017-08-12 08:10:10 +02:00
James Cole
ffd7c36cb2 New translations firefly.php (German) 2017-08-12 08:05:26 +02:00
James Cole
dba543d539 New translations firefly.php (French) 2017-08-12 08:05:24 +02:00
James Cole
9753c0f8eb New translations firefly.php (Russian) 2017-08-12 08:05:09 +02:00
James Cole
c50b4d3d47 New translations firefly.php (Dutch) 2017-08-12 08:05:02 +02:00
James Cole
907f886cf0 New translations validation.php (Dutch) 2017-08-12 08:04:53 +02:00
James Cole
218a2d2004 Expand password modal. 2017-08-12 08:01:40 +02:00
James Cole
0e0f2c6833 New translations form.php (Dutch) 2017-08-12 08:00:06 +02:00
James Cole
e59090d3b6 Text and modal for password security. 2017-08-12 07:56:02 +02:00
James Cole
0404be8bef New translations csv.php (Dutch) 2017-08-12 07:50:05 +02:00
James Cole
337895cbaa Add newlines to files. 2017-08-12 07:48:39 +02:00
James Cole
743547096e Various code cleanup 2017-08-12 07:47:42 +02:00
James Cole
81fb3df45e Fix #747 2017-08-12 07:39:58 +02:00
James Cole
12624cab5b Improve foreign currency routine for #746 2017-08-12 07:38:22 +02:00
James Cole
7d62ea88d2 New translations firefly.php (Slovenian) 2017-08-12 07:10:58 +02:00
James Cole
abcc277430 New translations firefly.php (Spanish) 2017-08-12 07:10:55 +02:00
James Cole
4c4c9426ee New translations firefly.php (Portuguese, Brazilian) 2017-08-12 07:10:52 +02:00
James Cole
88fdeb2bf2 New translations firefly.php (Polish) 2017-08-12 07:10:50 +02:00
James Cole
f9ab868022 New translations firefly.php (Chinese Traditional) 2017-08-12 07:10:47 +02:00
James Cole
148d2cec8f New translations firefly.php (Dutch) 2017-08-12 07:10:45 +02:00
James Cole
5869f157f6 New translations firefly.php (German) 2017-08-12 07:10:43 +02:00
James Cole
69a2902161 New translations firefly.php (French) 2017-08-12 07:10:40 +02:00
James Cole
c19b048249 New translations firefly.php (Russian) 2017-08-12 07:10:26 +02:00
James Cole
cd2c8acdb2 Merge pull request #729 from firefly-iii/l10n_develop
New Crowdin translations
2017-08-12 07:01:33 +02:00
James Cole
7d0d1c764f Make sure we’re still at 4.6.4 and bunq import is unavailable. [skip ci] 2017-08-12 07:01:21 +02:00
James Cole
b5acf1d529 Merge early release branch
Code for #749
  Add link to split withdrawal
  Clarifies #751
  Text for #748
  Improve error reporting #752
  Small code cleanup.
  Add copyright markers.
2017-08-12 06:59:59 +02:00
James Cole
72b08384ad Code for #749 2017-08-12 06:55:46 +02:00
James Cole
f51e48f282 Add link to split withdrawal 2017-08-12 06:55:35 +02:00
James Cole
2e6d1f3642 Clarifies #751 2017-08-12 06:44:00 +02:00
James Cole
716af4ed93 Text for #748 2017-08-12 06:41:14 +02:00
James Cole
31de86c9eb Improve error reporting #752 2017-08-12 06:40:17 +02:00
James Cole
04a2cd1f1f Small code cleanup. 2017-08-11 05:42:15 +02:00
James Cole
bc0ef11a8c Add copyright markers. 2017-08-11 05:36:05 +02:00
James Cole
90c8420a4c Initial code for preparing bunq import #714 2017-08-11 05:21:00 +02:00
James Cole
657d5e0d74 Upgrade version in develop 2017-08-11 05:02:49 +02:00
James Cole
03fa4d957c Added upgrade instruction [skip ci] 2017-08-10 20:52:10 +02:00
James Cole
8d4530f1f2 Fixes #743 2017-08-10 20:48:29 +02:00
James Cole
6d15c503c3 Fix #515 2017-08-10 20:41:33 +02:00
James Cole
75ddb34398 Remove references to date range thing. 2017-08-10 19:57:18 +02:00
James Cole
6fbfe6fb72 Remove references to date range thing. 2017-08-10 19:55:52 +02:00
James Cole
db500e911c update date range picker 2017-08-10 19:55:23 +02:00
James Cole
c0c5ced6ad Fix multi currency edit display 2017-08-10 19:55:13 +02:00
James Cole
726270f8bc New translations form.php (Chinese Traditional) 2017-08-08 16:41:01 +02:00
James Cole
c3908450a0 New translations form.php (French) 2017-08-08 16:40:59 +02:00
James Cole
f7ba05f465 New translations form.php (Dutch) 2017-08-08 16:40:58 +02:00
James Cole
dea7f7d5d6 New translations form.php (German) 2017-08-08 16:40:46 +02:00
James Cole
ed7a0a2b9d New translations form.php (Polish) 2017-08-08 16:40:45 +02:00
James Cole
ac6b4db0f8 New translations form.php (Slovenian) 2017-08-08 16:40:41 +02:00
James Cole
b5d659c13c New translations form.php (Portuguese, Brazilian) 2017-08-08 16:40:40 +02:00
James Cole
919cb5d1f2 New translations form.php (Spanish) 2017-08-08 16:40:39 +02:00
James Cole
e504d3cc35 New translations form.php (Russian) 2017-08-08 16:40:28 +02:00
James Cole
1d67939e76 No password service in env file. [skip ci] 2017-08-08 16:30:43 +02:00
James Cole
5d1e90d29c Expand verify password routine. 2017-08-08 16:30:21 +02:00
James Cole
1678eba9cc New translations intro.php (Polish) 2017-08-08 16:10:35 +02:00
James Cole
cc142b2ba1 New translations intro.php (Portuguese, Brazilian) 2017-08-08 16:10:33 +02:00
James Cole
48cbffba14 New translations intro.php (Russian) 2017-08-08 16:10:32 +02:00
James Cole
d909bb1b25 New translations intro.php (Spanish) 2017-08-08 16:10:31 +02:00
James Cole
3313e66fc2 New translations intro.php (Slovenian) 2017-08-08 16:10:30 +02:00
James Cole
085892a4c8 New translations intro.php (German) 2017-08-08 16:10:28 +02:00
James Cole
817e059230 New translations intro.php (French) 2017-08-08 16:10:27 +02:00
James Cole
7ce8891246 New translations intro.php (Dutch) 2017-08-08 16:10:25 +02:00
James Cole
439b2589f9 New translations intro.php (Chinese Traditional) 2017-08-08 16:10:24 +02:00
James Cole
e7b5cf66d2 Fix #739 2017-08-08 16:06:58 +02:00
James Cole
b29fabf76c Include virtual balance in transaction overview #735 2017-08-07 20:36:23 +02:00
James Cole
5d837c3ee4 Bump version. [skip ci] 2017-08-07 20:27:58 +02:00
James Cole
4c0396ad1c Fixes #733 2017-08-07 17:59:26 +02:00
James Cole
97b62fce79 New translations firefly.php (Russian) 2017-08-05 02:00:07 +02:00
James Cole
e904a38735 New translations firefly.php (Russian) 2017-08-05 01:10:08 +02:00
James Cole
ae72187aed New translations form.php (Russian) 2017-08-05 01:10:05 +02:00
James Cole
e4ebeefa61 New translations firefly.php (Russian) 2017-08-05 01:00:09 +02:00
James Cole
417373ba70 New translations form.php (Russian) 2017-08-05 01:00:06 +02:00
James Cole
36f9ded08e New translations breadcrumbs.php (Russian) 2017-08-05 01:00:05 +02:00
James Cole
858925b8c8 New translations firefly.php (Slovenian) 2017-08-04 17:11:13 +02:00
James Cole
d36c96fba9 New translations firefly.php (Spanish) 2017-08-04 17:11:10 +02:00
James Cole
2be6fb329e New translations firefly.php (Portuguese, Brazilian) 2017-08-04 17:11:05 +02:00
James Cole
da56363ef9 New translations firefly.php (Polish) 2017-08-04 17:11:02 +02:00
James Cole
90d73228f3 New translations firefly.php (Chinese Traditional) 2017-08-04 17:10:59 +02:00
James Cole
1c76fcd26b New translations firefly.php (Dutch) 2017-08-04 17:10:55 +02:00
James Cole
c26c4ddf15 New translations firefly.php (German) 2017-08-04 17:10:53 +02:00
James Cole
537bdb62da New translations firefly.php (French) 2017-08-04 17:10:49 +02:00
James Cole
b2ac2bd97a New translations firefly.php (Russian) 2017-08-04 17:10:32 +02:00
James Cole
aee6ea56b5 New translations validation.php (Russian) 2017-08-04 17:10:24 +02:00
James Cole
ff5506c842 New translations validation.php (German) 2017-08-04 17:10:16 +02:00
James Cole
94c5340fbf New translations validation.php (Polish) 2017-08-04 17:10:15 +02:00
James Cole
0e11026b60 New translations validation.php (Portuguese, Brazilian) 2017-08-04 17:10:14 +02:00
James Cole
1d8e953ebc New translations validation.php (Spanish) 2017-08-04 17:10:13 +02:00
James Cole
8708fba4bc New translations validation.php (Slovenian) 2017-08-04 17:10:12 +02:00
James Cole
bc1294ae61 New translations validation.php (French) 2017-08-04 17:10:10 +02:00
James Cole
308f05101e New translations validation.php (Dutch) 2017-08-04 17:10:09 +02:00
James Cole
f368739303 New translations validation.php (Chinese Traditional) 2017-08-04 17:10:07 +02:00
James Cole
1bca1b921b Fix import tests. 2017-08-04 16:24:44 +02:00
James Cole
3e513e92b1 Import routine is prepped for multi-source import (such as banks). 2017-08-04 15:56:14 +02:00
James Cole
194fe178c0 Refactor for #732 2017-08-04 15:48:26 +02:00
James Cole
5d10a19bfa First version of routine #732 2017-08-04 15:46:52 +02:00
James Cole
8f52a68526 New translations firefly.php (French) 2017-08-04 13:10:13 +02:00
James Cole
c67d0d59bb New translations firefly.php (French) 2017-08-04 13:00:08 +02:00
James Cole
4477064f17 New translations firefly.php (French) 2017-08-04 12:50:08 +02:00
James Cole
9dbe24b37c New translations csv.php (Portuguese, Brazilian) 2017-08-04 08:20:13 +02:00
James Cole
46a85295e8 New translations firefly.php (Portuguese, Brazilian) 2017-08-04 08:20:11 +02:00
James Cole
63170324a8 New translations form.php (Portuguese, Brazilian) 2017-08-04 08:20:08 +02:00
James Cole
4fd157b5f4 New translations firefly.php (Polish) 2017-08-03 21:00:23 +02:00
James Cole
e5406a0ea3 New translations firefly.php (Chinese Traditional) 2017-08-03 21:00:20 +02:00
James Cole
9b64ba21fd New translations firefly.php (Portuguese, Brazilian) 2017-08-03 21:00:17 +02:00
James Cole
18fcf07971 New translations firefly.php (Slovenian) 2017-08-03 21:00:14 +02:00
James Cole
d3404c6570 New translations firefly.php (Spanish) 2017-08-03 21:00:10 +02:00
James Cole
1878b5287b Cheap solution for #730 [skip ci] 2017-08-03 20:50:16 +02:00
James Cole
7f74545586 New translations firefly.php (German) 2017-07-30 14:10:38 +02:00
James Cole
a920894a8f New translations firefly.php (French) 2017-07-30 14:10:35 +02:00
James Cole
2c912456ce New translations firefly.php (Russian) 2017-07-30 14:10:23 +02:00
James Cole
ebda475972 New translations firefly.php (Dutch) 2017-07-30 14:10:17 +02:00
James Cole
05aace84e1 Fix tests for show() routines. 2017-07-30 13:57:46 +02:00
James Cole
1cfa1faccc Remove all time jumps because they’re unclear and complex. 2017-07-30 13:53:04 +02:00
James Cole
1caa393974 Simple cache routine. 2017-07-30 13:44:36 +02:00
James Cole
ef357ab6e5 Fix tests 2017-07-30 13:42:38 +02:00
James Cole
c39c5492ea Simplify controllers 2017-07-30 13:42:30 +02:00
James Cole
1a5d54f74f New translations firefly.php (Slovenian) 2017-07-30 10:40:53 +02:00
James Cole
13dc6c7dfb New translations firefly.php (Spanish) 2017-07-30 10:40:50 +02:00
James Cole
4c7dee69c2 New translations firefly.php (Portuguese, Brazilian) 2017-07-30 10:40:47 +02:00
James Cole
dc9cf7689d New translations firefly.php (Polish) 2017-07-30 10:40:44 +02:00
James Cole
778a408c6c New translations firefly.php (Chinese Traditional) 2017-07-30 10:40:42 +02:00
James Cole
2b7f3061d0 New translations firefly.php (Dutch) 2017-07-30 10:40:40 +02:00
James Cole
92903e1ec3 New translations firefly.php (German) 2017-07-30 10:40:37 +02:00
James Cole
c5a621010e New translations firefly.php (French) 2017-07-30 10:40:35 +02:00
James Cole
0b5b636578 New translations firefly.php (Russian) 2017-07-30 10:40:20 +02:00
James Cole
8fcdb91ba3 Will no longer support extended tag modes. 2017-07-30 10:22:14 +02:00
James Cole
f67d5f1197 Fix bug in filter. 2017-07-30 10:21:45 +02:00
James Cole
6e0e6203cc Some help text for attachment decrypter 2017-07-30 10:21:35 +02:00
James Cole
2694ce4148 Decryption routine for #671 2017-07-30 08:22:39 +02:00
James Cole
7c02b032f6 New translations firefly.php (Slovenian) 2017-07-29 14:40:52 +02:00
James Cole
deb7754cb9 New translations firefly.php (Spanish) 2017-07-29 14:40:50 +02:00
James Cole
624f3c60bd New translations firefly.php (Portuguese, Brazilian) 2017-07-29 14:40:46 +02:00
James Cole
8a8e792faa New translations firefly.php (Polish) 2017-07-29 14:40:44 +02:00
James Cole
bc836011bc New translations firefly.php (Chinese Traditional) 2017-07-29 14:40:41 +02:00
James Cole
107eedfb49 New translations firefly.php (Dutch) 2017-07-29 14:40:38 +02:00
James Cole
61a7dcda23 New translations firefly.php (German) 2017-07-29 14:40:36 +02:00
James Cole
873ca4f438 New translations firefly.php (French) 2017-07-29 14:40:33 +02:00
James Cole
29221c2901 New translations firefly.php (Russian) 2017-07-29 14:40:19 +02:00
James Cole
eac9613df7 Fix for #648 2017-07-29 14:25:54 +02:00
James Cole
184d5d25a6 New translations csv.php (Spanish) 2017-07-29 08:40:46 +02:00
James Cole
ae33411566 New translations csv.php (Slovenian) 2017-07-29 08:40:34 +02:00
James Cole
479ebcc3fa New translations csv.php (Portuguese, Brazilian) 2017-07-29 08:40:33 +02:00
James Cole
1ae572cf30 New translations csv.php (Chinese Traditional) 2017-07-29 08:40:29 +02:00
James Cole
ac6e16688d New translations csv.php (Dutch) 2017-07-29 08:40:28 +02:00
James Cole
69159e0271 New translations csv.php (French) 2017-07-29 08:40:28 +02:00
James Cole
cae35d6a5a New translations csv.php (Polish) 2017-07-29 08:40:27 +02:00
James Cole
df9b65e296 New translations csv.php (German) 2017-07-29 08:40:26 +02:00
James Cole
fb0b34a6a0 New translations csv.php (Russian) 2017-07-29 08:40:22 +02:00
James Cole
db3b822aef Include warning for #722 2017-07-29 08:27:39 +02:00
James Cole
f4994ef151 Also store links when importing data. 2017-07-28 14:52:01 +02:00
James Cole
8e27291417 Tags no longer mappable. 2017-07-28 14:40:53 +02:00
James Cole
aae9ad78e5 This should fix the tests for now. 2017-07-26 18:40:48 +02:00
James Cole
fb3efbfc66 Fix parameter count. 2017-07-26 16:40:25 +02:00
James Cole
0f8a66609a Fix controller for #718 2017-07-26 16:40:14 +02:00
James Cole
b3bb8c386f Fix routes for #718 2017-07-26 16:40:00 +02:00
James Cole
b3b5e0e155 This will disable the PHP 7.0 tests. 2017-07-25 21:01:37 +02:00
James Cole
99a0bf1286 This fixes #717 2017-07-25 21:01:25 +02:00
James Cole
650f0ee752 Merge branch 'hotfix/4.6.3.1' into develop 2017-07-23 20:02:46 +02:00
James Cole
cd373791ac Updated composer file. 2017-07-23 20:00:26 +02:00
James Cole
7b03b0c5fc Some PHP 7.1 compatible code. 2017-07-23 19:06:24 +02:00
672 changed files with 23351 additions and 15508 deletions

4
.dockerignore Normal file
View File

@@ -0,0 +1,4 @@
# Ignore composer specific files and vendor folder
composer.phar
composer.lock
vendor

View File

@@ -1,7 +1,6 @@
APP_ENV=${FF_APP_ENV}
APP_DEBUG=false
APP_FORCE_SSL=false
APP_FORCE_ROOT=
APP_NAME=FireflyIII
APP_KEY=${FF_APP_KEY}
APP_LOG=daily
APP_LOG_LEVEL=warning
@@ -28,7 +27,7 @@ REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_FROM=changeme@example.com
MAIL_USERNAME=null
@@ -41,6 +40,8 @@ SHOW_INCOMPLETE_TRANSLATIONS=false
CACHE_PREFIX=firefly
EXCHANGE_RATE_SERVICE=fixerio
GOOGLE_MAPS_API_KEY=
ANALYTICS_ID=
SITE_OWNER=mail@example.com
@@ -48,7 +49,7 @@ USE_ENCRYPTION=true
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=
PUSHER_ID=
DEMO_USERNAME=
DEMO_PASSWORD=

7
.env.example Executable file → Normal file
View File

@@ -1,7 +1,6 @@
APP_ENV=production
APP_DEBUG=false
APP_FORCE_SSL=false
APP_FORCE_ROOT=
APP_NAME=FireflyIII
APP_KEY=SomeRandomStringOf32CharsExactly
APP_LOG=daily
APP_LOG_LEVEL=warning
@@ -28,7 +27,7 @@ REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_FROM=changeme@example.com
MAIL_USERNAME=null
@@ -50,7 +49,7 @@ USE_ENCRYPTION=true
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=
PUSHER_ID=
DEMO_USERNAME=
DEMO_PASSWORD=

View File

@@ -1,7 +1,6 @@
APP_ENV=production
APP_DEBUG=true
APP_FORCE_SSL=false
APP_FORCE_ROOT=
APP_NAME=FireflyIII
APP_KEY=SomeRandomStringOf32CharsExactly
APP_LOG=syslog
APP_LOG_LEVEL=debug
@@ -28,7 +27,7 @@ REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=smtp
MAIL_HOST=mailtrap.io
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_FROM=changeme@example.com
MAIL_USERNAME=null
@@ -41,6 +40,8 @@ SHOW_INCOMPLETE_TRANSLATIONS=false
CACHE_PREFIX=firefly
EXCHANGE_RATE_SERVICE=fixerio
GOOGLE_MAPS_API_KEY=
ANALYTICS_ID=
SITE_OWNER=mail@example.com
@@ -48,8 +49,7 @@ USE_ENCRYPTION=true
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=
PUSHER_ID=
DEMO_USERNAME=
DEMO_PASSWORD=

21
.env.testing Executable file → Normal file
View File

@@ -1,7 +1,6 @@
APP_ENV=testing
APP_DEBUG=true
APP_FORCE_SSL=false
APP_FORCE_ROOT=
APP_NAME=FireflyIII
APP_KEY=TestTestTestTestTestTestTestTest
APP_LOG=daily
APP_LOG_LEVEL=debug
@@ -11,7 +10,7 @@ DB_CONNECTION=sqlite
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USERNAME=homestead
DB_PASSWORD=secret
DB_PASSWORD=
BROADCAST_DRIVER=log
CACHE_DRIVER=file
@@ -26,8 +25,8 @@ REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379
MAIL_DRIVER=log
MAIL_HOST=mailtrap.io
MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_FROM=changeme@example.com
MAIL_USERNAME=null
@@ -38,9 +37,19 @@ SEND_REGISTRATION_MAIL=true
SEND_ERROR_MESSAGE=true
SHOW_INCOMPLETE_TRANSLATIONS=false
CACHE_PREFIX=firefly
EXCHANGE_RATE_SERVICE=fixerio
GOOGLE_MAPS_API_KEY=
ANALYTICS_ID=
SITE_OWNER=mail@example.com
USE_ENCRYPTION=true
PUSHER_KEY=
PUSHER_SECRET=
PUSHER_APP_ID=
PUSHER_ID=
DEMO_USERNAME=
DEMO_PASSWORD=

2
.gitattributes vendored Executable file → Normal file
View File

@@ -1,3 +1,5 @@
* text=auto
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
CHANGELOG.md export-ignore

6
.gitignore vendored Executable file → Normal file
View File

@@ -1,8 +1,14 @@
/node_modules
/public/hot
/public/storage
/storage/*.key
/vendor
/.vagrant
Homestead.json
Homestead.yaml
npm-debug.log
yarn-error.log
.env
public/google*.html
report.html
composer.phar

View File

@@ -1,6 +1,5 @@
language: php
php:
- 7.0
- 7.1
cache:

View File

@@ -2,11 +2,126 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [4.6.6] - 2015-05-25
### Added
- #826, reported by @pkoziol.
- #855, by @ms32035
- #786, by @SmilingWorlock
- #875, by @gavu
- #834, by @gavu (and others)
### Changed
- Upgraded to Laravel 5.5
- Add version parameter to CSS and JS files
- #823, #824 fixed Docker config by @DieBauer
### Fixed
- #830
- #822, reported by @gazben
- #827, reported by @pkoziol
- #835, reported by @gavu
- #836, reported by @pkoziol
- #838, reported by @gavu
- #839, reported by @gavu
- #843, reported by @gavu
- #837, reported by @gavu
- #845, reported by @gavu
- #846, reported by @gavu
- #848, reported by @gavu
- #854, reported by @gavu
- #866, reported by @pkoziol
- #847, reported by @gavu
- #853, reported by @gavu
- #857, reported by @pkoziol
- #865, reported by @simonsmiley
- #826, reported by @pkoziol
- #856, reported by @ms32035
- #860, reported by @gavu
- #861, reported by @gavu
- #870, reported by @gavu
## [4.6.5] - 2017-09-09
### Added
- #616, The ability to link transactions
- #763, as suggested by @tannie
- #770, as suggested by @skibbipl
- #780, as suggested by @skibbipl
- #784, as suggested by @SmilingWorlock
- Lots of code for future support of automated Bunq imports
### Changed
- Rewrote the export routine
- #782, as suggested by @NiceGuyIT
- #800, as suggested by @jleeong
### Fixed
- #724, reported by @skibbipl
- #738, reported by @skibbipl
- #760, reported by @leander091
- #764, reported by @tannie
- #792, reported by @jleeong
- #793, reported by @nicoschreiner
- #797, reported by @leander091
- #801, reported by @pkoziol
- #803, reported by @pkoziol
- #805, reported by @pkoziol
- #806, reported by @pkoziol
- #807, reported by @pkoziol
- #808, reported by @pkoziol
- #809, reported by @pkoziol
- #814, reported by @nicoschreiner
- #818, reported by @gavu
- #819, reported by @DieBauer
- #820, reported by @simonsmiley
- Various other fixes
## [4.6.4] - 2017-08-13
### Added
- PHP7.1 support
- Routine to decrypt attachments from the command line, for issue #671
- A routine that can check if your password has been stolen in the past.
- Split transaction shows amount left to be split
### Changed
- Importer can (potentially) handle new import routines such as banks.
- Importer can fall back from JSON errors
### Deprecated
- Initial release.
### Removed
- PHP7.0 support
- Support for extended tag modes
- Remove "time jumps" to non-empty periods
### Fixed
- #717, reported by @NiceGuyIT
- #718, reported by @wtercato
- #722, reported by @simonsmiley
- #648, reported by @skibbipl
- #730, reported by @ragnarkarlsson
- #733, reported by @xpfgsyb
- #735, reported by @kristophr
- #739, reported by @skibbipl
- #515, reported by @schwalberich
- #743, reported by @simonsmiley
- #746, reported by @tannie
- #747, reported by @tannie
### Security
- Initial release.
## [4.6.3.1] - 2017-07-23
### Fixed
- Hotfix to close issue #715
## [4.6.3] - 2017-07-23
This will be the last release to support PHP 7.0.

View File

@@ -23,28 +23,31 @@ RUN docker-php-ext-install -j$(nproc) curl gd intl json mcrypt readline tidy zip
# Generate locales supported by firefly
RUN echo "en_US.UTF-8 UTF-8\nde_DE.UTF-8 UTF-8\nnl_NL.UTF-8 UTF-8\npt_BR.UTF-8 UTF-8" > /etc/locale.gen && locale-gen
COPY ./docker/apache2.conf /etc/apache2/apache2.conf
# Enable apache mod rewrite..
RUN a2enmod rewrite
# Enable apache mod ssl..
RUN a2enmod ssl
# Setup the Composer installer
RUN curl -o /tmp/composer-setup.php https://getcomposer.org/installer && \
curl -o /tmp/composer-setup.sig https://composer.github.io/installer.sig && \
php -r "if (hash('SHA384', file_get_contents('/tmp/composer-setup.php')) !== trim(file_get_contents('/tmp/composer-setup.sig'))) { unlink('/tmp/composer-setup.php'); echo 'Invalid installer' . PHP_EOL; exit(1); }" && \
chmod +x /tmp/composer-setup.php && \
php /tmp/composer-setup.php && \
mv composer.phar /usr/local/bin/composer && \
rm -f /tmp/composer-setup.{php,sig}
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
ADD . /var/www/firefly-iii
RUN chown -R www-data:www-data /var/www/
ADD docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
# Copy Apache Configs
COPY ./docker/apache-firefly.conf /etc/apache2/sites-available/000-default.conf
USER www-data
ENV FIREFLY_PATH /var/www/firefly-iii
WORKDIR /var/www/firefly-iii
WORKDIR $FIREFLY_PATH
RUN composer install --no-scripts --no-dev
# The working directory
COPY . $FIREFLY_PATH
USER root
RUN chown -R www-data:www-data /var/www && chmod -R 775 $FIREFLY_PATH/storage
ENTRYPOINT ["/var/www/firefly-iii/docker/entrypoint.sh"]
RUN composer install --prefer-dist --no-dev --no-scripts
EXPOSE 80
ENTRYPOINT ["docker/entrypoint.sh"]

View File

@@ -1,26 +1,36 @@
# Firefly III: A personal finances manager
[![Requires PHP7](https://img.shields.io/badge/php-7.0-red.svg)](https://secure.php.net/downloads.php) [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](https://packagist.org/packages/grumpydictator/firefly-iii) [![License](https://img.shields.io/badge/license-CC%20BY--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-sa/4.0/) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)
[![Requires PHP7.1](https://img.shields.io/badge/php-7.1-red.svg)](https://secure.php.net/downloads.php) [![Latest Stable Version](https://poser.pugx.org/grumpydictator/firefly-iii/v/stable)](https://packagist.org/packages/grumpydictator/firefly-iii) [![License](https://img.shields.io/badge/license-CC%20BY--SA%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-sa/4.0/) [![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=44UKUT455HUFA)
[![The index of Firefly III](https://i.nder.be/hurdhgyg/400)](https://i.nder.be/h2b37243) [![The account overview of Firefly III](https://i.nder.be/hnkfkdpr/400)](https://i.nder.be/hv70pbwc)
[![The useful financial reports of Firefly III](https://i.nder.be/h7sk6nb7/400)](https://i.nder.be/ccn0u2mp) [![Even more useful reports in Firefly III](https://i.nder.be/g237hr35/400)](https://i.nder.be/gm8hbh7z)
"Firefly III" is a financial manager. It can help you keep track of expenses, income, budgets and everything in between. It even supports credit cards, shared household accounts and savings accounts! It's pretty fancy. You should use it to save and organise money.
"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.
## Try it out!
[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/firefly-iii/firefly-iii/tree/master)
Firefly III can be run on Heroku. Register for a free Heroku account and instantly run Firefly III on your very own cloud instance. There is also a [demo site](https://firefly-iii.nder.be) with an example financial administration already present.
Firefly III can be run on Heroku.
Register for a free Heroku account and instantly run Firefly III on your very own cloud instance.
There is also a [demo site](https://firefly-iii.nder.be) with an example financial administration already present.
## Getting started
To install Firefly III, you'll need a web server (preferrably on Linux) and access to the command line. Then, please read the [installation guide](https://firefly-iii.github.io/using-installing.html).
To install Firefly III, you'll need a web server (preferrably on Linux) and access to the command line.
Then, please read the [installation guide](https://firefly-iii.github.io/using-installing.html).
At the moment, installation is fairly complex. I hope to improve this in the future. If you need support, please open a ticket.
## 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.
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.
@@ -31,7 +41,8 @@ Firefly works on the principle that if you know where you're money is going, you
- 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 is pretty awesome. [You can read more about Firefly III, and its features, on the Github Pages](https://firefly-iii.github.io/).
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 Github Pages](https://firefly-iii.github.io/).
### Contributing

View File

@@ -0,0 +1,143 @@
<?php
/**
* CreateExport.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use Carbon\Carbon;
use FireflyIII\Export\ProcessorInterface;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use Illuminate\Console\Command;
use Storage;
/**
* Class CreateExport
*
* Generates export from the command line.
*
* @package FireflyIII\Console\Commands
*/
class CreateExport extends Command
{
use VerifiesAccessToken;
/**
* The console command description.
*
* @var string
*/
protected $description = 'Use this command to create a new import. Your user ID can be found on the /profile page.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature
= 'firefly:create-export
{--user= : The user ID that the import should import for.}
{--token= : The user\'s access token.}
{--with_attachments : Include user\'s attachments?}
{--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
*/
public function handle()
{
if (!$this->verifyAccessToken()) {
$this->error('Invalid access token.');
return;
}
$this->line('Full export is running...');
// make repositories
/** @var UserRepositoryInterface $userRepository */
$userRepository = app(UserRepositoryInterface::class);
/** @var ExportJobRepositoryInterface $jobRepository */
$jobRepository = app(ExportJobRepositoryInterface::class);
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
/** @var JournalRepositoryInterface $journalRepository */
$journalRepository = app(JournalRepositoryInterface::class);
// set user
$user = $userRepository->find(intval($this->option('user')));
$jobRepository->setUser($user);
$journalRepository->setUser($user);
$accountRepository->setUser($user);
// first date
$firstJournal = $journalRepository->first();
$first = new Carbon;
if (!is_null($firstJournal->id)) {
$first = $firstJournal->date;
}
// create job and settings.
$job = $jobRepository->create();
$settings = [
'accounts' => $accountRepository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]),
'startDate' => $first,
'endDate' => new Carbon,
'exportFormat' => 'csv',
'includeAttachments' => $this->option('with_attachments'),
'includeOldUploads' => $this->option('with_uploads'),
'job' => $job,
];
/** @var ProcessorInterface $processor */
$processor = app(ProcessorInterface::class);
$processor->setSettings($settings);
$processor->collectJournals();
$processor->convertJournals();
$processor->exportJournals();
if ($settings['includeAttachments']) {
$processor->collectAttachments();
}
if ($settings['includeOldUploads']) {
$processor->collectOldUploads();
}
$processor->createZipFile();
$disk = Storage::disk('export');
$fileName = sprintf('export-%s.zip', date('Y-m-d_H-i-s'));
$disk->move($job->key . '.zip', $fileName);
$this->line('The export has finished! You can find the ZIP file in this location:');
$this->line(storage_path(sprintf('export/%s', $fileName)));
return;
}
}

View File

@@ -30,6 +30,7 @@ use Monolog\Formatter\LineFormatter;
*/
class CreateImport extends Command
{
use VerifiesAccessToken;
/**
* The console command description.
*
@@ -42,7 +43,13 @@ class CreateImport extends Command
*
* @var string
*/
protected $signature = 'firefly:create-import {file} {configuration} {--user=1} {--type=csv} {--start}';
protected $signature = 'firefly:create-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.}
{--token= : The user\'s access token.}
{--start : Starts the job immediately.}';
/**
* Create a new command instance.
@@ -54,11 +61,18 @@ class CreateImport extends Command
}
/**
* Run the command.
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
*/
public function handle()
{
if (!$this->verifyAccessToken()) {
$this->error('Invalid access token.');
return;
}
/** @var UserRepositoryInterface $userRepository */
$userRepository = app(UserRepositoryInterface::class);
$file = $this->argument('file');
@@ -133,6 +147,8 @@ class CreateImport extends Command
}
/**
* Verify user inserts correct arguments.
*
* @return bool
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five exactly.
*/
@@ -146,12 +162,12 @@ class CreateImport extends Command
$cwd = getcwd();
$validTypes = array_keys(config('firefly.import_formats'));
$type = strtolower($this->option('type'));
if (is_null($user->id)) {
$this->error(sprintf('There is no user with ID %d.', $this->option('user')));
return false;
}
if (!in_array($type, $validTypes)) {
$this->error(sprintf('Cannot import file of type "%s"', $type));

View File

@@ -0,0 +1,108 @@
<?php
/**
* DecryptAttachment.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Console\Commands;
use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface;
use Illuminate\Console\Command;
use Log;
/**
* Class DecryptAttachment
*
* @package FireflyIII\Console\Commands
*/
class DecryptAttachment extends Command
{
/**
* The console command description.
*
* @var string
*/
protected $description = 'Decrypts an attachment and dumps the content in a file in the given directory.';
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature
= '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.ExcessiveMethodLength)
*
*/
public function handle()
{
/** @var AttachmentRepositoryInterface $repository */
$repository = app(AttachmentRepositoryInterface::class);
$attachmentId = intval($this->argument('id'));
$attachment = $repository->findWithoutUser($attachmentId);
$attachmentName = trim($this->argument('name'));
$storagePath = realpath(trim($this->argument('directory')));
if (is_null($attachment->id)) {
$this->error(sprintf('No attachment with id #%d', $attachmentId));
Log::error(sprintf('DecryptAttachment: No attachment with id #%d', $attachmentId));
return;
}
if ($attachmentName !== $attachment->filename) {
$this->error('File name does not match.');
Log::error('DecryptAttachment: File name does not match.');
return;
}
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;
}
if (!is_writable($storagePath)) {
$this->error(sprintf('Path "%s" is not writable.', $storagePath));
Log::error(sprintf('DecryptAttachment: Path "%s" is not writable.', $storagePath));
return;
}
$fullPath = $storagePath . DIRECTORY_SEPARATOR . $attachment->filename;
$content = $repository->getContent($attachment);
$this->line(sprintf('Going to write content for attachment #%d into file "%s"', $attachment->id, $fullPath));
$result = file_put_contents($fullPath, $content);
if ($result === false) {
$this->error('Could not write to file.');
return;
}
$this->info(sprintf('%d bytes written. Exiting now..', $result));
return;
}
}

View File

@@ -51,7 +51,7 @@ class Import extends Command
}
/**
*
* Run the import routine.
*/
public function handle()
{
@@ -91,6 +91,8 @@ class Import extends Command
}
/**
* Check if job is valid to be imported.
*
* @param ImportJob $job
*
* @return bool

View File

@@ -20,24 +20,25 @@ use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\LimitRepetition;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use Illuminate\Console\Command;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Database\QueryException;
use Illuminate\Support\Collection;
use Log;
use Preferences;
use Schema;
use Steam;
/**
* Class UpgradeDatabase
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // it just touches a lot of things.
*
* Upgrade user database.
*
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // it just touches a lot of things.
* @package FireflyIII\Console\Commands
*/
class UpgradeDatabase extends Command
@@ -71,76 +72,26 @@ class UpgradeDatabase extends Command
{
$this->setTransactionIdentifier();
$this->migrateRepetitions();
$this->repairPiggyBanks();
$this->updateAccountCurrencies();
$this->updateJournalCurrencies();
$this->currencyInfoToTransactions();
$this->verifyCurrencyInfo();
$this->line('Updating currency information..');
$this->updateTransferCurrencies();
$this->updateOtherCurrencies();
$this->info('Firefly III database is up to date.');
return;
}
/**
* Moves the currency id info to the transaction instead of the journal.
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // cannot be helped.
* Migrate budget repetitions to new format where the end date is in the budget limit as well,
* making the limit_repetition table obsolete.
*/
private function currencyInfoToTransactions()
public function migrateRepetitions(): void
{
$count = 0;
$set = TransactionJournal::with('transactions')->get();
/** @var TransactionJournal $journal */
foreach ($set as $journal) {
/** @var Transaction $transaction */
foreach ($journal->transactions as $transaction) {
if (is_null($transaction->transaction_currency_id)) {
$transaction->transaction_currency_id = $journal->transaction_currency_id;
$transaction->save();
$count++;
}
}
// read and use the foreign amounts when present.
if ($journal->hasMeta('foreign_amount')) {
$amount = Steam::positive($journal->getMeta('foreign_amount'));
// update both transactions:
foreach ($journal->transactions as $transaction) {
$transaction->foreign_amount = $amount;
if (bccomp($transaction->amount, '0') === -1) {
// update with negative amount:
$transaction->foreign_amount = bcmul($amount, '-1');
}
// set foreign currency id:
$transaction->foreign_currency_id = intval($journal->getMeta('foreign_currency_id'));
$transaction->save();
}
$journal->deleteMeta('foreign_amount');
$journal->deleteMeta('foreign_currency_id');
}
}
$this->line(sprintf('Updated currency information for %d transactions', $count));
}
/**
* Migrate budget repetitions to new format.
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's 5.
*/
private function migrateRepetitions()
{
if (!Schema::hasTable('budget_limits')) {
return;
}
// get all budget limits with end_date NULL
$set = BudgetLimit::whereNull('end_date')->get();
if ($set->count() > 0) {
$this->line(sprintf('Found %d budget limit(s) to update', $set->count()));
}
/** @var BudgetLimit $budgetLimit */
foreach ($set as $budgetLimit) {
// get limit repetition (should be just one):
/** @var LimitRepetition $repetition */
$repetition = $budgetLimit->limitrepetitions()->first();
if (!is_null($repetition)) {
@@ -150,59 +101,30 @@ class UpgradeDatabase extends Command
$repetition->delete();
}
}
return;
}
/**
* Make sure there are only transfers linked to piggy bank events.
* This method gives all transactions which are part of a split journal (so more than 2) a sort of "order" so they are easier
* to easier to match to their counterpart. When a journal is split, it has two or three transactions: -3, -4 and -5 for example.
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // cannot be helped.
* In the database this is reflected as 6 transactions: -3/+3, -4/+4, -5/+5.
*
* When either of these are the same amount, FF3 can't keep them apart: +3/-3, +3/-3, +3/-3. This happens more often than you would
* think. So each set gets a number (1,2,3) to keep them apart.
*/
private function repairPiggyBanks()
{
// if table does not exist, return false
if (!Schema::hasTable('piggy_bank_events')) {
return;
}
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
/** @var PiggyBankEvent $event */
foreach ($set as $event) {
if (is_null($event->transaction_journal_id)) {
continue;
}
/** @var TransactionJournal $journal */
$journal = $event->transactionJournal()->first();
if (is_null($journal)) {
continue;
}
$type = $journal->transactionType->type;
if ($type !== TransactionType::TRANSFER) {
$event->transaction_journal_id = null;
$event->save();
$this->line(sprintf('Piggy bank #%d was referenced by an invalid event. This has been fixed.', $event->piggy_bank_id));
}
}
}
/**
* This is strangely complex, because the HAVING modifier is a no-no. And subqueries in Laravel are weird.
*/
private function setTransactionIdentifier()
public function setTransactionIdentifier(): void
{
// if table does not exist, return false
if (!Schema::hasTable('transaction_journals')) {
return;
}
$subQuery = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->groupBy(['transaction_journals.id'])
->select(['transaction_journals.id', DB::raw('COUNT(transactions.id) AS t_count')]);
$subQuery = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id')
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->groupBy(['transaction_journals.id'])
->select(['transaction_journals.id', DB::raw('COUNT(transactions.id) AS t_count')]);
$result = DB::table(DB::raw('(' . $subQuery->toSql() . ') AS derived'))
->mergeBindings($subQuery->getQuery())
->where('t_count', '>', 2)
@@ -210,55 +132,180 @@ class UpgradeDatabase extends Command
$journalIds = array_unique($result->pluck('id')->toArray());
foreach ($journalIds as $journalId) {
$this->updateJournal(intval($journalId));
$this->updateJournalidentifiers(intval($journalId));
}
return;
}
/**
* Make sure all accounts have proper currency info.
* 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.ExcessiveMethodLength)
*/
private function updateAccountCurrencies()
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 Account $account */
foreach ($accounts as $account) {
// get users preference, fall back to system pref.
$defaultCurrencyCode = Preferences::getForUser($account->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data;
$defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first();
$accountCurrency = intval($account->getMeta('currency_id'));
$openingBalance = $account->getOpeningBalance();
$obCurrency = intval($openingBalance->transaction_currency_id);
$accounts->each(
function (Account $account) {
// get users preference, fall back to system pref.
$defaultCurrencyCode = Preferences::getForUser($account->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data;
$defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first();
$accountCurrency = intval($account->getMeta('currency_id'));
$openingBalance = $account->getOpeningBalance();
$obCurrency = intval($openingBalance->transaction_currency_id);
// both 0? set to default currency:
if ($accountCurrency === 0 && $obCurrency === 0) {
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $defaultCurrency->id]);
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
continue;
// both 0? set to default currency:
if ($accountCurrency === 0 && $obCurrency === 0) {
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $defaultCurrency->id]);
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
return true;
}
// account is set to 0, opening balance is not?
if ($accountCurrency === 0 && $obCurrency > 0) {
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $obCurrency]);
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
return true;
}
// do not match and opening balance id is not null.
if ($accountCurrency !== $obCurrency && $openingBalance->id > 0) {
// update opening balance:
$openingBalance->transaction_currency_id = $accountCurrency;
$openingBalance->save();
$this->line(sprintf('Account #%d ("%s") now has a correct currency for opening balance.', $account->id, $account->name));
return true;
}
return true;
}
);
// account is set to 0, opening balance is not?
if ($accountCurrency === 0 && $obCurrency > 0) {
AccountMeta::create(['account_id' => $account->id, 'name' => 'currency_id', 'data' => $obCurrency]);
$this->line(sprintf('Account #%d ("%s") now has a currency setting (%s).', $account->id, $account->name, $defaultCurrencyCode));
continue;
return;
}
/**
* This routine verifies that withdrawals, deposits and opening balances have the correct currency settings for
* the accounts they are linked to.
*
* Both source and destination must match the respective currency preference of the related asset account.
* So FF3 must verify all transactions.
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function updateOtherCurrencies(): void
{
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::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) {
// get the transaction with the asset account in it:
/** @var Transaction $transaction */
$transaction = $journal->transactions()
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id')
->whereIn('account_types.type', [AccountType::DEFAULT, AccountType::ASSET])->first(['transactions.*']);
if (is_null($transaction)) {
return;
}
/** @var Account $account */
$account = $transaction->account;
$currency = $repository->find(intval($account->getMeta('currency_id')));
$transactions = $journal->transactions()->get();
$transactions->each(
function (Transaction $transaction) use ($currency) {
if (is_null($transaction->transaction_currency_id)) {
$transaction->transaction_currency_id = $currency->id;
$transaction->save();
}
// when mismatch in transaction:
if ($transaction->transaction_currency_id !== $currency->id) {
$transaction->foreign_currency_id = $transaction->transaction_currency_id;
$transaction->foreign_amount = $transaction->amount;
$transaction->transaction_currency_id = $currency->id;
$transaction->save();
}
}
);
// also update the journal, of course:
$journal->transaction_currency_id = $currency->id;
$journal->save();
}
);
// do not match:
if ($accountCurrency !== $obCurrency) {
// update opening balance:
$openingBalance->transaction_currency_id = $accountCurrency;
$openingBalance->save();
$this->line(sprintf('Account #%d ("%s") now has a correct currency for opening balance.', $account->id, $account->name));
continue;
return;
}
/**
* This routine verifies that transfers have the correct currency settings for the accounts they are linked to.
* For transfers, this is can be a destructive routine since we FORCE them into a currency setting whether they
* like it or not. Previous routines MUST have set the currency setting for both accounts for this to work.
*
* A transfer always has the
*
* Both source and destination must match the respective currency preference. So FF3 must verify ALL
* transactions.
*/
public function updateTransferCurrencies()
{
$set = TransactionJournal
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transaction_types.type', TransactionType::TRANSFER)
->get(['transaction_journals.*']);
$set->each(
function (TransactionJournal $transfer) {
// select all "source" transactions:
/** @var Collection $transactions */
$transactions = $transfer->transactions()->where('amount', '<', 0)->get();
$transactions->each(
function (Transaction $transaction) {
$this->updateTransactionCurrency($transaction);
$this->updateJournalCurrency($transaction);
}
);
}
);
}
// opening balance 0, account not zero? just continue:
// both are equal, just continue:
/**
* This method makes sure that the transaction journal uses the currency given in the transaction.
*
* @param Transaction $transaction
*/
private function updateJournalCurrency(Transaction $transaction): void
{
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
$currency = $repository->find(intval($transaction->account->getMeta('currency_id')));
$journal = $transaction->transactionJournal;
if (!(intval($currency->id) === intval($journal->transaction_currency_id))) {
$this->line(
sprintf(
'Transfer #%d ("%s") has been updated to use %s instead of %s.', $journal->id, $journal->description, $currency->code,
$journal->transactionCurrency->code
)
);
$journal->transaction_currency_id = $currency->id;
$journal->save();
}
return;
}
/**
@@ -267,7 +314,7 @@ class UpgradeDatabase extends Command
*
* @param int $journalId
*/
private function updateJournal(int $journalId)
private function updateJournalidentifiers(int $journalId): void
{
$identifier = 0;
$processed = [];
@@ -295,121 +342,134 @@ class UpgradeDatabase extends Command
if (!is_null($opposing)) {
// give both a new identifier:
$transaction->identifier = $identifier;
$opposing->identifier = $identifier;
$transaction->save();
$opposing->identifier = $identifier;
$opposing->save();
$processed[] = $transaction->id;
$processed[] = $opposing->id;
}
$identifier++;
}
return;
}
/**
* Makes sure that withdrawals, deposits and transfers have
* a currency setting matching their respective accounts
*/
private function updateJournalCurrencies()
{
$types = [
TransactionType::WITHDRAWAL => '<',
TransactionType::DEPOSIT => '>',
];
$repository = app(CurrencyRepositoryInterface::class);
$notification = '%s #%d uses %s but should use %s. It has been updated. Please verify this in Firefly III.';
$transfer = 'Transfer #%d has been updated to use the correct currencies. Please verify this in Firefly III.';
$driver = DB::connection()->getDriverName();
$pgsql = ['pgsql', 'postgresql'];
foreach ($types as $type => $operator) {
$query = TransactionJournal
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')->leftJoin(
'transactions', function (JoinClause $join) use ($operator) {
$join->on('transaction_journals.id', '=', 'transactions.transaction_journal_id')->where('transactions.amount', $operator, '0');
}
)
->leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id')
->leftJoin('account_meta', 'account_meta.account_id', '=', 'accounts.id')
->where('transaction_types.type', $type)
->where('account_meta.name', 'currency_id');
if (in_array($driver, $pgsql)) {
$query->where('transaction_journals.transaction_currency_id', '!=', DB::raw('cast(account_meta.data as int)'));
}
if (!in_array($driver, $pgsql)) {
$query->where('transaction_journals.transaction_currency_id', '!=', DB::raw('account_meta.data'));
}
$set = $query->get(['transaction_journals.*', 'account_meta.data as expected_currency_id', 'transactions.amount as transaction_amount']);
/** @var TransactionJournal $journal */
foreach ($set as $journal) {
$expectedCurrency = $repository->find(intval($journal->expected_currency_id));
$line = sprintf($notification, $type, $journal->id, $journal->transactionCurrency->code, $expectedCurrency->code);
$journal->setMeta('foreign_amount', $journal->transaction_amount);
$journal->setMeta('foreign_currency_id', $journal->transaction_currency_id);
$journal->transaction_currency_id = $expectedCurrency->id;
$journal->save();
$this->line($line);
}
}
/*
* For transfers it's slightly different. Both source and destination
* must match the respective currency preference. So we must verify ALL
* transactions.
*/
$set = TransactionJournal
::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id')
->where('transaction_types.type', TransactionType::TRANSFER)
->get(['transaction_journals.*']);
/** @var TransactionJournal $journal */
foreach ($set as $journal) {
$updated = false;
/** @var Transaction $sourceTransaction */
$sourceTransaction = $journal->transactions()->where('amount', '<', 0)->first();
$sourceCurrency = $repository->find(intval($sourceTransaction->account->getMeta('currency_id')));
if ($sourceCurrency->id !== $journal->transaction_currency_id) {
$updated = true;
$journal->transaction_currency_id = $sourceCurrency->id;
$journal->save();
}
// destination
$destinationTransaction = $journal->transactions()->where('amount', '>', 0)->first();
$destinationCurrency = $repository->find(intval($destinationTransaction->account->getMeta('currency_id')));
if ($destinationCurrency->id !== $journal->transaction_currency_id) {
$updated = true;
$journal->deleteMeta('foreign_amount');
$journal->deleteMeta('foreign_currency_id');
$journal->setMeta('foreign_amount', $destinationTransaction->amount);
$journal->setMeta('foreign_currency_id', $destinationCurrency->id);
}
if ($updated) {
$line = sprintf($transfer, $journal->id);
$this->line($line);
}
}
}
/**
* This method makes sure that the tranaction uses the same currency as the source account does.
* If not, the currency is updated to include a reference to its original currency as the "foreign" currency.
*
* 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.
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
* @param Transaction $transaction
*/
private function verifyCurrencyInfo()
private function updateTransactionCurrency(Transaction $transaction): void
{
$count = 0;
$transactions = Transaction::get();
/** @var Transaction $transaction */
foreach ($transactions as $transaction) {
$currencyId = intval($transaction->transaction_currency_id);
$foreignId = intval($transaction->foreign_currency_id);
if ($currencyId === $foreignId) {
$transaction->foreign_currency_id = null;
$transaction->foreign_amount = null;
$transaction->save();
$count++;
}
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
$currency = $repository->find(intval($transaction->account->getMeta('currency_id')));
// has no currency ID? Must have, so fill in using account preference:
if (is_null($transaction->transaction_currency_id)) {
$transaction->transaction_currency_id = $currency->id;
Log::debug(sprintf('Transaction #%d has no currency setting, now set to %s', $transaction->id, $currency->code));
$transaction->save();
}
$this->line(sprintf('Updated currency information for %d transactions', $count));
// does not match the source account (see above)? Can be fixed
// when mismatch in transaction and NO foreign amount is set:
if ($transaction->transaction_currency_id !== $currency->id && is_null($transaction->foreign_amount)) {
Log::debug(
sprintf(
'Transaction #%d has a currency setting (#%d) that should be #%d. Amount remains %s, currency is changed.', $transaction->id,
$transaction->transaction_currency_id, $currency->id, $transaction->amount
)
);
$transaction->transaction_currency_id = $currency->id;
$transaction->save();
}
// grab opposing transaction:
/** @var TransactionJournal $journal */
$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')));
if (is_null($opposingCurrency->id)) {
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 ($opposingCurrency->id === $currency->id) {
// update both transactions to match:
$transaction->foreign_amount = null;
$transaction->foreign_currency_id = null;
$opposing->foreign_amount = null;
$opposing->foreign_currency_id = null;
$opposing->transaction_currency_id = $currency->id;
$transaction->save();
$opposing->save();
Log::debug(sprintf('Cleaned up transaction #%d and #%d', $transaction->id, $opposing->id));
return;
}
// if destination account currency is different, both transactions must have this currency as foreign currency id.
if ($opposingCurrency->id !== $currency->id) {
$transaction->foreign_currency_id = $opposingCurrency->id;
$opposing->foreign_currency_id = $opposingCurrency->id;
$transaction->save();
$opposing->save();
Log::debug(sprintf('Verified foreign currency ID of transaction #%d and #%d', $transaction->id, $opposing->id));
}
// if foreign amount of one is null and the other is not, use this to restore:
if (is_null($transaction->foreign_amount) && !is_null($opposing->foreign_amount)) {
$transaction->foreign_amount = bcmul(strval($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 (is_null($opposing->foreign_amount) && !is_null($transaction->foreign_amount)) {
$opposing->foreign_amount = bcmul(strval($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 (is_null($opposing->foreign_amount) && is_null($transaction->foreign_amount)) {
$foreignAmount = $journal->getMeta('foreign_amount');
if (is_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->save();
$opposing->save();
return;
}
$foreignPositive = app('steam')->positive(strval($foreignAmount));
Log::debug(
sprintf(
'Journal #%d has missing foreign currency info, try to restore from meta-data ("%s").', $transaction->transaction_journal_id, $foreignAmount
)
);
$transaction->foreign_amount = bcmul($foreignPositive, '-1');
$opposing->foreign_amount = $foreignPositive;
$transaction->save();
$opposing->save();
}
return;
}
}

View File

@@ -84,6 +84,9 @@ class UpgradeFireflyInstructions extends Command
}
}
/**
* Render instructions.
*/
private function installInstructions()
{
/** @var string $version */
@@ -102,7 +105,7 @@ class UpgradeFireflyInstructions extends Command
$this->boxed('');
if (is_null($text)) {
$this->boxed(sprintf('Thank you for installin Firefly III, v%s!', $version));
$this->boxed(sprintf('Thank you for installing Firefly III, v%s!', $version));
$this->boxedInfo('There are no extra installation instructions.');
$this->boxed('Firefly III should be ready for use.');
$this->boxed('');
@@ -131,6 +134,9 @@ class UpgradeFireflyInstructions extends Command
}
/**
* Render upgrade instructions.
*/
private function updateInstructions()
{
/** @var string $version */

View File

@@ -1,10 +1,34 @@
<?php
/**
* UseEncryption.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
/**
* UseEncryption.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace FireflyIII\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Str;
/**
* Class UseEncryption
*
* @package FireflyIII\Console\Commands
*/
class UseEncryption extends Command
{
/**
@@ -34,7 +58,6 @@ class UseEncryption extends Command
*/
public function handle()
{
//
$this->handleObjects('Account', 'name', 'encrypted');
$this->handleObjects('Bill', 'name', 'name_encrypted');
$this->handleObjects('Bill', 'match', 'match_encrypted');
@@ -45,6 +68,8 @@ class UseEncryption extends Command
}
/**
* Run each object and encrypt them (or not).
*
* @param string $class
* @param string $field
* @param string $indicator

View File

@@ -0,0 +1,69 @@
<?php
/**
* VerifiesAccessToken.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
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.
*
* @package FireflyIII\Console\Commands
*/
trait VerifiesAccessToken
{
/**
* Abstract method to make sure trait knows about method "option".
* @param null $key
*
* @return mixed
*/
abstract public function option($key = null);
/**
* Returns false when given token does not match given user token.
*
* @return bool
*/
protected function verifyAccessToken(): bool
{
$userId = intval($this->option('user'));
$token = strval($this->option('token'));
/** @var UserRepositoryInterface $repository */
$repository = app(UserRepositoryInterface::class);
$user = $repository->find($userId);
if (is_null($user->id)) {
Log::error(sprintf('verifyAccessToken(): no such user for input "%d"', $userId));
return false;
}
$accessToken = Preferences::getForUser($user, 'access_token', null);
if (is_null($accessToken)) {
Log::error(sprintf('User #%d has no access token, so cannot access command line options.', $userId));
return false;
}
if (!($accessToken->data === $token)) {
Log::error(sprintf('Invalid access token for user #%d.', $userId));
return false;
}
return true;
}
}

View File

@@ -17,6 +17,8 @@ use Crypt;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Budget;
use FireflyIII\Models\LinkType;
use FireflyIII\Models\PiggyBankEvent;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionType;
@@ -25,12 +27,15 @@ use FireflyIII\User;
use Illuminate\Console\Command;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Database\Eloquent\Builder;
use Preferences;
use Schema;
use stdClass;
/**
* Class VerifyDatabase
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*
* @package FireflyIII\Console\Commands
*/
class VerifyDatabase extends Command
@@ -69,33 +74,93 @@ class VerifyDatabase extends Command
$this->reportObject('budget');
$this->reportObject('category');
$this->reportObject('tag');
// accounts with no transactions.
$this->reportAccounts();
// budgets with no limits
$this->reportBudgetLimits();
// budgets with no transactions
// sum of transactions is not zero.
$this->reportSum();
// any deleted transaction journals that have transactions that are NOT deleted:
$this->reportJournals();
// deleted transactions that are connected to a not deleted journal.
$this->reportTransactions();
// deleted accounts that still have not deleted transactions or journals attached to them.
$this->reportDeletedAccounts();
// report on journals with no transactions at all.
$this->reportNoTransactions();
// transfers with budgets.
$this->reportTransfersBudgets();
// report on journals with the wrong types of accounts.
$this->reportIncorrectJournals();
$this->repairPiggyBanks();
$this->createLinkTypes();
$this->createAccessTokens();
}
/**
* Create user access tokens, if not present already.
*/
private function createAccessTokens()
{
$users = User::get();
/** @var User $user */
foreach ($users as $user) {
$pref = Preferences::getForUser($user, 'access_token', null);
if (is_null($pref)) {
$token = $user->generateAccessToken();
Preferences::setForUser($user, 'access_token', $token);
$this->line(sprintf('Generated access token for user %s', $user->email));
}
}
}
/**
* Create default link types if necessary.
*/
private function createLinkTypes()
{
$set = [
'Related' => ['relates to', 'relates to'],
'Refund' => ['(partially) refunds', 'is (partially) refunded by'],
'Paid' => ['(partially) pays for', 'is (partially) paid for by'],
'Reimbursement' => ['(partially) reimburses', 'is (partially) reimbursed by'],
];
foreach ($set as $name => $values) {
$link = LinkType::where('name', $name)->where('outward', $values[0])->where('inward', $values[1])->first();
if (is_null($link)) {
$link = new LinkType;
$link->name = $name;
$link->outward = $values[0];
$link->inward = $values[1];
}
$link->editable = false;
$link->save();
}
}
/**
* Eeport (and fix) piggy banks. Make sure there are only transfers linked to piggy bank events.
*/
private function repairPiggyBanks(): void
{
$set = PiggyBankEvent::with(['PiggyBank', 'TransactionJournal', 'TransactionJournal.TransactionType'])->get();
$set->each(
function (PiggyBankEvent $event) {
if (is_null($event->transaction_journal_id)) {
return true;
}
/** @var TransactionJournal $journal */
$journal = $event->transactionJournal()->first();
if (is_null($journal)) {
return true;
}
$type = $journal->transactionType->type;
if ($type !== TransactionType::TRANSFER) {
$event->transaction_journal_id = null;
$event->save();
$this->line(sprintf('Piggy bank #%d was referenced by an invalid event. This has been fixed.', $event->piggy_bank_id));
}
return true;
}
);
return;
}
/**
* Reports on accounts with no transactions.
*/
@@ -169,6 +234,9 @@ class VerifyDatabase extends Command
}
}
/**
* Report on journals with bad account types linked to them.
*/
private function reportIncorrectJournals()
{
$configuration = [
@@ -235,7 +303,7 @@ class VerifyDatabase extends Command
}
/**
*
* Report on journals without transactions.
*/
private function reportNoTransactions()
{
@@ -253,6 +321,8 @@ class VerifyDatabase extends Command
}
/**
* Report on things with no linked journals.
*
* @param string $name
*/
private function reportObject(string $name)
@@ -324,7 +394,7 @@ class VerifyDatabase extends Command
}
/**
*
* Report on transfers that have budgets.
*/
private function reportTransfersBudgets()
{

View File

@@ -1,53 +1,26 @@
<?php
declare(strict_types=1);
/**
* Kernel.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Console;
use FireflyIII\Console\Commands\CreateImport;
use FireflyIII\Console\Commands\EncryptFile;
use FireflyIII\Console\Commands\Import;
use FireflyIII\Console\Commands\ScanAttachments;
use FireflyIII\Console\Commands\UpgradeDatabase;
use FireflyIII\Console\Commands\UpgradeFireflyInstructions;
use FireflyIII\Console\Commands\UseEncryption;
use FireflyIII\Console\Commands\VerifyDatabase;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
/**
* Class Kernel
*
* @package FireflyIII\Console
* File to make sure commnds work.
*/
class Kernel extends ConsoleKernel
{
/**
* The bootstrap classes for the application.
*
* Next upgrade verify these are the same.
*
* @var array
*/
protected $bootstrappers
= [
'Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables',
'Illuminate\Foundation\Bootstrap\LoadConfiguration',
'Illuminate\Foundation\Bootstrap\HandleExceptions',
'Illuminate\Foundation\Bootstrap\RegisterFacades',
'Illuminate\Foundation\Bootstrap\SetRequestForConsole',
'Illuminate\Foundation\Bootstrap\RegisterProviders',
'Illuminate\Foundation\Bootstrap\BootProviders',
];
/**
* The Artisan commands provided by your application.
*
@@ -55,23 +28,29 @@ class Kernel extends ConsoleKernel
*/
protected $commands
= [
UpgradeFireflyInstructions::class,
VerifyDatabase::class,
Import::class,
CreateImport::class,
EncryptFile::class,
ScanAttachments::class,
UpgradeDatabase::class,
UseEncryption::class,
//
];
/**
* Register the Closure based commands for the application.
* Register the commands for the application.
*
* @return void
*/
protected function commands()
{
$this->load(__DIR__ . '/Commands');
require base_path('routes/console.php');
}
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
protected function schedule(Schedule $schedule)
{
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* AdminRequestedTestMessage.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Events;
use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
use Log;
/**
* Class AdminRequestedTestMessage
*
* @package FireflyIII\Events
*/
class AdminRequestedTestMessage extends Event
{
use SerializesModels;
public $ipAddress;
public $user;
/**
* Create a new event instance.
*
* @param User $user
* @param string $ipAddress
*/
public function __construct(User $user, string $ipAddress)
{
Log::debug(sprintf('Triggered AdminRequestedTestMessage for user #%d (%s) and IP %s!', $user->id, $user->email, $ipAddress));
$this->user = $user;
$this->ipAddress = $ipAddress;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* UserChangedEmail.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Events;
use FireflyIII\User;
use Illuminate\Queue\SerializesModels;
/**
* Class UserChangedEmail
*
* @package FireflyIII\Events
*/
class UserChangedEmail extends Event
{
use SerializesModels;
/** @var string */
public $ipAddress;
/** @var string */
public $newEmail;
/** @var string */
public $oldEmail;
/** @var User */
public $user;
/**
* UserChangedEmail constructor.
*
* @param User $user
* @param string $newEmail
* @param string $oldEmail
* @param string $ipAddress
*/
public function __construct(User $user, string $newEmail, string $oldEmail, string $ipAddress)
{
$this->user = $user;
$this->ipAddress = $ipAddress;
$this->oldEmail = $oldEmail;
$this->newEmail = $newEmail;
}
}

View File

@@ -1,50 +1,45 @@
<?php
declare(strict_types=1);
/**
* Handler.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Exceptions;
use ErrorException;
use Exception;
use FireflyIII\Jobs\MailError;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\Eloquent\ModelNotFoundException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Illuminate\Session\TokenMismatchException;
use Illuminate\Validation\ValidationException as ValException;
use Request;
use Symfony\Component\HttpKernel\Exception\HttpException;
/**
* Class Handler
*
* @package FireflyIII\Exceptions
*/
class Handler extends ExceptionHandler
{
/**
* A list of the exception types that should not be reported.
* A list of the inputs that are never flashed for validation exceptions.
*
* @var array
*/
protected $dontFlash
= [
'password',
'password_confirmation',
];
/**
* A list of the exception types that are not reported.
*
* @var array
*/
protected $dontReport
= [
AuthenticationException::class,
AuthorizationException::class,
HttpException::class,
ModelNotFoundException::class,
TokenMismatchException::class,
ValException::class,
//
];
/**
@@ -67,14 +62,13 @@ class Handler extends ExceptionHandler
return parent::render($request, $exception);
}
/**
* Report or log an exception.
*
* This is a great spot to send exceptions to Sentry, Bugsnag, etc.
*
* @param Exception $exception
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five.
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five its fine.
* @param \Exception $exception
*
* @return void
*/
@@ -107,22 +101,7 @@ class Handler extends ExceptionHandler
dispatch($job);
}
parent::report($exception);
}
/**
* Convert an authentication exception into an unauthenticated response.
*
* @param $request
*
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
*/
protected function unauthenticated($request)
{
if ($request->expectsJson()) {
return response()->json(['error' => 'Unauthenticated.'], 401);
}
return redirect()->guest('login');
}
}

View File

@@ -122,6 +122,7 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface
*/
private function getAttachments(): Collection
{
$this->repository->setUser($this->user);
$attachments = $this->repository->getBetween($this->start, $this->end);
return $attachments;

View File

@@ -15,6 +15,7 @@ namespace FireflyIII\Export\Collector;
use FireflyIII\Models\ExportJob;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
@@ -26,6 +27,8 @@ class BasicCollector
{
/** @var ExportJob */
protected $job;
/** @var User */
protected $user;
/** @var Collection */
private $entries;
@@ -58,7 +61,16 @@ class BasicCollector
*/
public function setJob(ExportJob $job)
{
$this->job = $job;
$this->job = $job;
$this->user = $job->user;
}
/**
* @param User $user
*/
public function setUser(User $user)
{
$this->user = $user;
}

View File

@@ -1,347 +0,0 @@
<?php
/**
* JournalExportCollector.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Export\Collector;
use Carbon\Carbon;
use DB;
use FireflyIII\Models\Transaction;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Steam;
/**
* Class JournalExportCollector
*
* @package FireflyIII\Export\Collector
*/
class JournalExportCollector extends BasicCollector implements CollectorInterface
{
/** @var Collection */
private $accounts;
/** @var Carbon */
private $end;
/** @var Carbon */
private $start;
/** @var Collection */
private $workSet;
/**
* @return bool
*/
public function run(): bool
{
/*
* Instead of collecting journals we collect transactions for the given accounts.
* We left join the OPPOSING transaction AND some journal data.
* After that we complement this info with budgets, categories, etc.
*
* This is way more efficient and will also work on split journals.
*/
$this->getWorkSet();
/*
* Extract:
* possible budget ids for journals
* possible category ids journals
* possible budget ids for transactions
* possible category ids for transactions
*
* possible IBAN and account numbers?
*
*/
$journals = $this->extractJournalIds();
$transactions = $this->extractTransactionIds();
// extend work set with category data from journals:
$this->categoryDataForJournals($journals);
// extend work set with category cate from transactions (overrules journals):
$this->categoryDataForTransactions($transactions);
// same for budgets:
$this->budgetDataForJournals($journals);
$this->budgetDataForTransactions($transactions);
$this->setEntries($this->workSet);
return true;
}
/**
* @param Collection $accounts
*/
public function setAccounts(Collection $accounts)
{
$this->accounts = $accounts;
}
/**
* @param Carbon $start
* @param Carbon $end
*/
public function setDates(Carbon $start, Carbon $end)
{
$this->start = $start;
$this->end = $end;
}
/**
* @param array $journals
*
* @return bool
*/
private function budgetDataForJournals(array $journals): bool
{
$set = DB::table('budget_transaction_journal')
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction_journal.budget_id')
->whereIn('budget_transaction_journal.transaction_journal_id', $journals)
->get(
[
'budget_transaction_journal.budget_id',
'budget_transaction_journal.transaction_journal_id',
'budgets.name',
'budgets.encrypted',
]
);
$set->each(
function ($obj) {
$obj->name = Steam::decrypt(intval($obj->encrypted), $obj->name);
}
);
$array = [];
foreach ($set as $obj) {
$array[$obj->transaction_journal_id] = ['id' => $obj->budget_id, 'name' => $obj->name];
}
$this->workSet->each(
function ($obj) use ($array) {
if (isset($array[$obj->transaction_journal_id])) {
$obj->budget_id = $array[$obj->transaction_journal_id]['id'];
$obj->budget_name = $array[$obj->transaction_journal_id]['name'];
}
}
);
return true;
}
/**
* @param array $transactions
*
* @return bool
*/
private function budgetDataForTransactions(array $transactions): bool
{
$set = DB::table('budget_transaction')
->leftJoin('budgets', 'budgets.id', '=', 'budget_transaction.budget_id')
->whereIn('budget_transaction.transaction_id', $transactions)
->get(
[
'budget_transaction.budget_id',
'budget_transaction.transaction_id',
'budgets.name',
'budgets.encrypted',
]
);
$set->each(
function ($obj) {
$obj->name = Steam::decrypt(intval($obj->encrypted), $obj->name);
}
);
$array = [];
foreach ($set as $obj) {
$array[$obj->transaction_id] = ['id' => $obj->budget_id, 'name' => $obj->name];
}
$this->workSet->each(
function ($obj) use ($array) {
// first transaction
if (isset($array[$obj->id])) {
$obj->budget_id = $array[$obj->id]['id'];
$obj->budget_name = $array[$obj->id]['name'];
}
}
);
return true;
}
/**
* @param array $journals
*
* @return bool
*/
private function categoryDataForJournals(array $journals): bool
{
$set = DB::table('category_transaction_journal')
->leftJoin('categories', 'categories.id', '=', 'category_transaction_journal.category_id')
->whereIn('category_transaction_journal.transaction_journal_id', $journals)
->get(
[
'category_transaction_journal.category_id',
'category_transaction_journal.transaction_journal_id',
'categories.name',
'categories.encrypted',
]
);
$set->each(
function ($obj) {
$obj->name = Steam::decrypt(intval($obj->encrypted), $obj->name);
}
);
$array = [];
foreach ($set as $obj) {
$array[$obj->transaction_journal_id] = ['id' => $obj->category_id, 'name' => $obj->name];
}
$this->workSet->each(
function ($obj) use ($array) {
if (isset($array[$obj->transaction_journal_id])) {
$obj->category_id = $array[$obj->transaction_journal_id]['id'];
$obj->category_name = $array[$obj->transaction_journal_id]['name'];
}
}
);
return true;
}
/**
* @param array $transactions
*
* @return bool
*/
private function categoryDataForTransactions(array $transactions): bool
{
$set = DB::table('category_transaction')
->leftJoin('categories', 'categories.id', '=', 'category_transaction.category_id')
->whereIn('category_transaction.transaction_id', $transactions)
->get(
[
'category_transaction.category_id',
'category_transaction.transaction_id',
'categories.name',
'categories.encrypted',
]
);
$set->each(
function ($obj) {
$obj->name = Steam::decrypt(intval($obj->encrypted), $obj->name);
}
);
$array = [];
foreach ($set as $obj) {
$array[$obj->transaction_id] = ['id' => $obj->category_id, 'name' => $obj->name];
}
$this->workSet->each(
function ($obj) use ($array) {
// first transaction
if (isset($array[$obj->id])) {
$obj->category_id = $array[$obj->id]['id'];
$obj->category_name = $array[$obj->id]['name'];
}
}
);
return true;
}
/**
* @return array
*/
private function extractJournalIds(): array
{
return $this->workSet->pluck('transaction_journal_id')->toArray();
}
/**
* @return array
*/
private function extractTransactionIds()
{
$set = $this->workSet->pluck('id')->toArray();
$opposing = $this->workSet->pluck('opposing_id')->toArray();
$complete = $set + $opposing;
return array_unique($complete);
}
/**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
private function getWorkSet()
{
$accountIds = $this->accounts->pluck('id')->toArray();
$this->workSet = Transaction::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->leftJoin(
'transactions AS opposing', function (JoinClause $join) {
$join->on('opposing.transaction_journal_id', '=', 'transactions.transaction_journal_id')
->where('opposing.amount', '=', DB::raw('transactions.amount * -1'))
->where('transactions.identifier', '=', DB::raw('opposing.identifier'));
}
)
->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')
->leftJoin('accounts AS opposing_accounts', 'opposing.account_id', '=', 'opposing_accounts.id')
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', 'transaction_types.id')
->leftJoin('transaction_currencies', 'transactions.transaction_currency_id', '=', 'transaction_currencies.id')
->whereIn('transactions.account_id', $accountIds)
->where('transaction_journals.user_id', $this->job->user_id)
->where('transaction_journals.date', '>=', $this->start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $this->end->format('Y-m-d'))
->where('transaction_journals.completed', 1)
->whereNull('transaction_journals.deleted_at')
->whereNull('transactions.deleted_at')
->whereNull('opposing.deleted_at')
->orderBy('transaction_journals.date', 'DESC')
->orderBy('transactions.identifier', 'ASC')
->get(
[
'transactions.id',
'transactions.amount',
'transactions.description',
'transactions.account_id',
'accounts.name as account_name',
'accounts.encrypted as account_name_encrypted',
'transactions.identifier',
'opposing.id as opposing_id',
'opposing.amount AS opposing_amount',
'opposing.description as opposing_description',
'opposing.account_id as opposing_account_id',
'opposing_accounts.name as opposing_account_name',
'opposing_accounts.encrypted as opposing_account_encrypted',
'opposing.identifier as opposing_identifier',
'transaction_journals.id as transaction_journal_id',
'transaction_journals.date',
'transaction_journals.description as journal_description',
'transaction_journals.encrypted as journal_encrypted',
'transaction_journals.transaction_type_id',
'transaction_types.type as transaction_type',
'transactions.transaction_currency_id',
'transaction_currencies.code AS transaction_currency_code',
]
);
}
}

View File

@@ -15,6 +15,7 @@ namespace FireflyIII\Export\Collector;
use Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Contracts\Filesystem\FileNotFoundException;
use Log;
use Storage;
@@ -29,8 +30,6 @@ class UploadCollector extends BasicCollector implements CollectorInterface
private $exportDisk;
/** @var \Illuminate\Contracts\Filesystem\Filesystem */
private $uploadDisk;
/** @var string */
private $vintageFormat;
/**
* AttachmentCollector constructor.
@@ -50,14 +49,6 @@ class UploadCollector extends BasicCollector implements CollectorInterface
public function run(): bool
{
Log::debug('Going to collect attachments', ['key' => $this->job->key]);
// file names associated with the old import routine.
$this->vintageFormat = sprintf('csv-upload-%d-', $this->job->user->id);
// collect old upload files (names beginning with "csv-upload".
$this->collectVintageUploads();
// then collect current upload files:
$this->collectModernUploads();
return true;
@@ -70,7 +61,8 @@ class UploadCollector extends BasicCollector implements CollectorInterface
*/
private function collectModernUploads(): bool
{
$set = $this->job->user->importJobs()->where('status', 'import_complete')->get(['import_jobs.*']);
$set = $this->job->user->importJobs()->whereIn('status', ['import_complete', 'finished'])->get(['import_jobs.*']);
Log::debug(sprintf('Found %d import jobs', $set->count()));
$keys = [];
if ($set->count() > 0) {
$keys = $set->pluck('key')->toArray();
@@ -83,59 +75,6 @@ class UploadCollector extends BasicCollector implements CollectorInterface
return true;
}
/**
* This method collects all the uploads that are uploaded using the "old" importer. So from before the summer of 2016.
*
* @return bool
*/
private function collectVintageUploads(): bool
{
// grab upload directory.
$files = $this->uploadDisk->files();
foreach ($files as $entry) {
$this->processVintageUpload($entry);
}
return true;
}
/**
* This method tells you when the vintage upload file was actually uploaded.
*
* @param string $entry
*
* @return string
*/
private function getVintageUploadDate(string $entry): string
{
// this is an original upload.
$parts = explode('-', str_replace(['.csv.encrypted', $this->vintageFormat], '', $entry));
$originalUpload = intval($parts[1]);
$date = date('Y-m-d \a\t H-i-s', $originalUpload);
return $date;
}
/**
* Tells you if a file name is a vintage upload.
*
* @param string $entry
*
* @return bool
*/
private function isVintageImport(string $entry): bool
{
$len = strlen($this->vintageFormat);
// file is part of the old import routine:
if (substr($entry, 0, $len) === $this->vintageFormat) {
return true;
}
return false;
}
/**
* @param string $key
*
@@ -153,7 +92,7 @@ class UploadCollector extends BasicCollector implements CollectorInterface
$content = '';
try {
$content = Crypt::decrypt($this->uploadDisk->get(sprintf('%s.upload', $key)));
} catch (DecryptException $e) {
} catch (FileNotFoundException | DecryptException $e) {
Log::error(sprintf('Could not decrypt old import file "%s". Skipped because: %s', $key, $e->getMessage()));
}
@@ -168,47 +107,4 @@ class UploadCollector extends BasicCollector implements CollectorInterface
return true;
}
/**
* If the file is a vintage upload, process it.
*
* @param string $entry
*
* @return bool
*/
private function processVintageUpload(string $entry): bool
{
if ($this->isVintageImport($entry)) {
$this->saveVintageImportFile($entry);
return true;
}
return false;
}
/**
* This will store the content of the old vintage upload somewhere.
*
* @param string $entry
*/
private function saveVintageImportFile(string $entry)
{
$content = '';
try {
$content = Crypt::decrypt($this->uploadDisk->get($entry));
} catch (DecryptException $e) {
Log::error('Could not decrypt old CSV import file ' . $entry . '. Skipped because ' . $e->getMessage());
}
if (strlen($content) > 0) {
// add to export disk.
$date = $this->getVintageUploadDate($entry);
$file = $this->job->key . '-Old import dated ' . $date . '.csv';
$this->exportDisk->put($file, $content);
$this->getEntries()->push($file);
}
}
}

View File

@@ -13,6 +13,7 @@ declare(strict_types=1);
namespace FireflyIII\Export\Entry;
use FireflyIII\Models\Transaction;
use Steam;
/**
@@ -30,6 +31,7 @@ use Steam;
*
* Class Entry
* @SuppressWarnings(PHPMD.LongVariable)
* @SuppressWarnings(PHPMD.TooManyFields)
*
* @package FireflyIII\Export\Entry
*/
@@ -37,24 +39,43 @@ final class Entry
{
// @formatter:off
public $journal_id;
public $transaction_id = 0;
public $date;
public $description;
public $currency_code;
public $amount;
public $foreign_currency_code = '';
public $foreign_amount = '0';
public $transaction_type;
public $source_account_id;
public $source_account_name;
public $asset_account_id;
public $asset_account_name;
public $asset_account_iban;
public $asset_account_bic;
public $asset_account_number;
public $asset_currency_code;
public $destination_account_id;
public $destination_account_name;
public $opposing_account_id;
public $opposing_account_name;
public $opposing_account_iban;
public $opposing_account_bic;
public $opposing_account_number;
public $opposing_currency_code;
public $budget_id;
public $budget_name;
public $category_id;
public $category_name;
public $bill_id;
public $bill_name;
public $notes;
public $tags;
// @formatter:on
/**
@@ -65,32 +86,74 @@ final class Entry
}
/**
* @param $object
* Converts a given transaction (as collected by the collector) into an export entry.
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // complex but little choice.
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // cannot be helped
*
* @param Transaction $transaction
*
* @return Entry
*/
public static function fromObject($object): Entry
public static function fromTransaction(Transaction $transaction): Entry
{
$entry = new self;
$entry->journal_id = $object->transaction_journal_id;
$entry->description = Steam::decrypt(intval($object->journal_encrypted), $object->journal_description);
$entry->amount = $object->amount;
$entry->date = $object->date;
$entry->transaction_type = $object->transaction_type;
$entry->currency_code = $object->transaction_currency_code;
$entry->source_account_id = $object->account_id;
$entry->source_account_name = Steam::decrypt(intval($object->account_name_encrypted), $object->account_name);
$entry->destination_account_id = $object->opposing_account_id;
$entry->destination_account_name = Steam::decrypt(intval($object->opposing_account_encrypted), $object->opposing_account_name);
$entry->category_id = $object->category_id ?? '';
$entry->category_name = $object->category_name ?? '';
$entry->budget_id = $object->budget_id ?? '';
$entry->budget_name = $object->budget_name ?? '';
// update description when transaction description is different:
if (!is_null($object->description) && $object->description !== $entry->description) {
$entry->description = $entry->description . ' (' . $object->description . ')';
$entry = new self;
$entry->journal_id = $transaction->journal_id;
$entry->transaction_id = $transaction->id;
$entry->date = $transaction->date->format('Ymd');
$entry->description = $transaction->description;
if (strlen(strval($transaction->transaction_description)) > 0) {
$entry->description = $transaction->transaction_description . '(' . $transaction->description . ')';
}
$entry->currency_code = $transaction->transactionCurrency->code;
$entry->amount = round($transaction->transaction_amount, $transaction->transactionCurrency->decimal_places);
$entry->foreign_currency_code = is_null($transaction->foreign_currency_id) ? null : $transaction->foreignCurrency->code;
$entry->foreign_amount = is_null($transaction->foreign_currency_id)
? null
: strval(
round(
$transaction->transaction_foreign_amount, $transaction->foreignCurrency->decimal_places
)
);
$entry->transaction_type = $transaction->transaction_type_type;
$entry->asset_account_id = $transaction->account_id;
$entry->asset_account_name = app('steam')->tryDecrypt($transaction->account_name);
$entry->asset_account_iban = $transaction->account_iban;
$entry->asset_account_number = $transaction->account_number;
$entry->asset_account_bic = $transaction->account_bic;
$entry->asset_currency_code = $transaction->account_currency_code;
$entry->opposing_account_id = $transaction->opposing_account_id;
$entry->opposing_account_name = app('steam')->tryDecrypt($transaction->opposing_account_name);
$entry->opposing_account_iban = $transaction->opposing_account_iban;
$entry->opposing_account_number = $transaction->opposing_account_number;
$entry->opposing_account_bic = $transaction->opposing_account_bic;
$entry->opposing_currency_code = $transaction->opposing_currency_code;
/** budget */
$entry->budget_id = $transaction->transaction_budget_id;
$entry->budget_name = app('steam')->tryDecrypt($transaction->transaction_budget_name);
if (is_null($transaction->transaction_budget_id)) {
$entry->budget_id = $transaction->transaction_journal_budget_id;
$entry->budget_name = app('steam')->tryDecrypt($transaction->transaction_journal_budget_name);
}
/** category */
$entry->category_id = $transaction->transaction_category_id;
$entry->category_name = app('steam')->tryDecrypt($transaction->transaction_category_name);
if (is_null($transaction->transaction_category_id)) {
$entry->category_id = $transaction->transaction_journal_category_id;
$entry->category_name = app('steam')->tryDecrypt($transaction->transaction_journal_category_name);
}
/** budget */
$entry->bill_id = $transaction->bill_id;
$entry->bill_name = app('steam')->tryDecrypt($transaction->bill_name);
$entry->tags = $transaction->tags;
$entry->notes = $transaction->notes;
return $entry;
}

View File

@@ -0,0 +1,346 @@
<?php
/**
* ExpandedProcessor.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Export;
use Crypt;
use DB;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Export\Collector\AttachmentCollector;
use FireflyIII\Export\Collector\UploadCollector;
use FireflyIII\Export\Entry\Entry;
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Helpers\Filter\InternalTransferFilter;
use FireflyIII\Models\AccountMeta;
use FireflyIII\Models\ExportJob;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournalMeta;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use Illuminate\Support\Collection;
use Log;
use Storage;
use ZipArchive;
/**
* Class ExpandedProcessor
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects) // its doing a lot.
*
* @package FireflyIII\Export
*/
class ExpandedProcessor implements ProcessorInterface
{
/** @var Collection */
public $accounts;
/** @var string */
public $exportFormat;
/** @var bool */
public $includeAttachments;
/** @var bool */
public $includeOldUploads;
/** @var ExportJob */
public $job;
/** @var array */
public $settings;
/** @var Collection */
private $exportEntries;
/** @var Collection */
private $files;
/** @var Collection */
private $journals;
/**
* Processor constructor.
*/
public function __construct()
{
$this->journals = new Collection;
$this->exportEntries = new Collection;
$this->files = new Collection;
}
/**
* @return bool
*/
public function collectAttachments(): bool
{
/** @var AttachmentCollector $attachmentCollector */
$attachmentCollector = app(AttachmentCollector::class);
$attachmentCollector->setJob($this->job);
$attachmentCollector->setDates($this->settings['startDate'], $this->settings['endDate']);
$attachmentCollector->run();
$this->files = $this->files->merge($attachmentCollector->getEntries());
return true;
}
/**
* Collects all transaction journals.
*
* @return bool
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function collectJournals(): bool
{
// use journal collector thing.
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setUser($this->job->user);
$collector->setAccounts($this->accounts)->setRange($this->settings['startDate'], $this->settings['endDate'])
->withOpposingAccount()->withBudgetInformation()->withCategoryInformation()
->removeFilter(InternalTransferFilter::class);
$transactions = $collector->getJournals();
// get some more meta data for each entry:
$ids = $transactions->pluck('journal_id')->toArray();
$assetIds = $transactions->pluck('account_id')->toArray();
$opposingIds = $transactions->pluck('opposing_account_id')->toArray();
$notes = $this->getNotes($ids);
$tags = $this->getTags($ids);
/** @var array $ibans */
$ibans = $this->getIbans($assetIds) + $this->getIbans($opposingIds);
$currencies = $this->getAccountCurrencies($ibans);
$transactions->each(
function (Transaction $transaction) use ($notes, $tags, $ibans, $currencies) {
$journalId = intval($transaction->journal_id);
$accountId = intval($transaction->account_id);
$opposingId = intval($transaction->opposing_account_id);
$currencyId = $ibans[$accountId]['currency_id'] ?? 0;
$opposingCurrencyId = $ibans[$opposingId]['currency_id'] ?? 0;
$transaction->notes = $notes[$journalId] ?? '';
$transaction->tags = join(',', $tags[$journalId] ?? []);
$transaction->account_number = $ibans[$accountId]['accountNumber'] ?? '';
$transaction->account_bic = $ibans[$accountId]['BIC'] ?? '';
$transaction->account_currency_code = $currencies[$currencyId] ?? '';
$transaction->opposing_account_number = $ibans[$opposingId]['accountNumber'] ?? '';
$transaction->opposing_account_bic = $ibans[$opposingId]['BIC'] ?? '';
$transaction->opposing_currency_code = $currencies[$opposingCurrencyId] ?? '';
}
);
$this->journals = $transactions;
return true;
}
/**
* @return bool
*/
public function collectOldUploads(): bool
{
/** @var UploadCollector $uploadCollector */
$uploadCollector = app(UploadCollector::class);
$uploadCollector->setJob($this->job);
$uploadCollector->run();
$this->files = $this->files->merge($uploadCollector->getEntries());
return true;
}
/**
* @return bool
*/
public function convertJournals(): bool
{
$this->journals->each(
function (Transaction $transaction) {
$this->exportEntries->push(Entry::fromTransaction($transaction));
}
);
Log::debug(sprintf('Count %d entries in exportEntries (convertJournals)', $this->exportEntries->count()));
return true;
}
/**
* @return bool
* @throws FireflyException
*/
public function createZipFile(): bool
{
$zip = new ZipArchive;
$file = $this->job->key . '.zip';
$fullPath = storage_path('export') . '/' . $file;
if ($zip->open($fullPath, ZipArchive::CREATE) !== true) {
throw new FireflyException('Cannot store zip file.');
}
// for each file in the collection, add it to the zip file.
$disk = Storage::disk('export');
foreach ($this->getFiles() as $entry) {
// is part of this job?
$zipFileName = str_replace($this->job->key . '-', '', $entry);
$zip->addFromString($zipFileName, $disk->get($entry));
}
$zip->close();
// delete the files:
$this->deleteFiles();
return true;
}
/**
* @return bool
*/
public function exportJournals(): bool
{
$exporterClass = config('firefly.export_formats.' . $this->exportFormat);
$exporter = app($exporterClass);
$exporter->setJob($this->job);
$exporter->setEntries($this->exportEntries);
$exporter->run();
$this->files->push($exporter->getFileName());
return true;
}
/**
* @return Collection
*/
public function getFiles(): Collection
{
return $this->files;
}
/**
* Save export job settings to class.
*
* @param array $settings
*/
public function setSettings(array $settings)
{
// save settings
$this->settings = $settings;
$this->accounts = $settings['accounts'];
$this->exportFormat = $settings['exportFormat'];
$this->includeAttachments = $settings['includeAttachments'];
$this->includeOldUploads = $settings['includeOldUploads'];
$this->job = $settings['job'];
}
/**
*
*/
private function deleteFiles()
{
$disk = Storage::disk('export');
foreach ($this->getFiles() as $file) {
$disk->delete($file);
}
}
/**
* @param array $array
*
* @return array
*/
private function getAccountCurrencies(array $array): array
{
/** @var CurrencyRepositoryInterface $repository */
$repository = app(CurrencyRepositoryInterface::class);
$return = [];
$ids = [];
$repository->setUser($this->job->user);
foreach ($array as $value) {
$ids[] = $value['currency_id'] ?? 0;
}
$ids = array_unique($ids);
$result = $repository->getByIds($ids);
foreach ($result as $currency) {
$return[$currency->id] = $currency->code;
}
return $return;
}
/**
* Get all IBAN / SWIFT / account numbers
*
* @param array $array
*
* @return array
*/
private function getIbans(array $array): array
{
$array = array_unique($array);
$return = [];
$set = AccountMeta::whereIn('account_id', $array)
->leftJoin('accounts', 'accounts.id', 'account_meta.account_id')
->where('accounts.user_id', $this->job->user_id)
->whereIn('account_meta.name', ['accountNumber', 'BIC', 'currency_id'])
->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data']);
/** @var AccountMeta $meta */
foreach ($set as $meta) {
$id = intval($meta->account_id);
$return[$id][$meta->name] = $meta->data;
}
return $return;
}
/**
* Returns, if present, for the given journal ID's the notes.
*
* @param array $array
*
* @return array
*/
private function getNotes(array $array): array
{
$array = array_unique($array);
$set = TransactionJournalMeta::whereIn('journal_meta.transaction_journal_id', $array)
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id')
->where('transaction_journals.user_id', $this->job->user_id)
->where('journal_meta.name', 'notes')->get(
['journal_meta.transaction_journal_id', 'journal_meta.data', 'journal_meta.id']
);
$return = [];
/** @var TransactionJournalMeta $meta */
foreach ($set as $meta) {
$id = intval($meta->transaction_journal_id);
$return[$id] = $meta->data;
}
return $return;
}
/**
* Returns a comma joined list of all the users tags linked to these journals.
*
* @param array $array
*
* @return array
*/
private function getTags(array $array): array
{
$set = DB::table('tag_transaction_journal')
->whereIn('tag_transaction_journal.transaction_journal_id', $array)
->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id')
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'tag_transaction_journal.transaction_journal_id')
->where('transaction_journals.user_id', $this->job->user_id)
->get(['tag_transaction_journal.transaction_journal_id', 'tags.tag']);
$result = [];
foreach ($set as $entry) {
$id = intval($entry->transaction_journal_id);
$result[$id] = isset($result[$id]) ? $result[$id] : [];
$result[$id][] = Crypt::decrypt($entry->tag);
}
return $result;
}
}

View File

@@ -58,8 +58,12 @@ class CsvExporter extends BasicExporter implements ExporterInterface
// get field names for header row:
$first = $this->getEntries()->first();
$headers = array_keys(get_object_vars($first));
$rows[] = $headers;
$headers = [];
if (!is_null($first)) {
$headers = array_keys(get_object_vars($first));
}
$rows[] = $headers;
/** @var Entry $entry */
foreach ($this->getEntries() as $entry) {

View File

@@ -1,203 +0,0 @@
<?php
/**
* Processor.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Export;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Export\Collector\AttachmentCollector;
use FireflyIII\Export\Collector\JournalExportCollector;
use FireflyIII\Export\Collector\UploadCollector;
use FireflyIII\Export\Entry\Entry;
use FireflyIII\Models\ExportJob;
use Illuminate\Support\Collection;
use Log;
use Storage;
use ZipArchive;
/**
* Class Processor
*
* @package FireflyIII\Export
*/
class Processor implements ProcessorInterface
{
/** @var Collection */
public $accounts;
/** @var string */
public $exportFormat;
/** @var bool */
public $includeAttachments;
/** @var bool */
public $includeOldUploads;
/** @var ExportJob */
public $job;
/** @var array */
public $settings;
/** @var Collection */
private $exportEntries;
/** @var Collection */
private $files;
/** @var Collection */
private $journals;
/**
* Processor constructor.
*/
public function __construct()
{
$this->journals = new Collection;
$this->exportEntries = new Collection;
$this->files = new Collection;
}
/**
* @return bool
*/
public function collectAttachments(): bool
{
/** @var AttachmentCollector $attachmentCollector */
$attachmentCollector = app(AttachmentCollector::class);
$attachmentCollector->setJob($this->job);
$attachmentCollector->setDates($this->settings['startDate'], $this->settings['endDate']);
$attachmentCollector->run();
$this->files = $this->files->merge($attachmentCollector->getEntries());
return true;
}
/**
* @return bool
*/
public function collectJournals(): bool
{
/** @var JournalExportCollector $collector */
$collector = app(JournalExportCollector::class);
$collector->setJob($this->job);
$collector->setDates($this->settings['startDate'], $this->settings['endDate']);
$collector->setAccounts($this->settings['accounts']);
$collector->run();
$this->journals = $collector->getEntries();
Log::debug(sprintf('Count %d journals in collectJournals() ', $this->journals->count()));
return true;
}
/**
* @return bool
*/
public function collectOldUploads(): bool
{
/** @var UploadCollector $uploadCollector */
$uploadCollector = app(UploadCollector::class);
$uploadCollector->setJob($this->job);
$uploadCollector->run();
$this->files = $this->files->merge($uploadCollector->getEntries());
return true;
}
/**
* @return bool
*/
public function convertJournals(): bool
{
$count = 0;
foreach ($this->journals as $object) {
$this->exportEntries->push(Entry::fromObject($object));
$count++;
}
Log::debug(sprintf('Count %d entries in exportEntries (convertJournals)', $this->exportEntries->count()));
return true;
}
/**
* @return bool
* @throws FireflyException
*/
public function createZipFile(): bool
{
$zip = new ZipArchive;
$file = $this->job->key . '.zip';
$fullPath = storage_path('export') . '/' . $file;
if ($zip->open($fullPath, ZipArchive::CREATE) !== true) {
throw new FireflyException('Cannot store zip file.');
}
// for each file in the collection, add it to the zip file.
$disk = Storage::disk('export');
foreach ($this->getFiles() as $entry) {
// is part of this job?
$zipFileName = str_replace($this->job->key . '-', '', $entry);
$zip->addFromString($zipFileName, $disk->get($entry));
}
$zip->close();
// delete the files:
$this->deleteFiles();
return true;
}
/**
* @return bool
*/
public function exportJournals(): bool
{
$exporterClass = config('firefly.export_formats.' . $this->exportFormat);
$exporter = app($exporterClass);
$exporter->setJob($this->job);
$exporter->setEntries($this->exportEntries);
$exporter->run();
$this->files->push($exporter->getFileName());
return true;
}
/**
* @return Collection
*/
public function getFiles(): Collection
{
return $this->files;
}
/**
* @param array $settings
*/
public function setSettings(array $settings)
{
// save settings
$this->settings = $settings;
$this->accounts = $settings['accounts'];
$this->exportFormat = $settings['exportFormat'];
$this->includeAttachments = $settings['includeAttachments'];
$this->includeOldUploads = $settings['includeOldUploads'];
$this->job = $settings['job'];
}
/**
*
*/
private function deleteFiles()
{
$disk = Storage::disk('export');
foreach ($this->getFiles() as $file) {
$disk->delete($file);
}
}
}

View File

@@ -145,6 +145,9 @@ class MonthReportGenerator implements ReportGeneratorInterface
* @param Carbon $date
*
* @return array
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // not that long
*
*/
private function getAuditReport(Account $account, Carbon $date): array
{
@@ -175,9 +178,6 @@ class MonthReportGenerator implements ReportGeneratorInterface
$transaction->currency = $currency;
}
/*
* Reverse set again.
*/
$return = [
'journals' => $journals->reverse(),
'exists' => $journals->count() > 0,

View File

@@ -0,0 +1,55 @@
<?php
/**
* AdminEventHandler.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\AdminRequestedTestMessage;
use FireflyIII\Mail\AdminTestMail;
use Log;
use Mail;
use Session;
use Swift_TransportException;
/**
* Class AdminEventHandler
*
* @package FireflyIII\Handlers\Events
*/
class AdminEventHandler
{
/**
* @param AdminRequestedTestMessage $event
*
* @return bool
*/
public function sendTestMessage(AdminRequestedTestMessage $event): bool
{
$email = $event->user->email;
$ipAddress = $event->ipAddress;
Log::debug(sprintf('Now in sendTestMessage event handler. Email is %s, IP is %s', $email, $ipAddress));
try {
Log::debug('Trying to send message...');
Mail::to($email)->send(new AdminTestMail($email, $ipAddress));
// @codeCoverageIgnoreStart
} catch (Swift_TransportException $e) {
Log::debug('Send message failed! :(');
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
Session::flash('error', 'Possible email error: ' . $e->getMessage());
}
Log::debug('If no error above this line, message was sent.');
// @codeCoverageIgnoreEnd
return true;
}
}

View File

@@ -19,8 +19,8 @@ use FireflyIII\Models\RuleGroup;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface as JRI;
use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface as PRI;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface as RGRI;
use FireflyIII\Rules\Processor;
use FireflyIII\Support\Events\BillScanner;
use FireflyIII\TransactionRules\Processor;
use Log;
/**
@@ -57,11 +57,12 @@ class StoredJournalEventHandler
/**
* This method connects a new transfer to a piggy bank.
*
*
*
* @param StoredTransactionJournal $event
*
* @return bool
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function connectToPiggyBank(StoredTransactionJournal $event): bool
{

View File

@@ -18,8 +18,8 @@ use FireflyIII\Events\UpdatedTransactionJournal;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Rules\Processor;
use FireflyIII\Support\Events\BillScanner;
use FireflyIII\TransactionRules\Processor;
/**
* @codeCoverageIgnore

View File

@@ -15,11 +15,15 @@ namespace FireflyIII\Handlers\Events;
use FireflyIII\Events\RegisteredUser;
use FireflyIII\Events\RequestedNewPassword;
use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Mail\ConfirmEmailChangeMail;
use FireflyIII\Mail\RegisteredUser as RegisteredUserMail;
use FireflyIII\Mail\RequestedNewPassword as RequestedNewPasswordMail;
use FireflyIII\Mail\UndoEmailChangeMail;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use Log;
use Mail;
use Preferences;
use Swift_TransportException;
/**
@@ -54,6 +58,54 @@ class UserEventHandler
return true;
}
/**
* @param UserChangedEmail $event
*
* @return bool
*/
public function sendEmailChangeConfirmMail(UserChangedEmail $event): bool
{
$newEmail = $event->newEmail;
$oldEmail = $event->oldEmail;
$user = $event->user;
$ipAddress = $event->ipAddress;
$token = Preferences::getForUser($user, 'email_change_confirm_token', 'invalid');
$uri = route('profile.confirm-email-change', [$token->data]);
try {
Mail::to($newEmail)->send(new ConfirmEmailChangeMail($newEmail, $oldEmail, $uri, $ipAddress));
// @codeCoverageIgnoreStart
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
// @codeCoverageIgnoreEnd
return true;
}
/**
* @param UserChangedEmail $event
*
* @return bool
*/
public function sendEmailChangeUndoMail(UserChangedEmail $event): bool
{
$newEmail = $event->newEmail;
$oldEmail = $event->oldEmail;
$user = $event->user;
$ipAddress = $event->ipAddress;
$token = Preferences::getForUser($user, 'email_change_undo_token', 'invalid');
$uri = route('profile.undo-email-change', [$token->data, hash('sha256', $oldEmail)]);
try {
Mail::to($oldEmail)->send(new UndoEmailChangeMail($newEmail, $oldEmail, $uri, $ipAddress));
// @codeCoverageIgnoreStart
} catch (Swift_TransportException $e) {
Log::error($e->getMessage());
}
// @codeCoverageIgnoreEnd
return true;
}
/**
* @param RequestedNewPassword $event
*

View File

@@ -99,7 +99,7 @@ class AttachmentHelper implements AttachmentHelperInterface
*
* @return bool
*/
public function saveAttachmentsForModel(Model $model, array $files = null): bool
public function saveAttachmentsForModel(Model $model, ?array $files): bool
{
if (is_array($files)) {
foreach ($files as $entry) {
@@ -169,7 +169,6 @@ class AttachmentHelper implements AttachmentHelperInterface
// store it:
$this->uploadDisk->put($attachment->fileName(), $encrypted);
$attachment->uploaded = 1; // update attachment
$attachment->save();
$this->attachments->push($attachment);
@@ -180,8 +179,6 @@ class AttachmentHelper implements AttachmentHelperInterface
// return it.
return $attachment;
}
/**

View File

@@ -55,6 +55,6 @@ interface AttachmentHelperInterface
*
* @return bool
*/
public function saveAttachmentsForModel(Model $model, array $files = null): bool;
public function saveAttachmentsForModel(Model $model, ?array $files): bool;
}

View File

@@ -32,6 +32,8 @@ use Steam;
* Class MetaPieChart
*
* @package FireflyIII\Helpers\Chart
*
*
*/
class MetaPieChart implements MetaPieChartInterface
{
@@ -83,12 +85,15 @@ class MetaPieChart implements MetaPieChartInterface
* @param string $group
*
* @return array
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function generate(string $direction, string $group): array
{
$transactions = $this->getTransactions($direction);
$grouped = $this->groupByFields($transactions, $this->grouping[$group]);
$chartData = $this->organizeByType($group, $grouped);
$key = strval(trans('firefly.everything_else'));
// also collect all other transactions
if ($this->collectOtherObjects && $direction === 'expense') {
@@ -96,11 +101,12 @@ class MetaPieChart implements MetaPieChartInterface
$collector = app(JournalCollectorInterface::class);
$collector->setUser($this->user);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::WITHDRAWAL]);
$journals = $collector->getJournals();
$sum = strval($journals->sum('transaction_amount'));
$sum = bcmul($sum, '-1');
$sum = bcsub($sum, $this->total);
$chartData[strval(trans('firefly.everything_else'))] = $sum;
$journals = $collector->getJournals();
$sum = strval($journals->sum('transaction_amount'));
$sum = bcmul($sum, '-1');
$sum = bcsub($sum, $this->total);
$chartData[$key] = $sum;
}
if ($this->collectOtherObjects && $direction === 'income') {
@@ -108,10 +114,10 @@ class MetaPieChart implements MetaPieChartInterface
$collector = app(JournalCollectorInterface::class);
$collector->setUser($this->user);
$collector->setAccounts($this->accounts)->setRange($this->start, $this->end)->setTypes([TransactionType::DEPOSIT]);
$journals = $collector->getJournals();
$sum = strval($journals->sum('transaction_amount'));
$sum = bcsub($sum, $this->total);
$chartData[strval(trans('firefly.everything_else'))] = $sum;
$journals = $collector->getJournals();
$sum = strval($journals->sum('transaction_amount'));
$sum = bcsub($sum, $this->total);
$chartData[$key] = $sum;
}
return $chartData;
@@ -258,12 +264,9 @@ class MetaPieChart implements MetaPieChartInterface
$collector->removeFilter(TransferFilter::class);
}
if ($this->budgets->count() > 0) {
$collector->setBudgets($this->budgets);
}
if ($this->categories->count() > 0) {
$collector->setCategories($this->categories);
}
$collector->setBudgets($this->budgets);
$collector->setCategories($this->categories);
if ($this->tags->count() > 0) {
$collector->setTags($this->tags);
$collector->withCategoryInformation();
@@ -278,6 +281,9 @@ class MetaPieChart implements MetaPieChartInterface
* @param array $fields
*
* @return array
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
*/
protected function groupByFields(Collection $set, array $fields): array
{

View File

@@ -15,7 +15,6 @@ namespace FireflyIII\Helpers\Collector;
use Carbon\Carbon;
use Crypt;
use DB;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Filter\FilterInterface;
@@ -31,7 +30,6 @@ use FireflyIII\Models\Tag;
use FireflyIII\Models\Transaction;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Pagination\LengthAwarePaginator;
@@ -45,6 +43,9 @@ use Steam;
* Class JournalCollector
*
* @package FireflyIII\Helpers\Collector
*
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class JournalCollector implements JournalCollectorInterface
{
@@ -64,29 +65,31 @@ class JournalCollector implements JournalCollectorInterface
'transaction_journals.bill_id',
'bills.name as bill_name',
'bills.name_encrypted as bill_name_encrypted',
'transactions.id as id',
'transactions.id as id',
'transactions.description as transaction_description',
'transactions.account_id',
'transactions.identifier',
'transactions.transaction_journal_id',
'transactions.amount as transaction_amount',
'transactions.transaction_currency_id as transaction_currency_id',
'transaction_currencies.code as transaction_currency_code',
'transaction_currencies.symbol as transaction_currency_symbol',
'transaction_currencies.decimal_places as transaction_currency_dp',
'transactions.foreign_amount as transaction_foreign_amount',
'transactions.foreign_currency_id as foreign_currency_id',
'foreign_currencies.code as foreign_currency_code',
'foreign_currencies.symbol as foreign_currency_symbol',
'foreign_currencies.decimal_places as foreign_currency_dp',
'accounts.name as account_name',
'accounts.encrypted as account_encrypted',
'accounts.iban as account_iban',
'account_types.type as account_type',
];
/** @var bool */
private $filterTransfers = false;
@@ -175,12 +178,10 @@ class JournalCollector implements JournalCollectorInterface
if (!is_null($transaction->bill_name)) {
$transaction->bill_name = Steam::decrypt(intval($transaction->bill_name_encrypted), $transaction->bill_name);
}
$transaction->opposing_account_name = app('steam')->tryDecrypt($transaction->opposing_account_name);
$transaction->account_iban = app('steam')->tryDecrypt($transaction->account_iban);
$transaction->opposing_account_iban = app('steam')->tryDecrypt($transaction->opposing_account_iban);
try {
$transaction->opposing_account_name = Crypt::decrypt($transaction->opposing_account_name);
} catch (DecryptException $e) {
// if this fails its already decrypted.
}
}
);
@@ -399,6 +400,10 @@ class JournalCollector implements JournalCollectorInterface
*/
public function setPage(int $page): JournalCollectorInterface
{
if ($page < 1) {
$page = 1;
}
$this->page = $page;
if ($page > 0) {
@@ -411,10 +416,10 @@ class JournalCollector implements JournalCollectorInterface
$this->offset = $offset;
$this->query->skip($offset);
Log::debug(sprintf('Changed offset to %d', $offset));
return $this;
}
if (is_null($this->limit)) {
Log::debug('The limit is zero, cannot set the page.');
}
Log::debug('The limit is zero, cannot set the page.');
return $this;
}
@@ -617,6 +622,8 @@ class JournalCollector implements JournalCollectorInterface
$this->query->leftJoin('budgets as transaction_journal_budgets', 'transaction_journal_budgets.id', '=', 'budget_transaction_journal.budget_id');
$this->query->leftJoin('budget_transaction', 'budget_transaction.transaction_id', '=', 'transactions.id');
$this->query->leftJoin('budgets as transaction_budgets', 'transaction_budgets.id', '=', 'budget_transaction.budget_id');
$this->query->whereNull('transaction_journal_budgets.deleted_at');
$this->query->whereNull('transaction_budgets.deleted_at');
$this->fields[] = 'budget_transaction_journal.budget_id as transaction_journal_budget_id';
$this->fields[] = 'transaction_journal_budgets.encrypted as transaction_journal_budget_encrypted';
@@ -673,9 +680,12 @@ class JournalCollector implements JournalCollectorInterface
$this->query->leftJoin('account_types as opposing_account_types', 'opposing_accounts.account_type_id', '=', 'opposing_account_types.id');
$this->query->whereNull('opposing.deleted_at');
$this->fields[] = 'opposing.account_id as opposing_account_id';
$this->fields[] = 'opposing_accounts.name as opposing_account_name';
$this->fields[] = 'opposing_accounts.encrypted as opposing_account_encrypted';
$this->fields[] = 'opposing.id as opposing_id';
$this->fields[] = 'opposing.account_id as opposing_account_id';
$this->fields[] = 'opposing_accounts.name as opposing_account_name';
$this->fields[] = 'opposing_accounts.encrypted as opposing_account_encrypted';
$this->fields[] = 'opposing_accounts.iban as opposing_account_iban';
$this->fields[] = 'opposing_account_types.type as opposing_account_type';
$this->joinedOpposing = true;
Log::debug('joinedOpposing is now true!');

View File

@@ -41,11 +41,13 @@ class TransferFilter implements FilterInterface
continue;
}
// make property string:
$journalId = $transaction->transaction_journal_id;
$amount = Steam::positive($transaction->transaction_amount);
$accountIds = [intval($transaction->account_id), intval($transaction->opposing_account_id)];
$journalId = $transaction->transaction_journal_id;
$amount = Steam::positive($transaction->transaction_amount);
$accountIds = [intval($transaction->account_id), intval($transaction->opposing_account_id)];
$transactionIds = [$transaction->id, intval($transaction->opposing_id)];
sort($accountIds);
$key = $journalId . '-' . join(',', $accountIds) . '-' . $amount;
sort($transactionIds);
$key = $journalId . '-' . join(',', $transactionIds) . '-' . join(',', $accountIds) . '-' . $amount;
if (!isset($count[$key])) {
// not yet counted? add to new set and count it:
$new->push($transaction);

View File

@@ -14,16 +14,12 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Report;
use Carbon\Carbon;
use DB;
use FireflyIII\Helpers\Collection\Balance;
use FireflyIII\Helpers\Collection\BalanceEntry;
use FireflyIII\Helpers\Collection\BalanceHeader;
use FireflyIII\Helpers\Collection\BalanceLine;
use FireflyIII\Models\BudgetLimit;
use FireflyIII\Models\Tag;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use Illuminate\Database\Query\JoinClause;
use Illuminate\Support\Collection;
use Log;
@@ -71,17 +67,14 @@ class BalanceReportHelper implements BalanceReportHelperInterface
/** @var BudgetLimit $budgetLimit */
foreach ($budgetLimits as $budgetLimit) {
$line = $this->createBalanceLine($budgetLimit, $accounts);
$balance->addBalanceLine($line);
if (!is_null($budgetLimit->budget)) {
$line = $this->createBalanceLine($budgetLimit, $accounts);
$balance->addBalanceLine($line);
}
}
Log::debug('Create rest of the things.');
$noBudgetLine = $this->createNoBudgetLine($accounts, $start, $end);
$coveredByTagLine = $this->createTagsBalanceLine($accounts, $start, $end);
$leftUnbalancedLine = $this->createLeftUnbalancedLine($noBudgetLine, $coveredByTagLine);
$noBudgetLine = $this->createNoBudgetLine($accounts, $start, $end);
$balance->addBalanceLine($noBudgetLine);
$balance->addBalanceLine($coveredByTagLine);
$balance->addBalanceLine($leftUnbalancedLine);
$balance->setBalanceHeader($header);
Log::debug('Clear unused budgets.');
@@ -93,54 +86,6 @@ class BalanceReportHelper implements BalanceReportHelperInterface
return $balance;
}
/**
* This method collects all transfers that are part of a "balancing act" tag
* and groups the amounts of those transfers by their destination account.
*
* This is used to indicate which expenses, usually outside of budgets, have been
* corrected by transfers from a savings account.
*
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return Collection
*/
private function allCoveredByBalancingActs(Collection $accounts, Carbon $start, Carbon $end): Collection
{
$ids = $accounts->pluck('id')->toArray();
$set = auth()->user()->tags()
->leftJoin('tag_transaction_journal', 'tag_transaction_journal.tag_id', '=', 'tags.id')
->leftJoin('transaction_journals', 'tag_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id')
->leftJoin('transaction_types', 'transaction_journals.transaction_type_id', '=', 'transaction_types.id')
->leftJoin(
'transactions AS t_source', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_source.transaction_journal_id')->where('t_source.amount', '<', 0);
}
)
->leftJoin(
'transactions AS t_destination', function (JoinClause $join) {
$join->on('transaction_journals.id', '=', 't_destination.transaction_journal_id')->where('t_destination.amount', '>', 0);
}
)
->where('tags.tagMode', 'balancingAct')
->where('transaction_types.type', TransactionType::TRANSFER)
->where('transaction_journals.date', '>=', $start->format('Y-m-d'))
->where('transaction_journals.date', '<=', $end->format('Y-m-d'))
->whereNull('transaction_journals.deleted_at')
->whereIn('t_source.account_id', $ids)
->whereIn('t_destination.account_id', $ids)
->groupBy('t_destination.account_id')
->get(
[
't_destination.account_id',
DB::raw('SUM(t_destination.amount) AS sum'),
]
);
return $set;
}
/**
* @param BudgetLimit $budgetLimit
@@ -168,40 +113,6 @@ class BalanceReportHelper implements BalanceReportHelperInterface
return $line;
}
/**
* @param BalanceLine $noBudgetLine
* @param BalanceLine $coveredByTagLine
*
* @return BalanceLine
*/
private function createLeftUnbalancedLine(BalanceLine $noBudgetLine, BalanceLine $coveredByTagLine): BalanceLine
{
$line = new BalanceLine;
$line->setRole(BalanceLine::ROLE_DIFFROLE);
$noBudgetEntries = $noBudgetLine->getBalanceEntries();
$tagEntries = $coveredByTagLine->getBalanceEntries();
foreach ($noBudgetEntries as $entry) {
$account = $entry->getAccount();
$tagEntry = $tagEntries->filter(
function (BalanceEntry $current) use ($account) {
return $current->getAccount()->id === $account->id;
}
);
if ($tagEntry->first()) {
// found corresponding entry. As we should:
$newEntry = new BalanceEntry;
$newEntry->setAccount($account);
$spent = bcadd($tagEntry->first()->getLeft(), $entry->getSpent());
$newEntry->setSpent($spent);
$line->addBalanceEntry($newEntry);
}
}
return $line;
}
/**
* @param Collection $accounts
@@ -227,41 +138,6 @@ class BalanceReportHelper implements BalanceReportHelperInterface
return $empty;
}
/**
* @param Collection $accounts
* @param Carbon $start
* @param Carbon $end
*
* @return BalanceLine
*/
private function createTagsBalanceLine(Collection $accounts, Carbon $start, Carbon $end): BalanceLine
{
$tags = new BalanceLine;
$tagsLeft = $this->allCoveredByBalancingActs($accounts, $start, $end);
$tags->setRole(BalanceLine::ROLE_TAGROLE);
foreach ($accounts as $account) {
$leftEntry = $tagsLeft->filter(
function (Tag $tag) use ($account) {
return $tag->account_id === $account->id;
}
);
$left = '0';
if (!is_null($leftEntry->first())) {
$left = $leftEntry->first()->sum;
}
// balanced by tags
$tagEntry = new BalanceEntry;
$tagEntry->setAccount($account);
$tagEntry->setLeft($left);
$tags->addBalanceEntry($tagEntry);
}
return $tags;
}
/**
* @param Balance $balance

View File

@@ -42,6 +42,7 @@ class BudgetReportHelper implements BudgetReportHelperInterface
/**
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5.
* @SuppressWarnings(PHPMD.ExcessiveMethodLength) // all the arrays make it long.
* @param Carbon $start
* @param Carbon $end
* @param Collection $accounts

View File

@@ -39,6 +39,7 @@ use View;
* Class AccountController
*
* @package FireflyIII\Http\Controllers
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class AccountController extends Controller
{
@@ -141,9 +142,14 @@ class AccountController extends Controller
}
/**
* Edit an account.
*
* @param Request $request
* @param Account $account
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // long and complex but not that excessively so.
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*
* @return View
*/
public function edit(Request $request, Account $account)
@@ -194,7 +200,7 @@ class AccountController extends Controller
return view(
'accounts.edit', compact(
'allCurrencies', 'currencySelectList', 'account', 'currency', 'subTitle', 'subTitleIcon', 'what', 'roles'
'allCurrencies', 'currencySelectList', 'account', 'currency', 'subTitle', 'subTitleIcon', 'what', 'roles', 'preFilled'
)
);
}
@@ -237,12 +243,16 @@ class AccountController extends Controller
/**
* Show an account.
* @param Request $request
* @param JournalRepositoryInterface $repository
* @param Account $account
* @param string $moment
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // long and complex but not that excessively so.
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function show(Request $request, JournalRepositoryInterface $repository, Account $account, string $moment = '')
{
@@ -253,7 +263,7 @@ class AccountController extends Controller
$currencyRepos = app(CurrencyRepositoryInterface::class);
$range = Preferences::get('viewRange', '1M')->data;
$subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type);
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$chartUri = route('chart.account.single', [$account->id]);
$start = null;
@@ -274,55 +284,31 @@ class AccountController extends Controller
if (strlen($moment) > 0 && $moment !== 'all') {
$start = new Carbon($moment);
$end = Navigation::endOfPeriod($start, $range);
$subTitle = trans(
'firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
$fStart = $start->formatLocalized($this->monthAndDayFormat);
$fEnd = $end->formatLocalized($this->monthAndDayFormat);
$subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]);
$chartUri = route('chart.account.period', [$account->id, $start->format('Y-m-d')]);
$periods = $this->getPeriodOverview($account);
}
// prep for current period
// prep for current period view
if (strlen($moment) === 0) {
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
$subTitle = trans(
'firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
$fStart = $start->formatLocalized($this->monthAndDayFormat);
$fEnd = $end->formatLocalized($this->monthAndDayFormat);
$subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]);
$periods = $this->getPeriodOverview($account);
}
$count = 0;
$loop = 0;
// grab journals, but be prepared to jump a period back to get the right ones:
Log::info('Now at loop start.');
while ($count === 0 && $loop < 3) {
$loop++;
$collector = app(JournalCollectorInterface::class);
Log::info('Count is zero, search for journals.');
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page);
if (!is_null($start)) {
$collector->setRange($start, $end);
}
$journals = $collector->getPaginatedJournals();
$journals->setPath('accounts/show/' . $account->id . '/' . $moment);
$count = $journals->getCollection()->count();
if ($count === 0 && $loop < 3) {
$start->subDay();
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfPeriod($start, $range);
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
}
// grab journals:
$collector = app(JournalCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page);
if (!is_null($start)) {
$collector->setRange($start, $end);
}
if ($moment !== 'all' && $loop > 1) {
$subTitle = trans(
'firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
$journals = $collector->getPaginatedJournals();
$journals->setPath(route('accounts.show', [$account->id, $moment]));
return view(
'accounts.show',
@@ -413,6 +399,8 @@ class AccountController extends Controller
* @param Account $account The account involved.
*
* @return Collection
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
private function getPeriodOverview(Account $account): Collection
{
@@ -421,9 +409,9 @@ class AccountController extends Controller
$start = $repository->oldestJournalDate($account);
$range = Preferences::get('viewRange', '1M')->data;
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfX(new Carbon, $range);
$end = Navigation::endOfX(new Carbon, $range, null);
$entries = new Collection;
$count = 0;
// properties for cache
$cache = new CacheProperties;
$cache->addProperty($start);
@@ -436,24 +424,20 @@ class AccountController extends Controller
}
Log::debug('Going to get period expenses and incomes.');
while ($end >= $start) {
while ($end >= $start && $count < 90) {
$end = Navigation::startOfPeriod($end, $range);
$currentEnd = Navigation::endOfPeriod($end, $range);
// try a collector for income:
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($end, $currentEnd)
->setTypes([TransactionType::DEPOSIT])
->withOpposingAccount();
$collector->setAccounts(new Collection([$account]))->setRange($end, $currentEnd)->setTypes([TransactionType::DEPOSIT])->withOpposingAccount();
$earned = strval($collector->getJournals()->sum('transaction_amount'));
// try a collector for expenses:
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAccounts(new Collection([$account]))->setRange($end, $currentEnd)
->setTypes([TransactionType::WITHDRAWAL])
->withOpposingAccount();
$collector->setAccounts(new Collection([$account]))->setRange($end, $currentEnd)->setTypes([TransactionType::WITHDRAWAL])->withOpposingAccount();
$spent = strval($collector->getJournals()->sum('transaction_amount'));
$dateStr = $end->format('Y-m-d');
$dateName = Navigation::periodShow($end, $range);
@@ -466,7 +450,7 @@ class AccountController extends Controller
'date' => clone $end]
);
$end = Navigation::subtractPeriod($end, $range, 1);
$count++;
}
$cache->store($entries);

View File

@@ -14,7 +14,11 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Admin;
use FireflyIII\Events\AdminRequestedTestMessage;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Session;
use Log;
/**
* Class HomeController
@@ -34,4 +38,18 @@ class HomeController extends Controller
return view('admin.index', compact('title', 'mainTitleIcon'));
}
/**
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function testMessage(Request $request)
{
$ipAddress = $request->ip();
Log::debug(sprintf('Now in testMessage() controller. IP is %s', $ipAddress));
event(new AdminRequestedTestMessage(auth()->user(), $ipAddress));
Session::flash('info', strval(trans('firefly.send_test_triggered')));
return redirect(route('admin.index'));
}
}

View File

@@ -0,0 +1,229 @@
<?php
/**
* LinkController.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Admin;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\LinkTypeFormRequest;
use FireflyIII\Models\LinkType;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use Illuminate\Http\Request;
use Preferences;
use View;
/**
* Class LinkController
*
* @package FireflyIII\Http\Controllers\Admin
*/
class LinkController extends Controller
{
/**
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
View::share('title', strval(trans('firefly.administration')));
View::share('mainTitleIcon', 'fa-hand-spock-o');
return $next($request);
}
);
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function create()
{
$subTitle = trans('firefly.create_new_link_type');
$subTitleIcon = 'fa-link';
// put previous url in session if not redirect from store (not "create another").
if (session('link_types.create.fromStore') !== true) {
$this->rememberPreviousUri('link_types.create.uri');
}
return view('admin.link.create', compact('subTitle', 'subTitleIcon'));
}
/**
* @param Request $request
* @param LinkTypeRepositoryInterface $repository
* @param LinkType $linkType
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
*/
public function delete(Request $request, LinkTypeRepositoryInterface $repository, LinkType $linkType)
{
if (!$linkType->editable) {
$request->session()->flash('error', strval(trans('firefly.cannot_edit_link_type', ['name' => $linkType->name])));
return redirect(route('admin.links.index'));
}
$subTitle = trans('firefly.delete_link_type', ['name' => $linkType->name]);
$otherTypes = $repository->get();
$count = $repository->countJournals($linkType);
$moveTo = [];
$moveTo[0] = trans('firefly.do_not_save_connection');
/** @var LinkType $otherType */
foreach ($otherTypes as $otherType) {
if ($otherType->id !== $linkType->id) {
$moveTo[$otherType->id] = sprintf('%s (%s / %s)', $otherType->name, $otherType->inward, $otherType->outward);
}
}
// put previous url in session
$this->rememberPreviousUri('link_types.delete.uri');
return view('admin.link.delete', compact('linkType', 'subTitle', 'moveTo', 'count'));
}
/**
* @param Request $request
* @param LinkTypeRepositoryInterface $repository
* @param LinkType $linkType
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function destroy(Request $request, LinkTypeRepositoryInterface $repository, LinkType $linkType)
{
$name = $linkType->name;
$moveTo = $repository->find(intval($request->get('move_link_type_before_delete')));
$repository->destroy($linkType, $moveTo);
$request->session()->flash('success', strval(trans('firefly.deleted_link_type', ['name' => $name])));
Preferences::mark();
return redirect($this->getPreviousUri('link_types.delete.uri'));
}
/**
* @param Request $request
* @param LinkType $linkType
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
*/
public function edit(Request $request, LinkType $linkType)
{
if (!$linkType->editable) {
$request->session()->flash('error', strval(trans('firefly.cannot_edit_link_type', ['name' => $linkType->name])));
return redirect(route('admin.links.index'));
}
$subTitle = trans('firefly.edit_link_type', ['name' => $linkType->name]);
$subTitleIcon = 'fa-link';
// put previous url in session if not redirect from store (not "return_to_edit").
if (session('link_types.edit.fromUpdate') !== true) {
$this->rememberPreviousUri('link_types.edit.uri');
}
$request->session()->forget('link_types.edit.fromUpdate');
return view('admin.link.edit', compact('subTitle', 'subTitleIcon', 'linkType'));
}
/**
* @param LinkTypeRepositoryInterface $repository
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index(LinkTypeRepositoryInterface $repository)
{
$subTitle = trans('firefly.journal_link_configuration');
$subTitleIcon = 'fa-link';
$linkTypes = $repository->get();
$linkTypes->each(
function (LinkType $linkType) use ($repository) {
$linkType->journalCount = $repository->countJournals($linkType);
}
);
return view('admin.link.index', compact('subTitle', 'subTitleIcon', 'linkTypes'));
}
/**
* @param LinkType $linkType
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function show(LinkType $linkType)
{
$subTitle = trans('firefly.overview_for_link', ['name' => $linkType->name]);
$subTitleIcon = 'fa-link';
$links = $linkType->transactionJournalLinks()->get();
return view('admin.link.show', compact('subTitle', 'subTitleIcon', 'linkType', 'links'));
}
/**
* @param LinkTypeFormRequest $request
* @param LinkTypeRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function store(LinkTypeFormRequest $request, LinkTypeRepositoryInterface $repository)
{
$data = [
'name' => $request->string('name'),
'inward' => $request->string('inward'),
'outward' => $request->string('outward'),
];
$linkType = $repository->store($data);
$request->session()->flash('success', strval(trans('firefly.stored_new_link_type', ['name' => $linkType->name])));
if (intval($request->get('create_another')) === 1) {
// set value so create routine will not overwrite URL:
$request->session()->put('link_types.create.fromStore', true);
return redirect(route('link_types.create', [$request->input('what')]))->withInput();
}
// redirect to previous URL.
return redirect($this->getPreviousUri('link_types.create.uri'));
}
public function update(LinkTypeFormRequest $request, LinkTypeRepositoryInterface $repository, LinkType $linkType)
{
if (!$linkType->editable) {
$request->session()->flash('error', strval(trans('firefly.cannot_edit_link_type', ['name' => $linkType->name])));
return redirect(route('admin.links.index'));
}
$data = [
'name' => $request->string('name'),
'inward' => $request->string('inward'),
'outward' => $request->string('outward'),
];
$repository->update($linkType, $data);
$request->session()->flash('success', strval(trans('firefly.updated_link_type', ['name' => $linkType->name])));
Preferences::mark();
if (intval($request->get('return_to_edit')) === 1) {
// set value so edit routine will not overwrite URL:
$request->session()->put('link_types.edit.fromUpdate', true);
return redirect(route('admin.links.edit', [$linkType->id]))->withInput(['return_to_edit' => 1]);
}
// redirect to previous URL.
return redirect($this->getPreviousUri('link_types.edit.uri'));
}
}

View File

@@ -48,6 +48,32 @@ class UserController extends Controller
);
}
/**
* @param User $user
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function delete(User $user)
{
$subTitle = trans('firefly.delete_user', ['email' => $user->email]);
return view('admin.users.delete', compact('user', 'subTitle'));
}
/**
* @param User $user
* @param UserRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function destroy(User $user, UserRepositoryInterface $repository)
{
$repository->destroy($user);
Session::flash('success', strval(trans('firefly.user_deleted')));
return redirect(route('admin.users'));
}
/**
* @param User $user
*
@@ -64,9 +90,10 @@ class UserController extends Controller
$subTitle = strval(trans('firefly.edit_user', ['email' => $user->email]));
$subTitleIcon = 'fa-user-o';
$codes = [
'' => strval(trans('firefly.no_block_code')),
'bounced' => strval(trans('firefly.block_code_bounced')),
'expired' => strval(trans('firefly.block_code_expired')),
'' => strval(trans('firefly.no_block_code')),
'bounced' => strval(trans('firefly.block_code_bounced')),
'expired' => strval(trans('firefly.block_code_expired')),
'email_changed' => strval(trans('firefly.block_code_email_changed')),
];
return view('admin.users.edit', compact('user', 'subTitle', 'subTitleIcon', 'codes'));
@@ -143,6 +170,7 @@ class UserController extends Controller
}
$repository->changeStatus($user, $data['blocked'], $data['blocked_code']);
$repository->updateEmail($user, $data['email']);
Session::flash('success', strval(trans('firefly.updated_user', ['email' => $user->email])));
Preferences::mark();

View File

@@ -99,7 +99,6 @@ class AttachmentController extends Controller
public function download(AttachmentRepositoryInterface $repository, Attachment $attachment)
{
if ($repository->exists($attachment)) {
$content = $repository->getContent($attachment);
$quoted = sprintf('"%s"', addcslashes(basename($attachment->filename), '"\\'));

View File

@@ -1,31 +1,34 @@
<?php
declare(strict_types=1);
/**
* ForgotPasswordController.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Auth;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
use Password;
/**
* Class ForgotPasswordController
*
* @package FireflyIII\Http\Controllers\Auth
*/
class ForgotPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset emails and
| includes a trait which assists in sending these notifications from
| your application to your users. Feel free to explore this trait.
|
*/
use SendsPasswordResetEmails;
/**
@@ -36,37 +39,6 @@ class ForgotPasswordController extends Controller
{
parent::__construct();
$this->middleware('guest');
}
/**
* Send a reset link to the given user.
*
* @param Request $request
*
* @param UserRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse
*/
public function sendResetLinkEmail(Request $request, UserRepositoryInterface $repository)
{
$this->validate($request, ['email' => 'required|email']);
// verify if the user is not a demo user. If so, we give him back an error.
$user = User::where('email', $request->get('email'))->first();
if (!is_null($user) && $repository->hasRole($user, 'demo')) {
return back()->withErrors(['email' => trans('firefly.cannot_reset_demo_user')]);
}
$response = $this->broker()->sendResetLink($request->only('email'));
if ($response === Password::RESET_LINK_SENT) {
return back()->with('status', trans($response));
}
// If an error was returned by the password broker, we will get this message
// translated so we can notify a user of the problem. We'll redirect back
// to where the users came from so they can attempt this process again.
return back()->withErrors(['email' => trans($response)]); // @codeCoverageIgnore
}
}

View File

@@ -1,38 +1,49 @@
<?php
declare(strict_types=1);
/**
* LoginController.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Auth;
use Config;
use FireflyConfig;
use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\User;
use Illuminate\Cookie\CookieJar;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Lang;
/**
* @codeCoverageIgnore
*
* Class LoginController
*
* @package FireflyIII\Http\Controllers\Auth
*/
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
@@ -40,79 +51,11 @@ class LoginController extends Controller
public function __construct()
{
parent::__construct();
$this->middleware('guest', ['except' => 'logout']);
$this->middleware('guest')->except('logout');
}
/**
* Handle a login request to the application.
*
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
*/
public function login(Request $request)
{
$this->validateLogin($request);
$lockedOut = $this->hasTooManyLoginAttempts($request);
if ($lockedOut) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
$credentials = $this->credentials($request);
$credentials['blocked'] = 0; // must not be blocked.
if ($this->guard()->attempt($credentials, $request->has('remember'))) {
return $this->sendLoginResponse($request);
}
$errorMessage = $this->getBlockedError($credentials['email']);
if (!$lockedOut) {
$this->incrementLoginAttempts($request);
}
return $this->sendFailedLoginResponse($request, $errorMessage);
}
/**
* @param Request $request
* @param CookieJar $cookieJar
*
* @return $this
*/
public function logout(Request $request, CookieJar $cookieJar)
{
if (intval(getenv('SANDSTORM')) === 1) {
return view('error')->with('message', strval(trans('firefly.sandstorm_not_available')));
}
$cookie = $cookieJar->forever('twoFactorAuthenticated', 'false');
$this->guard()->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect('/')->withCookie($cookie);
}
/**
* @return string
*/
public function redirectTo(): string
{
return route('index');
}
/**
* Show the application login form.
*
* @param Request $request
*
* @param CookieJar $cookieJar
* Show the application's login form.
*
* @return \Illuminate\Http\Response
*/
@@ -120,8 +63,9 @@ class LoginController extends Controller
{
// forget 2fa cookie:
$cookie = $cookieJar->forever('twoFactorAuthenticated', 'false');
// is allowed to?
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
$allowRegistration = true;
if ($singleUserMode === true && $userCount > 0) {
@@ -133,59 +77,4 @@ class LoginController extends Controller
return view('auth.login', compact('allowRegistration', 'email', 'remember'))->withCookie($cookie);
}
/**
* Get the failed login message.
*
* @param string $message
*
* @return string
*/
protected function getFailedLoginMessage(string $message)
{
if (strlen($message) > 0) {
return $message;
}
return Lang::has('auth.failed') ? Lang::get('auth.failed') : 'These credentials do not match our records.';
}
/**
* Get the failed login response instance.
*
* @param \Illuminate\Http\Request $request
* @param string $message
*
* @return \Illuminate\Http\RedirectResponse
*/
protected function sendFailedLoginResponse(Request $request, string $message)
{
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
->withErrors(
[
$this->username() => $this->getFailedLoginMessage($message),
]
);
}
/**
* @param string $email
*
* @return string
*/
private function getBlockedError(string $email): string
{
// check if user is blocked:
$errorMessage = '';
/** @var User $foundUser */
$foundUser = User::where('email', $email)->where('blocked', 1)->first();
if (!is_null($foundUser)) {
// user exists, but is blocked:
$code = strlen(strval($foundUser->blocked_code)) > 0 ? $foundUser->blocked_code : 'general_blocked';
$errorMessage = strval(trans('firefly.' . $code . '_error', ['email' => $email]));
}
return $errorMessage;
}
}

View File

@@ -1,88 +0,0 @@
<?php
/**
* PasswordController.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Auth;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\User;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Mail\Message;
use Illuminate\Support\Facades\Password;
/**
* @codeCoverageIgnore
*
* Class PasswordController
*
* @package FireflyIII\Http\Controllers\Auth
* @method getEmailSubject()
* @method getSendResetLinkEmailSuccessResponse(string $response)
* @method getSendResetLinkEmailFailureResponse(string $response)
*/
class PasswordController extends Controller
{
use ResetsPasswords;
/**
* Create a new password controller instance.
*
*/
public function __construct()
{
parent::__construct();
$this->middleware('guest');
}
/**
* Send a reset link to the given user.
* @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's 7 but ok
*
* @param \Illuminate\Http\Request $request
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function sendResetLinkEmail(Request $request)
{
$this->validate($request, ['email' => 'required|email']);
$user = User::whereEmail($request->get('email'))->first();
$response = 'passwords.blocked';
if (is_null($user)) {
$response = Password::INVALID_USER;
}
if (!is_null($user) && intval($user->blocked) === 0) {
$response = Password::sendResetLink(
$request->only('email'), function (Message $message) {
$message->subject($this->getEmailSubject());
}
);
}
switch ($response) {
case Password::RESET_LINK_SENT:
return $this->getSendResetLinkEmailSuccessResponse($response);
case Password::INVALID_USER:
case 'passwords.blocked':
default:
return $this->getSendResetLinkEmailFailureResponse($response);
}
}
}

View File

@@ -1,42 +1,44 @@
<?php
declare(strict_types=1);
/**
* RegisterController.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Auth;
use Auth;
use Config;
use FireflyConfig;
use FireflyIII\Events\RegisteredUser;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\User;
use Illuminate\Auth\Events\Registered;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Session;
use Validator;
/**
* @codeCoverageIgnore
*
* Class RegisterController
*
* @package FireflyIII\Http\Controllers\Auth
*/
class RegisterController extends Controller
{
/*
|--------------------------------------------------------------------------
| Register Controller
|--------------------------------------------------------------------------
|
| This controller handles the registration of new users as well as their
| validation and creation. By default this controller uses a trait to
| provide this functionality without requiring any additional code.
|
*/
use RegistersUsers;
/**
* Where to redirect users after login / registration.
* Where to redirect users after registration.
*
* @var string
*/
@@ -44,6 +46,7 @@ class RegisterController extends Controller
/**
* Create a new controller instance.
*
*/
public function __construct()
{
@@ -52,14 +55,16 @@ class RegisterController extends Controller
}
/**
* @param Request $request
* Handle a registration request for the application.
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
* @param \Illuminate\Http\Request $request
*
* @return \Illuminate\Http\Response
*/
public function register(Request $request)
{
// is allowed to?
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
if ($singleUserMode === true && $userCount > 0) {
$message = 'Registration is currently not available.';
@@ -67,29 +72,19 @@ class RegisterController extends Controller
return view('error', compact('message'));
}
$this->validator($request->all())->validate();
$validator = $this->validator($request->all());
event(new Registered($user = $this->create($request->all())));
if ($validator->fails()) {
$this->throwValidationException($request, $validator);
}
$user = $this->create($request->all());
// trigger user registration event:
event(new RegisteredUser($user, $request->ip()));
Auth::login($user);
$this->guard()->login($user);
Session::flash('success', strval(trans('firefly.registered')));
Session::flash('gaEventCategory', 'user');
Session::flash('gaEventAction', 'new-registration');
return redirect($this->redirectPath());
return $this->registered($request, $user)
?: redirect($this->redirectPath());
}
/**
* OLD
* Show the application registration form.
*
* @param Request $request
@@ -99,10 +94,10 @@ class RegisterController extends Controller
public function showRegistrationForm(Request $request)
{
// is demo site?
$isDemoSite = FireflyConfig::get('is_demo_site', Config::get('firefly.configuration.is_demo_site'))->data;
$isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
// is allowed to?
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
if ($singleUserMode === true && $userCount > 0) {
$message = 'Registration is currently not available.';
@@ -112,6 +107,7 @@ class RegisterController extends Controller
$email = $request->old('email');
return view('auth.register', compact('isDemoSite', 'email'));
}
@@ -120,19 +116,16 @@ class RegisterController extends Controller
*
* @param array $data
*
* @return User
* @return \FireflyIII\User
*/
protected function create(array $data)
{
/** @var User $user */
$user = User::create(
return User::create(
[
'email' => $data['email'],
'password' => bcrypt($data['password']),
]
);
return $user;
}
/**
@@ -146,8 +139,8 @@ class RegisterController extends Controller
{
return Validator::make(
$data, [
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:6|confirmed',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|secure_password|confirmed',
]
);
}

View File

@@ -1,32 +1,43 @@
<?php
declare(strict_types=1);
/**
* ResetPasswordController.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Auth;
use FireflyIII\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\ResetsPasswords;
/**
* @codeCoverageIgnore
*
* Class ResetPasswordController
*
* @package FireflyIII\Http\Controllers\Auth
*/
class ResetPasswordController extends Controller
{
/*
|--------------------------------------------------------------------------
| Password Reset Controller
|--------------------------------------------------------------------------
|
| This controller is responsible for handling password reset requests
| and uses a simple trait to include this behavior. You're free to
| explore this trait and override any methods you wish to tweak.
|
*/
use ResetsPasswords;
/**
* Where to redirect users after resetting their password.
*
* @var string
*/
protected $redirectTo = '/home';
/**
* Create a new controller instance.
*
@@ -34,7 +45,6 @@ class ResetPasswordController extends Controller
public function __construct()
{
parent::__construct();
$this->middleware('guest');
}
}

View File

@@ -34,6 +34,8 @@ class TwoFactorController extends Controller
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function index(Request $request)
{

View File

@@ -13,6 +13,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Amount;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Http\Requests\BillFormRequest;
@@ -129,6 +130,11 @@ class BillController extends Controller
if (session('bills.edit.fromUpdate') !== true) {
$this->rememberPreviousUri('bills.edit.uri');
}
$currency = Amount::getDefaultCurrency();
$bill->amount_min = round($bill->amount_min, $currency->decimal_places);
$bill->amount_max = round($bill->amount_max, $currency->decimal_places);
$request->session()->forget('bills.edit.fromUpdate');
$request->session()->flash('gaEventCategory', 'bills');
$request->session()->flash('gaEventAction', 'edit');
@@ -206,7 +212,7 @@ class BillController extends Controller
/** @var Carbon $date */
$date = session('start');
$year = $date->year;
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$yearAverage = $repository->getYearAverage($bill, $date);
$overallAverage = $repository->getOverallAverage($bill);
@@ -217,7 +223,7 @@ class BillController extends Controller
$collector->setAllAssetAccounts()->setBills(new Collection([$bill]))->setLimit($pageSize)->setPage($page)->withBudgetInformation()
->withCategoryInformation();
$journals = $collector->getPaginatedJournals();
$journals->setPath('/bills/show/' . $bill->id);
$journals->setPath(route('bills.show', [$bill->id]));
$bill->nextExpectedMatch = $repository->nextExpectedMatch($bill, new Carbon);
$hideBill = true;

View File

@@ -40,6 +40,7 @@ use View;
* Class BudgetController
*
* @package FireflyIII\Http\Controllers
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class BudgetController extends Controller
{
@@ -75,11 +76,9 @@ class BudgetController extends Controller
*/
public function amount(Request $request, Budget $budget)
{
$amount = intval($request->get('amount'));
/** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */
$end = session('end', Carbon::now()->endOfMonth());
$amount = intval($request->get('amount'));
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
$budgetLimit = $this->repository->updateLimitAmount($budget, $start, $end, $amount);
if ($amount === 0) {
$budgetLimit = null;
@@ -170,6 +169,9 @@ class BudgetController extends Controller
* @param string|null $moment
*
* @return View
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity) complex because of while loop
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function index(string $moment = null)
{
@@ -184,7 +186,6 @@ class BudgetController extends Controller
$end = Navigation::endOfPeriod($start, $range);
} catch (Exception $e) {
// start and end are already defined.
}
}
$next = clone $end;
@@ -192,16 +193,12 @@ class BudgetController extends Controller
$prev = clone $start;
$prev->subDay();
$prev = Navigation::startOfPeriod($prev, $range);
$this->repository->cleanupBudgets();
$budgets = $this->repository->getActiveBudgets();
$inactive = $this->repository->getInactiveBudgets();
$periodStart = $start->formatLocalized($this->monthAndDayFormat);
$periodEnd = $end->formatLocalized($this->monthAndDayFormat);
$budgetInformation = $this->collectBudgetInformation($budgets, $start, $end);
$budgetInformation = $this->repository->collectBudgetInformation($budgets, $start, $end);
$defaultCurrency = Amount::getDefaultCurrency();
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
$spent = array_sum(array_column($budgetInformation, 'spent'));
@@ -243,17 +240,85 @@ class BudgetController extends Controller
compact(
'available', 'currentMonth', 'next', 'nextText', 'prev', 'prevText',
'periodStart', 'periodEnd', 'budgetInformation', 'inactive', 'budgets',
'spent', 'budgeted', 'previousLoop', 'nextLoop', 'start'
'spent', 'budgeted', 'previousLoop', 'nextLoop', 'start', 'end'
)
);
}
/**
* @param Carbon $start
* @param Carbon $end
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function infoIncome(Carbon $start, Carbon $end)
{
// properties for cache
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('info-income');
if ($cache->has()) {
$result = $cache->get(); // @codeCoverageIgnore
}
if (!$cache->has()) {
$result = [
'available' => '0',
'earned' => '0',
'suggested' => '0',
];
$currency = Amount::getDefaultCurrency();
$range = Preferences::get('viewRange', '1M')->data;
$begin = Navigation::subtractPeriod($start, $range, 3);
// get average amount available.
$total = '0';
$count = 0;
$currentStart = clone $begin;
while ($currentStart < $start) {
$currentEnd = Navigation::endOfPeriod($currentStart, $range);
$total = bcadd($total, $this->repository->getAvailableBudget($currency, $currentStart, $currentEnd));
$currentStart = Navigation::addPeriod($currentStart, $range, 0);
$count++;
}
$result['available'] = bcdiv($total, strval($count));
// amount earned in this period:
$subDay = clone $end;
$subDay->subDay();
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($begin, $subDay)->setTypes([TransactionType::DEPOSIT])->withOpposingAccount();
$result['earned'] = bcdiv(strval($collector->getJournals()->sum('transaction_amount')), strval($count));
// amount spent in period
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($begin, $subDay)->setTypes([TransactionType::WITHDRAWAL])->withOpposingAccount();
$result['spent'] = bcdiv(strval($collector->getJournals()->sum('transaction_amount')), strval($count));
// suggestion starts with the amount spent
$result['suggested'] = bcmul($result['spent'], '-1');
$result['suggested'] = bccomp($result['suggested'], $result['earned']) === 1 ? $result['earned'] : $result['suggested'];
// unless it's more than you earned. So min() of suggested/earned
$cache->store($result);
}
return view('budgets.info', compact('result', 'begin', 'currentEnd'));
}
/**
* @param Request $request
* @param JournalRepositoryInterface $repository
* @param string $moment
*
* @return View
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function noBudget(Request $request, JournalRepositoryInterface $repository, string $moment = '')
{
@@ -293,37 +358,15 @@ class BudgetController extends Controller
);
}
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$count = 0;
$loop = 0;
// grab journals, but be prepared to jump a period back to get the right ones:
Log::info('Now at no-budget loop start.');
while ($count === 0 && $loop < 3) {
$loop++;
Log::info(sprintf('Count is zero, search for journals between %s and %s.', $start->format('Y-m-d'), $end->format('Y-m-d')));
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setLimit($pageSize)->setPage($page)
->withoutBudget()->withOpposingAccount();
$journals = $collector->getPaginatedJournals();
$journals->setPath('/budgets/list/no-budget');
$count = $journals->getCollection()->count();
if ($count === 0 && $loop < 3) {
$start->subDay();
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfPeriod($start, $range);
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
}
}
if ($moment !== 'all' && $loop > 1) {
$subTitle = trans(
'firefly.without_budget_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL])->setLimit($pageSize)->setPage($page)
->withoutBudget()->withOpposingAccount();
$journals = $collector->getPaginatedJournals();
$journals->setPath(route('budgets.no-budget'));
return view('budgets.no-budget', compact('journals', 'subTitle', 'moment', 'periods', 'start', 'end'));
}
@@ -335,15 +378,15 @@ class BudgetController extends Controller
*/
public function postUpdateIncome(BudgetIncomeRequest $request)
{
$start = session('start', new Carbon);
$end = session('end', new Carbon);
$start = Carbon::createFromFormat('Y-m-d', $request->string('start'));
$end = Carbon::createFromFormat('Y-m-d', $request->string('end'));
$defaultCurrency = Amount::getDefaultCurrency();
$amount = $request->get('amount');
$this->repository->setAvailableBudget($defaultCurrency, $start, $end, $amount);
Preferences::mark();
return redirect(route('budgets.index'));
return redirect(route('budgets.index', [$start->format('Y-m-d')]));
}
/**
@@ -357,7 +400,7 @@ class BudgetController extends Controller
/** @var Carbon $start */
$start = session('first', Carbon::create()->startOfYear());
$end = new Carbon;
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$limits = $this->getLimits($budget, $start, $end);
$repetition = null;
@@ -366,7 +409,7 @@ class BudgetController extends Controller
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setBudget($budget)->setLimit($pageSize)->setPage($page)->withCategoryInformation();
$journals = $collector->getPaginatedJournals();
$journals->setPath('/budgets/show/' . $budget->id);
$journals->setPath(route('budgets.show', [$budget->id]));
$subTitle = trans('firefly.all_journals_for_budget', ['name' => $budget->name]);
@@ -388,7 +431,7 @@ class BudgetController extends Controller
throw new FireflyException('This budget limit is not part of this budget.');
}
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$subTitle = trans(
'firefly.budget_in_period', [
@@ -404,7 +447,7 @@ class BudgetController extends Controller
$collector->setAllAssetAccounts()->setRange($budgetLimit->start_date, $budgetLimit->end_date)
->setBudget($budget)->setLimit($pageSize)->setPage($page)->withCategoryInformation();
$journals = $collector->getPaginatedJournals();
$journals->setPath('/budgets/show/' . $budget->id . '/' . $budgetLimit->id);
$journals->setPath(route('budgets.show', [$budget->id, $budgetLimit->id]));
$start = session('first', Carbon::create()->startOfYear());
@@ -465,62 +508,20 @@ class BudgetController extends Controller
}
/**
* @return View
* @param Carbon $start
* @param Carbon $end
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function updateIncome()
public function updateIncome(Carbon $start, Carbon $end)
{
$start = session('start', new Carbon);
$end = session('end', new Carbon);
$defaultCurrency = Amount::getDefaultCurrency();
$available = $this->repository->getAvailableBudget($defaultCurrency, $start, $end);
$available = round($available, $defaultCurrency->decimal_places);
return view('budgets.income', compact('available', 'start', 'end'));
}
/**
* @param Collection $budgets
* @param Carbon $start
* @param Carbon $end
*
* @return array
*/
private function collectBudgetInformation(Collection $budgets, Carbon $start, Carbon $end): array
{
// get account information
/** @var AccountRepositoryInterface $accountRepository */
$accountRepository = app(AccountRepositoryInterface::class);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET, AccountType::CASH]);
$return = [];
/** @var Budget $budget */
foreach ($budgets as $budget) {
$budgetId = $budget->id;
$return[$budgetId] = [
'spent' => $this->repository->spentInPeriod(new Collection([$budget]), $accounts, $start, $end),
'budgeted' => '0',
'currentRep' => false,
];
$budgetLimits = $this->repository->getBudgetLimits($budget, $start, $end);
$otherLimits = new Collection;
// get all the budget limits relevant between start and end and examine them:
/** @var BudgetLimit $limit */
foreach ($budgetLimits as $limit) {
if ($limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end)
) {
$return[$budgetId]['currentLimit'] = $limit;
$return[$budgetId]['budgeted'] = $limit->amount;
continue;
}
// otherwise it's just one of the many relevant repetitions:
$otherLimits->push($limit);
}
$return[$budgetId]['otherLimits'] = $otherLimits;
}
return $return;
}
/**
* @param Budget $budget
* @param Carbon $start
@@ -567,7 +568,7 @@ class BudgetController extends Controller
$start = $first->date ?? new Carbon;
$range = Preferences::get('viewRange', '1M')->data;
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfX(new Carbon, $range);
$end = Navigation::endOfX(new Carbon, $range, null);
$entries = new Collection;
// properties for cache

View File

@@ -164,10 +164,12 @@ class CategoryController extends Controller
public function noCategory(Request $request, JournalRepositoryInterface $repository, string $moment = '')
{
// default values:
$range = Preferences::get('viewRange', '1M')->data;
$start = null;
$end = null;
$periods = new Collection;
$range = Preferences::get('viewRange', '1M')->data;
$start = null;
$end = null;
$periods = new Collection;
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
// prep for "all" view.
if ($moment === 'all') {
@@ -199,37 +201,14 @@ class CategoryController extends Controller
);
}
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$count = 0;
$loop = 0;
// grab journals, but be prepared to jump a period back to get the right ones:
Log::info('Now at no-cat loop start.');
while ($count === 0 && $loop < 3) {
$loop++;
Log::info('Count is zero, search for journals.');
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withoutCategory()->withOpposingAccount();
$collector->removeFilter(InternalTransferFilter::class);
$journals = $collector->getPaginatedJournals();
$journals->setPath('/categories/list/no-category');
$count = $journals->getCollection()->count();
if ($count === 0 && $loop < 3) {
$start->subDay();
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfPeriod($start, $range);
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
}
}
if ($moment !== 'all' && $loop > 1) {
$subTitle = trans(
'firefly.without_category_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withoutCategory()->withOpposingAccount()
->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]);
$collector->removeFilter(InternalTransferFilter::class);
$journals = $collector->getPaginatedJournals();
$journals->setPath(route('categories.no-category'));
return view('categories.no-category', compact('journals', 'subTitle', 'moment', 'periods', 'start', 'end'));
}
@@ -247,20 +226,19 @@ class CategoryController extends Controller
// default values:
$subTitle = $category->name;
$subTitleIcon = 'fa-bar-chart';
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$count = 0;
$loop = 0;
$range = Preferences::get('viewRange', '1M')->data;
$start = null;
$end = null;
$periods = new Collection;
// prep for "all" view.
if ($moment === 'all') {
$subTitle = trans('firefly.all_journals_for_category', ['name' => $category->name]);
$start = $repository->firstUseDate($category);
$first = $repository->firstUseDate($category);
/** @var Carbon $start */
$start = is_null($first) ? new Carbon : $first;
$end = new Carbon;
}
@@ -278,7 +256,9 @@ class CategoryController extends Controller
// prep for current period
if (strlen($moment) === 0) {
/** @var Carbon $start */
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
/** @var Carbon $end */
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
$periods = $this->getPeriodOverview($category);
$subTitle = trans(
@@ -287,34 +267,15 @@ class CategoryController extends Controller
'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
// grab journals, but be prepared to jump a period back to get the right ones:
Log::info('Now at category loop start.');
while ($count === 0 && $loop < 3) {
$loop++;
Log::info('Count is zero, search for journals.');
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withOpposingAccount()
->setCategory($category)->withBudgetInformation()->withCategoryInformation();
$collector->removeFilter(InternalTransferFilter::class);
$journals = $collector->getPaginatedJournals();
$journals->setPath('categories/show/' . $category->id);
$count = $journals->getCollection()->count();
if ($count === 0 && $loop < 3) {
$start->subDay();
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfPeriod($start, $range);
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
}
}
if ($moment !== 'all' && $loop > 1) {
$subTitle = trans(
'firefly.journals_in_period_for_category',
['name' => $category->name, 'start' => $start->formatLocalized($this->monthAndDayFormat),
'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withOpposingAccount()
->setCategory($category)->withBudgetInformation()->withCategoryInformation();
$collector->removeFilter(InternalTransferFilter::class);
$journals = $collector->getPaginatedJournals();
$journals->setPath(route('categories.show', [$category->id]));
return view('categories.show', compact('category', 'moment', 'journals', 'periods', 'subTitle', 'subTitleIcon', 'start', 'end'));
}
@@ -382,7 +343,7 @@ class CategoryController extends Controller
$start = $first->date ?? new Carbon;
$range = Preferences::get('viewRange', '1M')->data;
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfX(new Carbon, $range);
$end = Navigation::endOfX(new Carbon, $range, null);
$entries = new Collection;
// properties for cache
@@ -401,11 +362,11 @@ class CategoryController extends Controller
$end = Navigation::startOfPeriod($end, $range);
$currentEnd = Navigation::endOfPeriod($end, $range);
// count journals without budget in this period:
// count journals without category in this period:
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withoutCategory()
->withOpposingAccount();
->withOpposingAccount()->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]);
$collector->removeFilter(InternalTransferFilter::class);
$count = $collector->getJournals()->count();
@@ -463,13 +424,14 @@ class CategoryController extends Controller
$accountRepository = app(AccountRepositoryInterface::class);
$accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$first = $repository->firstUseDate($category);
if ($first->year === 1900) {
if (is_null($first)) {
$first = new Carbon;
}
$range = Preferences::get('viewRange', '1M')->data;
$first = Navigation::startOfPeriod($first, $range);
$end = Navigation::endOfX(new Carbon, $range);
$end = Navigation::endOfX(new Carbon, $range, null);
$entries = new Collection;
$count = 0;
// properties for entries with their amounts.
$cache = new CacheProperties();
@@ -481,7 +443,7 @@ class CategoryController extends Controller
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
while ($end >= $first) {
while ($end >= $first && $count < 90) {
$end = Navigation::startOfPeriod($end, $range);
$currentEnd = Navigation::endOfPeriod($end, $range);
$spent = $repository->spentInPeriod(new Collection([$category]), $accounts, $end, $currentEnd);
@@ -509,6 +471,7 @@ class CategoryController extends Controller
]
);
$end = Navigation::subtractPeriod($end, $range, 1);
$count++;
}
$cache->store($entries);

View File

@@ -163,7 +163,7 @@ class BudgetController extends Controller
*
* @return \Illuminate\Http\JsonResponse
*/
public function expenseAsset(Budget $budget, BudgetLimit $budgetLimit = null)
public function expenseAsset(Budget $budget, ?BudgetLimit $budgetLimit)
{
$cache = new CacheProperties;
$cache->addProperty($budget->id);
@@ -208,7 +208,7 @@ class BudgetController extends Controller
*
* @return \Illuminate\Http\JsonResponse
*/
public function expenseCategory(Budget $budget, BudgetLimit $budgetLimit = null)
public function expenseCategory(Budget $budget, ?BudgetLimit $budgetLimit)
{
$cache = new CacheProperties;
$cache->addProperty($budget->id);
@@ -255,7 +255,7 @@ class BudgetController extends Controller
*
* @return \Illuminate\Http\JsonResponse
*/
public function expenseExpense(Budget $budget, BudgetLimit $budgetLimit = null)
public function expenseExpense(Budget $budget, ?BudgetLimit $budgetLimit)
{
$cache = new CacheProperties;
$cache->addProperty($budget->id);

View File

@@ -67,7 +67,7 @@ class CategoryController extends Controller
$start = $repository->firstUseDate($category);
if ($start->year === 1900) {
if (is_null($start)) {
$start = new Carbon;
}

View File

@@ -44,6 +44,8 @@ class Controller extends BaseController
protected $monthAndDayFormat;
/** @var string */
protected $monthFormat;
/** @var string */
protected $redirectUri = '/';
/**
* Controller constructor.
@@ -61,6 +63,7 @@ class Controller extends BaseController
View::share('IS_DEMO_SITE', $isDemoSite);
View::share('DEMO_USERNAME', env('DEMO_USERNAME', ''));
View::share('DEMO_PASSWORD', env('DEMO_PASSWORD', ''));
View::share('FF_VERSION', config('firefly.version'));
$this->middleware(
@@ -115,10 +118,10 @@ class Controller extends BaseController
{
$uri = strval(session($identifier));
if (!(strpos($identifier, 'delete') === false) && !(strpos($uri, '/show/') === false)) {
$uri = route('index');
$uri = $this->redirectUri;
}
if (!(strpos($uri, 'javascript') === false)) {
$uri = route('index');
if (!(strpos($uri, 'jscript') === false)) {
$uri = $this->redirectUri;
}
return $uri;

View File

@@ -46,7 +46,7 @@ class ExportController extends Controller
$this->middleware(
function ($request, $next) {
View::share('mainTitleIcon', 'fa-file-archive-o');
View::share('title', trans('firefly.export_data'));
View::share('title', trans('firefly.export_and_backup_data'));
return $next($request);
}
@@ -137,13 +137,14 @@ class ExportController extends Controller
public function postIndex(ExportFormRequest $request, AccountRepositoryInterface $repository, ExportJobRepositoryInterface $jobs)
{
$job = $jobs->findByKey($request->get('job'));
$accounts = $request->get('accounts') ?? [];
$settings = [
'accounts' => $repository->getAccountsById($request->get('accounts')),
'accounts' => $repository->getAccountsById($accounts),
'startDate' => new Carbon($request->get('export_start_range')),
'endDate' => new Carbon($request->get('export_end_range')),
'exportFormat' => $request->get('exportFormat'),
'includeAttachments' => intval($request->get('include_attachments')) === 1,
'includeOldUploads' => intval($request->get('include_old_uploads')) === 1,
'includeAttachments' => $request->boolean('include_attachments'),
'includeOldUploads' => $request->boolean('include_old_uploads'),
'job' => $job,
];
@@ -159,12 +160,14 @@ class ExportController extends Controller
$jobs->changeStatus($job, 'export_status_collecting_journals');
$processor->collectJournals();
$jobs->changeStatus($job, 'export_status_collected_journals');
/*
* Transform to exportable entries:
*/
$jobs->changeStatus($job, 'export_status_converting_to_export_format');
$processor->convertJournals();
$jobs->changeStatus($job, 'export_status_converted_to_export_format');
/*
* Transform to (temporary) file:
*/
@@ -180,6 +183,7 @@ class ExportController extends Controller
$jobs->changeStatus($job, 'export_status_collected_attachments');
}
/*
* Collect old uploads
*/

View File

@@ -82,6 +82,14 @@ class HomeController extends Controller
*/
public function displayError()
{
Log::debug('This is a test message at the DEBUG level.');
Log::info('This is a test message at the INFO level.');
Log::notice('This is a test message at the NOTICE level.');
Log::warning('This is a test message at the WARNING level.');
Log::error('This is a test message at the ERROR level.');
Log::critical('This is a test message at the CRITICAL level.');
Log::alert('This is a test message at the ALERT level.');
Log::emergency('This is a test message at the EMERGENCY level.');
throw new FireflyException('A very simple test error.');
}
@@ -121,9 +129,9 @@ class HomeController extends Controller
/** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */
$end = session('end', Carbon::now()->endOfMonth());
$accounts = $repository->getAccountsById($frontPage->data);
$showDepositsFrontpage = Preferences::get('showDepositsFrontpage', false)->data;
$end = session('end', Carbon::now()->endOfMonth());
$accounts = $repository->getAccountsById($frontPage->data);
$showDeps = Preferences::get('showDepositsFrontpage', false)->data;
// zero bills? Hide some elements from view.
/** @var BillRepositoryInterface $billRepository */
@@ -138,7 +146,7 @@ class HomeController extends Controller
}
return view(
'index', compact('count', 'title', 'subTitle', 'mainTitleIcon', 'transactions', 'showDepositsFrontpage', 'billCount')
'index', compact('count', 'subTitle', 'transactions', 'showDeps', 'billCount')
);
}

View File

@@ -0,0 +1,153 @@
<?php
/**
* BankController.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Import;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Support\Import\Information\InformationInterface;
use FireflyIII\Support\Import\Prerequisites\PrerequisitesInterface;
use Illuminate\Http\Request;
use Log;
use Session;
class BankController extends Controller
{
/**
* This method must ask the user all parameters necessary to start importing data. This may not be enough
* to finish the import itself (ie. mapping) but it should be enough to begin: accounts to import from,
* accounts to import into, data ranges, etc.
*
* @param string $bank
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
*/
public function form(string $bank)
{
$class = config(sprintf('firefly.import_pre.%s', $bank));
/** @var PrerequisitesInterface $object */
$object = app($class);
$object->setUser(auth()->user());
if ($object->hasPrerequisites()) {
return redirect(route('import.bank.prerequisites', [$bank]));
}
$class = config(sprintf('firefly.import_info.%s', $bank));
/** @var InformationInterface $object */
$object = app($class);
$object->setUser(auth()->user());
$remoteAccounts = $object->getAccounts();
return view('import.bank.form', compact('remoteAccounts', 'bank'));
}
/**
* With the information given in the submitted form Firefly III will call upon the bank's classes to return transaction
* information as requested. The user will be able to map unknown data and continue. Or maybe, it's put into some kind of
* fake CSV file and forwarded to the import routine.
*
* @param Request $request
* @param string $bank
*
* @return \Illuminate\Http\RedirectResponse|null
*/
public function postForm(Request $request, string $bank)
{
$class = config(sprintf('firefly.import_pre.%s', $bank));
/** @var PrerequisitesInterface $object */
$object = app($class);
$object->setUser(auth()->user());
if ($object->hasPrerequisites()) {
return redirect(route('import.bank.prerequisites', [$bank]));
}
$remoteAccounts = $request->get('do_import');
if (!is_array($remoteAccounts) || count($remoteAccounts) === 0) {
Session::flash('error', 'Must select accounts');
return redirect(route('import.bank.form', [$bank]));
}
$remoteAccounts = array_keys($remoteAccounts);
$class = config(sprintf('firefly.import_pre.%s', $bank));
// get import file
// get import config
}
/**
* This method processes the prerequisites the user has entered in the previous step.
*
* Whatever storePrerequisites does, it should make sure that the system is ready to continue immediately. So
* no extra calls or stuff, except maybe to open a session
*
* @see PrerequisitesInterface::storePrerequisites
*
* @param Request $request
* @param string $bank
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function postPrerequisites(Request $request, string $bank)
{
Log::debug(sprintf('Now in postPrerequisites for %s', $bank));
$class = config(sprintf('firefly.import_pre.%s', $bank));
/** @var PrerequisitesInterface $object */
$object = app($class);
$object->setUser(auth()->user());
if (!$object->hasPrerequisites()) {
Log::debug(sprintf('No more prerequisites for %s, move to form.', $bank));
return redirect(route('import.bank.form', [$bank]));
}
Log::debug('Going to store entered preprerequisites.');
// store post data
$result = $object->storePrerequisites($request);
if ($result->count() > 0) {
Session::flash('error', $result->first());
return redirect(route('import.bank.prerequisites', [$bank]));
}
return redirect(route('import.bank.form', [$bank]));
}
/**
* This method shows you, if necessary, a form that allows you to enter any required values, such as API keys,
* login passwords or other values.
*
* @param string $bank
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
*/
public function prerequisites(string $bank)
{
$class = config(sprintf('firefly.import_pre.%s', $bank));
/** @var PrerequisitesInterface $object */
$object = app($class);
$object->setUser(auth()->user());
if ($object->hasPrerequisites()) {
$view = $object->getView();
$parameters = $object->getViewParameters();
return view($view, $parameters);
}
return redirect(route('import.bank.form', [$bank]));
}
}

View File

@@ -0,0 +1,306 @@
<?php
/**
* FileController.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Import;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\ImportUploadRequest;
use FireflyIII\Import\Configurator\ConfiguratorInterface;
use FireflyIII\Import\Routine\ImportRoutine;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Http\Request;
use Illuminate\Http\Response as LaravelResponse;
use Log;
use Response;
use Session;
use View;
/**
* Class FileController.
*
* @package FireflyIII\Http\Controllers\Import
*/
class FileController extends Controller
{
/** @var ImportJobRepositoryInterface */
public $repository;
/**
*
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
View::share('mainTitleIcon', 'fa-archive');
View::share('title', trans('firefly.import_index_title'));
$this->repository = app(ImportJobRepositoryInterface::class);
return $next($request);
}
);
}
/**
* This is step 3. This repeats until the job is configured.
*
* @param ImportJob $job
*
* @return View
* @throws FireflyException
*/
public function configure(ImportJob $job)
{
// create configuration class:
$configurator = $this->makeConfigurator($job);
// is the job already configured?
if ($configurator->isJobConfigured()) {
$this->repository->updateStatus($job, 'configured');
return redirect(route('import.file.status', [$job->key]));
}
$view = $configurator->getNextView();
$data = $configurator->getNextData();
$subTitle = trans('firefly.import_config_bread_crumb');
$subTitleIcon = 'fa-wrench';
return view($view, compact('data', 'job', 'subTitle', 'subTitleIcon'));
}
/**
* Generate a JSON file of the job's configuration and send it to the user.
*
* @param ImportJob $job
*
* @return LaravelResponse
*/
public function download(ImportJob $job)
{
Log::debug('Now in download()', ['job' => $job->key]);
$config = $job->configuration;
// This is CSV import specific:
$config['column-roles-complete'] = false;
$config['column-mapping-complete'] = false;
$config['initial-config-complete'] = false;
$config['delimiter'] = $config['delimiter'] === "\t" ? 'tab' : $config['delimiter'];
$result = json_encode($config, JSON_PRETTY_PRINT);
$name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\'));
/** @var LaravelResponse $response */
$response = response($result, 200);
$response->header('Content-disposition', 'attachment; filename=' . $name)
->header('Content-Type', 'application/json')
->header('Content-Description', 'File Transfer')
->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($result));
return $response;
}
/**
* This is step 1. Upload a file.
*
* @return View
*/
public function index()
{
$subTitle = trans('firefly.import_index_sub_title');
$subTitleIcon = 'fa-home';
$importFileTypes = [];
$defaultImportType = config('firefly.default_import_format');
foreach (array_keys(config('firefly.import_formats')) as $type) {
$importFileTypes[$type] = trans('firefly.import_file_type_' . $type);
}
return view('import.file.index', compact('subTitle', 'subTitleIcon', 'importFileTypes', 'defaultImportType'));
}
/**
* This is step 2. It creates an Import Job. Stores the import.
*
* @param ImportUploadRequest $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function initialize(ImportUploadRequest $request)
{
Log::debug('Now in initialize()');
// create import job:
$type = $request->get('import_file_type');
$job = $this->repository->create($type);
Log::debug('Created new job', ['key' => $job->key, 'id' => $job->id]);
// process file:
$this->repository->processFile($job, $request->files->get('import_file'));
// process config, if present:
if ($request->files->has('configuration_file')) {
$this->repository->processConfiguration($job, $request->files->get('configuration_file'));
}
$this->repository->updateStatus($job, 'initialized');
return redirect(route('import.file.configure', [$job->key]));
}
/**
*
* Show status of import job in JSON.
*
* @param ImportJob $job
*
* @return \Illuminate\Http\JsonResponse
*/
public function json(ImportJob $job)
{
$result = [
'started' => false,
'finished' => false,
'running' => false,
'errors' => array_values($job->extended_status['errors']),
'percentage' => 0,
'show_percentage' => false,
'steps' => $job->extended_status['steps'],
'done' => $job->extended_status['done'],
'statusText' => trans('firefly.import_status_job_' . $job->status),
'status' => $job->status,
'finishedText' => '',
];
if ($job->extended_status['steps'] !== 0) {
$result['percentage'] = round(($job->extended_status['done'] / $job->extended_status['steps']) * 100, 0);
$result['show_percentage'] = true;
}
if ($job->status === 'finished') {
$tagId = $job->extended_status['tag'];
/** @var TagRepositoryInterface $repository */
$repository = app(TagRepositoryInterface::class);
$tag = $repository->find($tagId);
$result['finished'] = true;
$result['finishedText'] = trans('firefly.import_status_finished_job', ['link' => route('tags.show', [$tag->id, 'all']), 'tag' => $tag->tag]);
}
if ($job->status === 'running') {
$result['started'] = true;
$result['running'] = true;
}
return Response::json($result);
}
/**
* Step 4. Save the configuration.
*
* @param Request $request
* @param ImportJob $job
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function postConfigure(Request $request, ImportJob $job)
{
Log::debug('Now in postConfigure()', ['job' => $job->key]);
$configurator = $this->makeConfigurator($job);
// is the job already configured?
if ($configurator->isJobConfigured()) {
return redirect(route('import.file.status', [$job->key]));
}
$data = $request->all();
$configurator->configureJob($data);
// get possible warning from configurator:
$warning = $configurator->getWarningMessage();
if (strlen($warning) > 0) {
Session::flash('warning', $warning);
}
// return to configure
return redirect(route('import.file.configure', [$job->key]));
}
/**
* @param ImportJob $job
*
* @return \Illuminate\Http\JsonResponse
* @throws FireflyException
*/
public function start(ImportJob $job)
{
/** @var ImportRoutine $routine */
$routine = app(ImportRoutine::class);
$routine->setJob($job);
$result = $routine->run();
if ($result) {
return Response::json(['run' => 'ok']);
}
throw new FireflyException('Job did not complete succesfully.');
}
/**
* @param ImportJob $job
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
*/
public function status(ImportJob $job)
{
$statuses = ['configured', 'running', 'finished'];
if (!in_array($job->status, $statuses)) {
return redirect(route('import.file.configure', [$job->key]));
}
$subTitle = trans('firefly.import_status_sub_title');
$subTitleIcon = 'fa-star';
return view('import.file.status', compact('job', 'subTitle', 'subTitleIcon'));
}
/**
* @param ImportJob $job
*
* @return ConfiguratorInterface
* @throws FireflyException
*/
private function makeConfigurator(ImportJob $job): ConfiguratorInterface
{
$type = $job->file_type;
$key = sprintf('firefly.import_configurators.%s', $type);
$className = config($key);
if (is_null($className)) {
throw new FireflyException('Cannot find configurator class for this job.'); // @codeCoverageIgnore
}
/** @var ConfiguratorInterface $configurator */
$configurator = app($className);
$configurator->setJob($job);
return $configurator;
}
}

View File

@@ -12,17 +12,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Requests\ImportUploadRequest;
use FireflyIII\Import\Configurator\ConfiguratorInterface;
use FireflyIII\Import\Routine\ImportRoutine;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use Illuminate\Http\Request;
use Illuminate\Http\Response as LaravelResponse;
use Log;
use Response;
use View;
/**
@@ -53,72 +43,9 @@ class ImportController extends Controller
);
}
/**
* This is step 3. This repeats until the job is configured.
*
* @param ImportJob $job
*
* @return View
* @throws FireflyException
*/
public function configure(ImportJob $job)
{
// create configuration class:
$configurator = $this->makeConfigurator($job);
// is the job already configured?
if ($configurator->isJobConfigured()) {
$this->repository->updateStatus($job, 'configured');
return redirect(route('import.status', [$job->key]));
}
$view = $configurator->getNextView();
$data = $configurator->getNextData();
$subTitle = trans('firefly.import_config_bread_crumb');
$subTitleIcon = 'fa-wrench';
return view($view, compact('data', 'job', 'subTitle', 'subTitleIcon'));
}
/**
* Generate a JSON file of the job's configuration and send it to the user.
*
* @param ImportJob $job
*
* @return LaravelResponse
*/
public function download(ImportJob $job)
{
Log::debug('Now in download()', ['job' => $job->key]);
$config = $job->configuration;
// This is CSV import specific:
$config['column-roles-complete'] = false;
$config['column-mapping-complete'] = false;
$config['initial-config-complete'] = false;
$config['delimiter'] = $config['delimiter'] === "\t" ? 'tab' : $config['delimiter'];
$result = json_encode($config, JSON_PRETTY_PRINT);
$name = sprintf('"%s"', addcslashes('import-configuration-' . date('Y-m-d') . '.json', '"\\'));
/** @var LaravelResponse $response */
$response = response($result, 200);
$response->header('Content-disposition', 'attachment; filename=' . $name)
->header('Content-Type', 'application/json')
->header('Content-Description', 'File Transfer')
->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($result));
return $response;
}
/**
* This is step 1. Upload a file.
* General import index
*
* @return View
*/
@@ -136,160 +63,4 @@ class ImportController extends Controller
return view('import.index', compact('subTitle', 'subTitleIcon', 'importFileTypes', 'defaultImportType'));
}
/**
* This is step 2. It creates an Import Job. Stores the import.
*
* @param ImportUploadRequest $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function initialize(ImportUploadRequest $request)
{
Log::debug('Now in initialize()');
// create import job:
$type = $request->get('import_file_type');
$job = $this->repository->create($type);
Log::debug('Created new job', ['key' => $job->key, 'id' => $job->id]);
// process file:
$this->repository->processFile($job, $request->files->get('import_file'));
// process config, if present:
if ($request->files->has('configuration_file')) {
$this->repository->processConfiguration($job, $request->files->get('configuration_file'));
}
$this->repository->updateStatus($job, 'initialized');
return redirect(route('import.configure', [$job->key]));
}
/**
*
* Show status of import job in JSON.
*
* @param ImportJob $job
*
* @return \Illuminate\Http\JsonResponse
*/
public function json(ImportJob $job)
{
$result = [
'started' => false,
'finished' => false,
'running' => false,
'errors' => array_values($job->extended_status['errors']),
'percentage' => 0,
'show_percentage' => false,
'steps' => $job->extended_status['steps'],
'done' => $job->extended_status['done'],
'statusText' => trans('firefly.import_status_job_' . $job->status),
'status' => $job->status,
'finishedText' => '',
];
if ($job->extended_status['steps'] !== 0) {
$result['percentage'] = round(($job->extended_status['done'] / $job->extended_status['steps']) * 100, 0);
$result['show_percentage'] = true;
}
if ($job->status === 'finished') {
$tagId = $job->extended_status['tag'];
/** @var TagRepositoryInterface $repository */
$repository = app(TagRepositoryInterface::class);
$tag = $repository->find($tagId);
$result['finished'] = true;
$result['finishedText'] = trans('firefly.import_status_finished_job', ['link' => route('tags.show', [$tag->id, 'all']), 'tag' => $tag->tag]);
}
if ($job->status === 'running') {
$result['started'] = true;
$result['running'] = true;
}
return Response::json($result);
}
/**
* Step 4. Save the configuration.
*
* @param Request $request
* @param ImportJob $job
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function postConfigure(Request $request, ImportJob $job)
{
Log::debug('Now in postConfigure()', ['job' => $job->key]);
$configurator = $this->makeConfigurator($job);
// is the job already configured?
if ($configurator->isJobConfigured()) {
return redirect(route('import.status', [$job->key]));
}
$data = $request->all();
$configurator->configureJob($data);
// return to configure
return redirect(route('import.configure', [$job->key]));
}
/**
* @param ImportJob $job
*
* @return \Illuminate\Http\JsonResponse
* @throws FireflyException
*/
public function start(ImportJob $job)
{
/** @var ImportRoutine $routine */
$routine = app(ImportRoutine::class);
$routine->setJob($job);
$result = $routine->run();
if ($result) {
return Response::json(['run' => 'ok']);
}
throw new FireflyException('Job did not complete succesfully.');
}
/**
* @param ImportJob $job
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
*/
public function status(ImportJob $job)
{
$statuses = ['configured', 'running', 'finished'];
if (!in_array($job->status, $statuses)) {
return redirect(route('import.configure', [$job->key]));
}
$subTitle = trans('firefly.import_status_sub_title');
$subTitleIcon = 'fa-star';
return view('import.status', compact('job', 'subTitle', 'subTitleIcon'));
}
/**
* @param ImportJob $job
*
* @return ConfiguratorInterface
* @throws FireflyException
*/
private function makeConfigurator(ImportJob $job): ConfiguratorInterface
{
$type = $job->file_type;
$key = sprintf('firefly.import_configurators.%s', $type);
$className = config($key);
if (is_null($className)) {
throw new FireflyException('Cannot find configurator class for this job.'); // @codeCoverageIgnore
}
/** @var ConfiguratorInterface $configurator */
$configurator = app($className);
$configurator->setJob($job);
return $configurator;
}
}

View File

@@ -12,6 +12,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Amount;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
@@ -19,9 +20,9 @@ use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use Illuminate\Http\Request;
use Log;
use Navigation;
use Preferences;
use Session;
/**
* Class JavascriptController
@@ -88,11 +89,6 @@ class JavascriptController extends Controller
*/
public function variables(Request $request)
{
$picker = $this->getDateRangePicker();
$start = Session::get('start');
$end = Session::get('end');
$linkTitle = sprintf('%s - %s', $start->formatLocalized($this->monthAndDayFormat), $end->formatLocalized($this->monthAndDayFormat));
$firstDate = session('first')->format('Y-m-d');
$localeconv = localeconv();
$accounting = Amount::getJsConfig($localeconv);
$localeconv = localeconv();
@@ -100,15 +96,16 @@ class JavascriptController extends Controller
$localeconv['frac_digits'] = $defaultCurrency->decimal_places;
$pref = Preferences::get('language', config('firefly.default_language', 'en_US'));
$lang = $pref->data;
$data = [
'picker' => $picker,
'linkTitle' => $linkTitle,
'firstDate' => $firstDate,
'currencyCode' => Amount::getCurrencyCode(),
'currencySymbol' => Amount::getCurrencySymbol(),
'accounting' => $accounting,
'localeconv' => $localeconv,
'language' => $lang,
$dateRange = $this->getDateRangeConfig();
$data = [
'currencyCode' => Amount::getCurrencyCode(),
'currencySymbol' => Amount::getCurrencySymbol(),
'accounting' => $accounting,
'localeconv' => $localeconv,
'language' => $lang,
'dateRangeTitle' => $dateRange['title'],
'dateRangeConfig' => $dateRange['configuration'],
];
$request->session()->keep(['two-factor-secret']);
@@ -119,40 +116,73 @@ class JavascriptController extends Controller
/**
* @return array
* @throws FireflyException
*/
private function getDateRangePicker(): array
private function getDateRangeConfig(): array
{
$viewRange = Preferences::get('viewRange', '1M')->data;
$start = Session::get('start');
$end = Session::get('end');
$start = session('start');
$end = session('end');
$first = session('first');
$title = sprintf('%s - %s', $start->formatLocalized($this->monthAndDayFormat), $end->formatLocalized($this->monthAndDayFormat));
$isCustom = session('is_custom_range');
$ranges = [
// first range is the current range:
$title => [$start, $end],
];
Log::debug(sprintf('viewRange is %s', $viewRange));
$prevStart = clone $start;
$prevEnd = clone $start;
$nextStart = clone $end;
$nextEnd = clone $end;
if ($viewRange === 'custom') {
$days = $start->diffInDays($end);
$prevStart->subDays($days);
$nextEnd->addDays($days);
unset($days);
// get the format for the ranges:
$format = $this->getFormatByRange($viewRange);
// when current range is a custom range, add the current period as the next range.
if ($isCustom) {
Log::debug('Custom is true.');
$index = $start->formatLocalized($format);
$customPeriodStart = Navigation::startOfPeriod($start, $viewRange);
$customPeriodEnd = Navigation::endOfPeriod($customPeriodStart, $viewRange);
$ranges[$index] = [$customPeriodStart, $customPeriodEnd];
}
// then add previous range and next range
$previousDate = Navigation::subtractPeriod($start, $viewRange);
$index = $previousDate->formatLocalized($format);
$previousStart = Navigation::startOfPeriod($previousDate, $viewRange);
$previousEnd = Navigation::endOfPeriod($previousStart, $viewRange);
$ranges[$index] = [$previousStart, $previousEnd];
if ($viewRange !== 'custom') {
$prevStart = Navigation::subtractPeriod($start, $viewRange);// subtract for previous period
$prevEnd = Navigation::endOfPeriod($prevStart, $viewRange);
$nextStart = Navigation::addPeriod($start, $viewRange, 0); // add for previous period
$nextEnd = Navigation::endOfPeriod($nextStart, $viewRange);
}
$nextDate = Navigation::addPeriod($start, $viewRange, 0);
$index = $nextDate->formatLocalized($format);
$nextStart = Navigation::startOfPeriod($nextDate, $viewRange);
$nextEnd = Navigation::endOfPeriod($nextStart, $viewRange);
$ranges[$index] = [$nextStart, $nextEnd];
$ranges = [];
$ranges['current'] = [$start->format('Y-m-d'), $end->format('Y-m-d')];
$ranges['previous'] = [$prevStart->format('Y-m-d'), $prevEnd->format('Y-m-d')];
$ranges['next'] = [$nextStart->format('Y-m-d'), $nextEnd->format('Y-m-d')];
// everything
$index = strval(trans('firefly.everything'));
$ranges[$index] = [$first, new Carbon];
$return = [
'title' => $title,
'configuration' => [
'apply' => strval(trans('firefly.apply')),
'cancel' => strval(trans('firefly.cancel')),
'from' => strval(trans('firefly.from')),
'to' => strval(trans('firefly.to')),
'customRange' => strval(trans('firefly.customRange')),
'start' => $start->format('Y-m-d'),
'end' => $end->format('Y-m-d'),
'ranges' => $ranges,
],
];
return $return;
}
private function getFormatByRange(string $viewRange): string
{
switch ($viewRange) {
default:
throw new FireflyException('The date picker does not yet support "' . $viewRange . '".'); // @codeCoverageIgnore
throw new FireflyException(sprintf('The date picker does not yet support "%s".', $viewRange)); // @codeCoverageIgnore
case '1D':
case 'custom':
$format = (string)trans('config.month_and_day');
@@ -174,18 +204,6 @@ class JavascriptController extends Controller
break;
}
$current = $start->formatLocalized($format);
$next = $nextStart->formatLocalized($format);
$prev = $prevStart->formatLocalized($format);
return [
'start' => $start->format('Y-m-d'),
'end' => $end->format('Y-m-d'),
'current' => $current,
'previous' => $prev,
'next' => $next,
'ranges' => $ranges,
];
return $format;
}
}

View File

@@ -0,0 +1,171 @@
<?php
/**
* AutoCompleteController.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Json;
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Response;
/**
* Class AutoCompleteController
*
* @package FireflyIII\Http\Controllers\Json
*/
class AutoCompleteController extends Controller
{
/**
* Returns a JSON list of all accounts.
*
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*
*/
public function allAccounts(AccountRepositoryInterface $repository)
{
$return = array_unique(
$repository->getAccountsByType(
[AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET]
)->pluck('name')->toArray()
);
sort($return);
return Response::json($return);
}
/**
* @param JournalCollectorInterface $collector
*
* @return \Illuminate\Http\JsonResponse
*/
public function allTransactionJournals(JournalCollectorInterface $collector)
{
$collector->setLimit(250)->setPage(1);
$return = array_unique($collector->getJournals()->pluck('description')->toArray());
sort($return);
return Response::json($return);
}
/**
* Returns a JSON list of all beneficiaries.
*
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*
*/
public function expenseAccounts(AccountRepositoryInterface $repository)
{
$set = $repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY]);
$filtered = $set->filter(
function (Account $account) {
if ($account->active) {
return $account;
}
return false;
}
);
$return = array_unique($filtered->pluck('name')->toArray());
sort($return);
return Response::json($return);
}
/**
* @param JournalCollectorInterface $collector
*
* @param TransactionJournal $except
*
* @return \Illuminate\Http\JsonResponse|mixed
*/
public function journalsWithId(JournalCollectorInterface $collector, TransactionJournal $except)
{
$cache = new CacheProperties;
$cache->addProperty('recent-journals-id');
if ($cache->has()) {
return $cache->get(); // @codeCoverageIgnore
}
$collector->setLimit(400)->setPage(1);
$set = $collector->getJournals()->pluck('description', 'journal_id')->toArray();
$return = [];
foreach ($set as $id => $description) {
$id = intval($id);
if ($id !== $except->id) {
$return[] = [
'id' => $id,
'name' => $id . ': ' . $description,
];
}
}
$cache->store($return);
return Response::json($return);
}
/**
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*
*/
public function revenueAccounts(AccountRepositoryInterface $repository)
{
$set = $repository->getAccountsByType([AccountType::REVENUE]);
$filtered = $set->filter(
function (Account $account) {
if ($account->active) {
return $account;
}
return false;
}
);
$return = array_unique($filtered->pluck('name')->toArray());
sort($return);
return Response::json($return);
}
/**
* @param JournalCollectorInterface $collector
* @param string $what
*
* @return \Illuminate\Http\JsonResponse
*/
public function transactionJournals(JournalCollectorInterface $collector, string $what)
{
$type = config('firefly.transactionTypesByWhat.' . $what);
$types = [$type];
$collector->setTypes($types)->setLimit(250)->setPage(1);
$return = array_unique($collector->getJournals()->pluck('description')->toArray());
sort($return);
return Response::json($return);
}
}

View File

@@ -0,0 +1,193 @@
<?php
/**
* BoxController.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Json;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Response;
/**
* Class BoxController
*
* @package FireflyIII\Http\Controllers\Json
*/
class BoxController extends Controller
{
/**
* @param BudgetRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*/
public function available(BudgetRepositoryInterface $repository)
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
$today = new Carbon;
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty($today);
$cache->addProperty('box-available');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
// get available amount
$currency = app('amount')->getDefaultCurrency();
$available = $repository->getAvailableBudget($currency, $start, $end);
// get spent amount:
$budgets = $repository->getActiveBudgets();
$budgetInformation = $repository->collectBudgetInformation($budgets, $start, $end);
$spent = strval(array_sum(array_column($budgetInformation, 'spent')));
$left = bcadd($available, $spent);
// left less than zero? then it's zero:
if (bccomp($left, '0') === -1) {
$left = '0';
}
$days = $today->diffInDays($end) + 1;
$perDay = '0';
if ($days !== 0) {
$perDay = bcdiv($left, strval($days));
}
$return = [
'perDay' => app('amount')->formatAnything($currency, $perDay, false),
'left' => app('amount')->formatAnything($currency, $left, false),
];
$cache->store($return);
return Response::json($return);
}
/**
* @return \Illuminate\Http\JsonResponse
*/
public function balance()
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('box-balance');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
// try a collector for income:
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)
->setTypes([TransactionType::DEPOSIT])
->withOpposingAccount();
$income = strval($collector->getJournals()->sum('transaction_amount'));
$currency = app('amount')->getDefaultCurrency();
// expense:
// try a collector for expenses:
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)
->setTypes([TransactionType::WITHDRAWAL])
->withOpposingAccount();
$expense = strval($collector->getJournals()->sum('transaction_amount'));
$response = [
'income' => app('amount')->formatAnything($currency, $income, false),
'expense' => app('amount')->formatAnything($currency, $expense, false),
'combined' => app('amount')->formatAnything($currency, bcadd($income, $expense), false),
];
$cache->store($response);
return Response::json($response);
}
/**
* @param BillRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*/
public function bills(BillRepositoryInterface $repository)
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('box-bills');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
/*
* Since both this method and the chart use the exact same data, we can suffice
* with calling the one method in the bill repository that will get this amount.
*/
$paidAmount = bcmul($repository->getBillsPaidInRange($start, $end), '-1');
$unpaidAmount = $repository->getBillsUnpaidInRange($start, $end); // will be a positive amount.
$currency = app('amount')->getDefaultCurrency();
$return = [
'paid' => app('amount')->formatAnything($currency, $paidAmount, false),
'unpaid' => app('amount')->formatAnything($currency, $unpaidAmount, false),
];
$cache->store($return);
return Response::json($return);
}
/**
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*/
public function netWorth(AccountRepositoryInterface $repository)
{
$today = new Carbon(date('Y-m-d')); // needed so its per day.
$cache = new CacheProperties;
$cache->addProperty($today);
$cache->addProperty('box-net-worth');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$currency = app('amount')->getDefaultCurrency();
$balances = app('steam')->balancesByAccounts($accounts, $today);
$sum = '0';
foreach ($balances as $entry) {
$sum = bcadd($sum, $entry);
}
$return = [
'net_worth' => app('amount')->formatAnything($currency, $sum, false),
];
$cache->store($return);
return Response::json($return);
}
}

View File

@@ -163,4 +163,4 @@ class IntroController
return $steps;
}
}
}

View File

@@ -16,9 +16,7 @@ namespace FireflyIII\Http\Controllers;
use Amount;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
@@ -62,151 +60,6 @@ class JsonController extends Controller
return Response::json(['html' => $view]);
}
/**
* Returns a JSON list of all accounts.
*
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*
*/
public function allAccounts(AccountRepositoryInterface $repository)
{
$return = array_unique(
$repository->getAccountsByType(
[AccountType::REVENUE, AccountType::EXPENSE, AccountType::BENEFICIARY, AccountType::DEFAULT, AccountType::ASSET]
)->pluck('name')->toArray()
);
sort($return);
return Response::json($return);
}
/**
* @param JournalCollectorInterface $collector
*
* @return \Illuminate\Http\JsonResponse
*/
public function allTransactionJournals(JournalCollectorInterface $collector)
{
$collector->setLimit(100)->setPage(1);
$return = array_unique($collector->getJournals()->pluck('description')->toArray());
sort($return);
return Response::json($return);
}
/**
* @param BillRepositoryInterface $repository
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function boxBillsPaid(BillRepositoryInterface $repository)
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
/*
* Since both this method and the chart use the exact same data, we can suffice
* with calling the one method in the bill repository that will get this amount.
*/
$amount = $repository->getBillsPaidInRange($start, $end); // will be a negative amount.
$amount = bcmul($amount, '-1');
$currency = Amount::getDefaultCurrency();
$data = ['box' => 'bills-paid', 'amount' => Amount::formatAnything($currency, $amount, false), 'amount_raw' => $amount];
return Response::json($data);
}
/**
* @param BillRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*/
public function boxBillsUnpaid(BillRepositoryInterface $repository)
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
$amount = $repository->getBillsUnpaidInRange($start, $end); // will be a positive amount.
$currency = Amount::getDefaultCurrency();
$data = ['box' => 'bills-unpaid', 'amount' => Amount::formatAnything($currency, $amount, false), 'amount_raw' => $amount];
return Response::json($data);
}
/**
* @return \Illuminate\Http\JsonResponse
* @internal param AccountTaskerInterface $accountTasker
* @internal param AccountRepositoryInterface $repository
*
*/
public function boxIn()
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
// works for json too!
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('box-in');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
// try a collector for income:
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)
->setTypes([TransactionType::DEPOSIT])
->withOpposingAccount();
$amount = strval($collector->getJournals()->sum('transaction_amount'));
$currency = Amount::getDefaultCurrency();
$data = ['box' => 'in', 'amount' => Amount::formatAnything($currency, $amount, false), 'amount_raw' => $amount];
$cache->store($data);
return Response::json($data);
}
/**
* @return \Symfony\Component\HttpFoundation\Response
* @internal param AccountTaskerInterface $accountTasker
* @internal param AccountRepositoryInterface $repository
*
*/
public function boxOut()
{
$start = session('start', Carbon::now()->startOfMonth());
$end = session('end', Carbon::now()->endOfMonth());
// works for json too!
$cache = new CacheProperties;
$cache->addProperty($start);
$cache->addProperty($end);
$cache->addProperty('box-out');
if ($cache->has()) {
return Response::json($cache->get()); // @codeCoverageIgnore
}
// try a collector for expenses:
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)
->setTypes([TransactionType::WITHDRAWAL])
->withOpposingAccount();
$amount = strval($collector->getJournals()->sum('transaction_amount'));
$currency = Amount::getDefaultCurrency();
$data = ['box' => 'out', 'amount' => Amount::formatAnything($currency, $amount, false), 'amount_raw' => $amount];
$cache->store($data);
return Response::json($data);
}
/**
* @param BudgetRepositoryInterface $repository
*
@@ -235,36 +88,6 @@ class JsonController extends Controller
return Response::json($return);
}
/**
* Returns a JSON list of all beneficiaries.
*
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*
*/
public function expenseAccounts(AccountRepositoryInterface $repository)
{
$return = array_unique($repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY])->pluck('name')->toArray());
sort($return);
return Response::json($return);
}
/**
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\JsonResponse
*
*/
public function revenueAccounts(AccountRepositoryInterface $repository)
{
$return = array_unique($repository->getAccountsByType([AccountType::REVENUE])->pluck('name')->toArray());
sort($return);
return Response::json($return);
}
/**
* Returns a JSON list of all beneficiaries.
*
@@ -281,26 +104,6 @@ class JsonController extends Controller
}
/**
* @param JournalCollectorInterface $collector
* @param string $what
*
* @return \Illuminate\Http\JsonResponse
*/
public function transactionJournals(JournalCollectorInterface $collector, string $what)
{
$type = config('firefly.transactionTypesByWhat.' . $what);
$types = [$type];
$collector->setTypes($types)->setLimit(100)->setPage(1);
$return = array_unique($collector->getJournals()->pluck('description')->toArray());
sort($return);
return Response::json($return);
}
/**
* @param JournalRepositoryInterface $repository
*
@@ -329,6 +132,7 @@ class JsonController extends Controller
$triggers[$key] = trans('firefly.rule_trigger_' . $key . '_choice');
}
}
asort($triggers);
$view = view('rules.partials.trigger', compact('triggers', 'count'))->render();

View File

@@ -85,27 +85,27 @@ class PreferencesController extends Controller
*/
public function index(AccountRepositoryInterface $repository)
{
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$viewRangePref = Preferences::get('viewRange', '1M');
$viewRange = $viewRangePref->data;
$frontPageAccounts = Preferences::get('frontPageAccounts', []);
$language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data;
$transactionPageSize = Preferences::get('transactionPageSize', 50)->data;
$customFiscalYear = Preferences::get('customFiscalYear', 0)->data;
$showDepositsFrontpage = Preferences::get('showDepositsFrontpage', false)->data;
$fiscalYearStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
$fiscalYearStart = date('Y') . '-' . $fiscalYearStartStr;
$tjOptionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
$is2faEnabled = Preferences::get('twoFactorAuthEnabled', 0)->data; // twoFactorAuthEnabled
$has2faSecret = !is_null(Preferences::get('twoFactorAuthSecret')); // hasTwoFactorAuthSecret
$showIncomplete = env('SHOW_INCOMPLETE_TRANSLATIONS', false) === true;
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$viewRangePref = Preferences::get('viewRange', '1M');
$viewRange = $viewRangePref->data;
$frontPageAccounts = Preferences::get('frontPageAccounts', []);
$language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data;
$transactionPageSize = Preferences::get('transactionPageSize', 50)->data;
$customFiscalYear = Preferences::get('customFiscalYear', 0)->data;
$showDeps = Preferences::get('showDepositsFrontpage', false)->data;
$fiscalYearStartStr = Preferences::get('fiscalYearStart', '01-01')->data;
$fiscalYearStart = date('Y') . '-' . $fiscalYearStartStr;
$tjOptionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
$is2faEnabled = Preferences::get('twoFactorAuthEnabled', 0)->data; // twoFactorAuthEnabled
$has2faSecret = !is_null(Preferences::get('twoFactorAuthSecret')); // hasTwoFactorAuthSecret
$showIncomplete = env('SHOW_INCOMPLETE_TRANSLATIONS', false) === true;
return view(
'preferences.index',
compact(
'language', 'accounts', 'frontPageAccounts', 'tjOptionalFields',
'viewRange', 'customFiscalYear', 'transactionPageSize', 'fiscalYearStart', 'is2faEnabled',
'has2faSecret', 'showIncomplete', 'showDepositsFrontpage'
'has2faSecret', 'showIncomplete', 'showDeps'
)
);
}

View File

@@ -13,14 +13,20 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Auth;
use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Exceptions\ValidationException;
use FireflyIII\Http\Middleware\IsLimitedUser;
use FireflyIII\Http\Requests\DeleteAccountFormRequest;
use FireflyIII\Http\Requests\EmailFormRequest;
use FireflyIII\Http\Requests\ProfileFormRequest;
use FireflyIII\Models\Preference;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Hash;
use Log;
use Preferences;
use Session;
use View;
@@ -47,10 +53,23 @@ class ProfileController extends Controller
return $next($request);
}
);
$this->middleware(IsLimitedUser::class);
$this->middleware(IsLimitedUser::class)->except(['confirmEmailChange', 'undoEmailChange']);
}
/**
* @return View
*/
public function changeEmail()
{
$title = auth()->user()->email;
$email = auth()->user()->email;
$subTitle = strval(trans('firefly.change_your_email'));
$subTitleIcon = 'fa-envelope';
return view('profile.change-email', compact('title', 'subTitle', 'subTitleIcon', 'email'));
}
/**
* @return View
*/
@@ -63,6 +82,37 @@ class ProfileController extends Controller
return view('profile.change-password', compact('title', 'subTitle', 'subTitleIcon'));
}
/**
* @param string $token
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
* @throws FireflyException
*/
public function confirmEmailChange(string $token)
{
// find preference with this token value.
$set = Preferences::findByName('email_change_confirm_token');
$user = null;
/** @var Preference $preference */
foreach ($set as $preference) {
if ($preference->data === $token) {
$user = $preference->user;
}
}
// update user to clear blocked and blocked_code.
if (is_null($user)) {
throw new FireflyException('Invalid token.');
}
$user->blocked = 0;
$user->blocked_code = '';
$user->save();
// return to login.
Session::flash('success', strval(trans('firefly.login_with_new_email')));
return redirect(route('login'));
}
/**
* @return View
*/
@@ -84,7 +134,57 @@ class ProfileController extends Controller
$subTitle = auth()->user()->email;
$userId = auth()->user()->id;
return view('profile.index', compact('subTitle', 'userId'));
// get access token or create one.
$accessToken = Preferences::get('access_token', null);
if (is_null($accessToken)) {
$token = auth()->user()->generateAccessToken();
$accessToken = Preferences::set('access_token', $token);
}
return view('profile.index', compact('subTitle', 'userId', 'accessToken'));
}
/**
* @param EmailFormRequest $request
* @param UserRepositoryInterface $repository
*
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function postChangeEmail(EmailFormRequest $request, UserRepositoryInterface $repository)
{
/** @var User $user */
$user = auth()->user();
$newEmail = $request->string('email');
$oldEmail = $user->email;
if ($newEmail === $user->email) {
Session::flash('error', strval(trans('firefly.email_not_changed')));
return redirect(route('profile.change-email'))->withInput();
}
$existing = $repository->findByEmail($newEmail);
if (!is_null($existing)) {
// force user logout.
$this->guard()->logout();
$request->session()->invalidate();
Session::flash('success', strval(trans('firefly.email_changed')));
return redirect(route('index'));
}
// now actually update user:
$repository->changeEmail($user, $newEmail);
// call event.
$ipAddress = $request->ip();
event(new UserChangedEmail($user, $newEmail, $oldEmail, $ipAddress));
// force user logout.
Auth::guard()->logout();
$request->session()->invalidate();
Session::flash('success', strval(trans('firefly.email_changed')));
return redirect(route('index'));
}
/**
@@ -140,6 +240,64 @@ class ProfileController extends Controller
return redirect(route('index'));
}
/**
*
*/
function regenerate()
{
$token = auth()->user()->generateAccessToken();
Preferences::set('access_token', $token);
Session::flash('success', strval(trans('firefly.token_regenerated')));
return redirect(route('profile.index'));
}
/**
* @param string $token
* @param string $hash
*
* @throws FireflyException
*/
public function undoEmailChange(string $token, string $hash)
{
// find preference with this token value.
$set = Preferences::findByName('email_change_undo_token');
$user = null;
/** @var Preference $preference */
foreach ($set as $preference) {
if ($preference->data === $token) {
$user = $preference->user;
}
}
if (is_null($user)) {
throw new FireflyException('Invalid token.');
}
// found user.
// which email address to return to?
$set = Preferences::beginsWith($user, 'previous_email_');
$match = null;
foreach ($set as $entry) {
$hashed = hash('sha256', $entry->data);
if ($hashed === $hash) {
$match = $entry->data;
break;
}
}
if (is_null($match)) {
throw new FireflyException('Invalid token.');
}
// change user back
$user->email = $match;
$user->blocked = 0;
$user->blocked_code = '';
$user->save();
// return to login.
Session::flash('success', strval(trans('firefly.login_with_old_email')));
return redirect(route('login'));
}
/**
* @param User $user

View File

@@ -27,7 +27,7 @@ use FireflyIII\Models\RuleTrigger;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Rules\TransactionMatcher;
use FireflyIII\TransactionRules\TransactionMatcher;
use Illuminate\Http\Request;
use Preferences;
use Response;
@@ -166,10 +166,13 @@ class RuleController extends Controller
*/
public function edit(Request $request, RuleRepositoryInterface $repository, Rule $rule)
{
$oldTriggers = $this->getCurrentTriggers($rule);
$triggerCount = count($oldTriggers);
$oldActions = $this->getCurrentActions($rule);
$actionCount = count($oldActions);
/** @var RuleGroupRepositoryInterface $ruleGroupRepository */
$ruleGroupRepository = app(RuleGroupRepositoryInterface::class);
$oldTriggers = $this->getCurrentTriggers($rule);
$triggerCount = count($oldTriggers);
$oldActions = $this->getCurrentActions($rule);
$actionCount = count($oldActions);
$ruleGroups = ExpandedForm::makeSelectList($ruleGroupRepository->get());
// has old input?
if ($request->old()) {
@@ -191,7 +194,12 @@ class RuleController extends Controller
Session::flash('gaEventCategory', 'rules');
Session::flash('gaEventAction', 'edit-rule');
return view('rules.rule.edit', compact('rule', 'subTitle', 'primaryTrigger', 'oldTriggers', 'oldActions', 'triggerCount', 'actionCount'));
return view(
'rules.rule.edit', compact(
'rule', 'subTitle',
'primaryTrigger', 'oldTriggers', 'oldActions', 'triggerCount', 'actionCount', 'ruleGroups'
)
);
}
/**
@@ -523,7 +531,7 @@ class RuleController extends Controller
$actions[] = view(
'rules.partials.action',
[
'oldTrigger' => $entry->action_type,
'oldAction' => $entry->action_type,
'oldValue' => $entry->action_value,
'oldChecked' => $entry->stop_processing,
'count' => $count,

View File

@@ -51,7 +51,7 @@ class SearchController extends Controller
*/
public function index(Request $request, SearchInterface $searcher)
{
$fullQuery = $request->get('q');
$fullQuery = strval($request->get('q'));
// parse search terms:
$searcher->parseQuery($fullQuery);

View File

@@ -22,7 +22,6 @@ use FireflyIII\Repositories\Tag\TagRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Log;
use Navigation;
use Preferences;
use Session;
@@ -44,9 +43,6 @@ use View;
class TagController extends Controller
{
/** @var array */
public $tagOptions = [];
/** @var TagRepositoryInterface */
protected $repository;
@@ -57,21 +53,13 @@ class TagController extends Controller
{
parent::__construct();
View::share('hideTags', true);
$this->redirectUri = route('tags.index');
$this->middleware(
function ($request, $next) {
$this->repository = app(TagRepositoryInterface::class);
$this->tagOptions = [
'nothing' => trans('firefly.regular_tag'),
'balancingAct' => trans('firefly.balancing_act'),
'advancePayment' => trans('firefly.advance_payment'),
];
View::share('title', strval(trans('firefly.tags')));
View::share('mainTitleIcon', 'fa-tags');
View::share('tagOptions', $this->tagOptions);
return $next($request);
}
@@ -79,22 +67,16 @@ class TagController extends Controller
}
/**
* @param Request $request
* Create a new tag.
*
* @return View
*/
public function create(Request $request)
public function create()
{
$subTitle = trans('firefly.new_tag');
$subTitleIcon = 'fa-tag';
$apiKey = env('GOOGLE_MAPS_API_KEY', '');
$preFilled = [
'tagMode' => 'nothing',
];
if (!$request->old('tagMode')) {
Session::flash('preFilled', $preFilled);
}
// put previous url in session if not redirect from store (not "create another").
if (session('tags.create.fromStore') !== true) {
$this->rememberPreviousUri('tags.create.uri');
@@ -107,6 +89,8 @@ class TagController extends Controller
}
/**
* Delete a tag
*
* @param Tag $tag
*
* @return View
@@ -141,38 +125,18 @@ class TagController extends Controller
}
/**
* @param Tag $tag
* Edit a tag
*
* @param TagRepositoryInterface $repository
* @param Tag $tag
*
* @return View
*/
public function edit(Tag $tag, TagRepositoryInterface $repository)
public function edit(Tag $tag)
{
$subTitle = trans('firefly.edit_tag', ['tag' => $tag->tag]);
$subTitleIcon = 'fa-tag';
$apiKey = env('GOOGLE_MAPS_API_KEY', '');
/*
* Default tag options (again)
*/
$tagOptions = $this->tagOptions;
/*
* Can this tag become another type?
*/
$allowAdvance = $repository->tagAllowAdvance($tag);
$allowToBalancingAct = $repository->tagAllowBalancing($tag);
// edit tag options:
if ($allowAdvance === false) {
unset($tagOptions['advancePayment']);
}
if ($allowToBalancingAct === false) {
unset($tagOptions['balancingAct']);
}
// put previous url in session if not redirect from store (not "return_to_edit").
if (session('tags.edit.fromUpdate') !== true) {
$this->rememberPreviousUri('tags.edit.uri');
@@ -181,46 +145,34 @@ class TagController extends Controller
Session::flash('gaEventCategory', 'tags');
Session::flash('gaEventAction', 'edit');
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'tagOptions', 'apiKey'));
return view('tags.edit', compact('tag', 'subTitle', 'subTitleIcon', 'apiKey'));
}
/**
* View all tags
*
* @param TagRepositoryInterface $repository
*
* @return View
*/
public function index(TagRepositoryInterface $repository)
{
$title = 'Tags';
$mainTitleIcon = 'fa-tags';
$types = ['nothing', 'balancingAct', 'advancePayment'];
$count = $repository->count();
// loop each types and get the tags, group them by year.
$collection = [];
foreach ($types as $type) {
// collect tags by year:
/** @var Carbon $start */
$start = clone(session('first'));
$now = new Carbon;
$clouds = [];
$clouds['no-date'] = $repository->tagCloud(null);
while ($now > $start) {
$year = $now->year;
$clouds[$year] = $repository->tagCloud($year);
/** @var Collection $tags */
$tags = $repository->getByType($type);
$tags = $tags->sortBy(
function (Tag $tag) {
$date = !is_null($tag->date) ? $tag->date->format('Ymd') : '000000';
return strtolower($date . $tag->tag);
}
);
/** @var Tag $tag */
foreach ($tags as $tag) {
$year = is_null($tag->date) ? trans('firefly.no_year') : $tag->date->year;
$monthFormatted = is_null($tag->date) ? trans('firefly.no_month') : $tag->date->formatLocalized($this->monthFormat);
$collection[$type][$year][$monthFormatted][] = $tag;
}
$now->subYear();
}
$count = $repository->count();
return view('tags.index', compact('title', 'mainTitleIcon', 'types', 'collection', 'count'));
return view('tags.index', compact('clouds', 'count'));
}
/**
@@ -236,26 +188,21 @@ class TagController extends Controller
// default values:
$subTitle = $tag->tag;
$subTitleIcon = 'fa-tag';
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$count = 0;
$loop = 0;
$range = Preferences::get('viewRange', '1M')->data;
$start = null;
$end = null;
$periods = new Collection;
$apiKey = env('GOOGLE_MAPS_API_KEY', '');
$sum = '0';
$path = 'tags/show/' . $tag->id;
$path = route('tags.show', [$tag->id]);
// prep for "all" view.
if ($moment === 'all') {
$subTitle = trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]);
$start = $repository->firstUseDate($tag);
$end = new Carbon;
$sum = $repository->sumOfTag($tag);
$path = 'tags/show/' . $tag->id . '/all';
$path = route('tags.show', [$tag->id, 'all']);
}
// prep for "specific date" view.
@@ -268,12 +215,14 @@ class TagController extends Controller
'start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
$periods = $this->getPeriodOverview($tag);
$sum = $repository->sumOfTag($tag, $start, $end);
$path = route('tags.show', [$tag->id, $moment]);
}
// prep for current period
if (strlen($moment) === 0) {
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
/** @var Carbon $start */
$start = clone session('start', Navigation::startOfPeriod(new Carbon, $range));
/** @var Carbon $end */
$end = clone session('end', Navigation::endOfPeriod(new Carbon, $range));
$periods = $this->getPeriodOverview($tag);
$subTitle = trans(
@@ -281,37 +230,19 @@ class TagController extends Controller
['tag' => $tag->tag, 'start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
// grab journals, but be prepared to jump a period back to get the right ones:
Log::info('Now at tag loop start.');
while ($count === 0 && $loop < 3) {
$loop++;
Log::info(sprintf('Count is zero, search for journals between %s and %s (pagesize %d, page %d).', $start, $end, $pageSize, $page));
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withOpposingAccount()
->setTag($tag)->withBudgetInformation()->withCategoryInformation()->removeFilter(InternalTransferFilter::class);
$journals = $collector->getPaginatedJournals();
$journals->setPath($path);
$count = $journals->getCollection()->count();
if ($count === 0 && $loop < 3) {
$start->subDay();
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfPeriod($start, $range);
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
}
}
if ($moment !== 'all' && $loop > 1) {
$subTitle = trans(
'firefly.journals_in_period_for_tag',
['tag' => $tag->tag, 'start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setLimit($pageSize)->setPage($page)->withOpposingAccount()
->setTag($tag)->withBudgetInformation()->withCategoryInformation()->removeFilter(InternalTransferFilter::class);
$journals = $collector->getPaginatedJournals();
$journals->setPath($path);
return view('tags.show', compact('apiKey', 'tag', 'periods', 'subTitle', 'subTitleIcon', 'journals', 'sum', 'start', 'end', 'moment'));
$sums = $repository->sumsOfTag($tag, $start, $end);
return view('tags.show', compact('apiKey', 'tag', 'sums', 'periods', 'subTitle', 'subTitleIcon', 'journals', 'start', 'end', 'moment'));
}
/**
* @param TagFormRequest $request
*
@@ -408,4 +339,6 @@ class TagController extends Controller
return $collection;
}
}

View File

@@ -85,7 +85,7 @@ class ConvertController extends Controller
// cannot convert split.
if ($journal->transactions()->count() > 2) {
Session::flash('error', trans('firefly.cannot_convert_split_journl'));
Session::flash('error', trans('firefly.cannot_convert_split_journal'));
return redirect(route('transactions.show', [$journal->id]));
}
@@ -134,7 +134,7 @@ class ConvertController extends Controller
}
if ($journal->transactions()->count() > 2) {
Session::flash('error', trans('firefly.cannot_convert_split_journl'));
Session::flash('error', trans('firefly.cannot_convert_split_journal'));
return redirect(route('transactions.show', [$journal->id]));
}
@@ -185,7 +185,7 @@ class ConvertController extends Controller
case TransactionType::DEPOSIT . '-' . TransactionType::WITHDRAWAL:
case TransactionType::TRANSFER . '-' . TransactionType::WITHDRAWAL:
// three and five
if ($data['destination_account_expense'] === '') {
if ($data['destination_account_expense'] === '' || is_null($data['destination_account_expense'])) {
// destination is a cash account.
$destination = $accountRepository->getCashAccount();
@@ -232,7 +232,7 @@ class ConvertController extends Controller
case TransactionType::WITHDRAWAL . '-' . TransactionType::DEPOSIT:
case TransactionType::TRANSFER . '-' . TransactionType::DEPOSIT:
if ($data['source_account_revenue'] === '') {
if ($data['source_account_revenue'] === '' || is_null($data['source_account_revenue'])) {
// destination is a cash account.
$destination = $accountRepository->getCashAccount();

View File

@@ -0,0 +1,148 @@
<?php
/**
* LinkController.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Transaction;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\JournalLinkRequest;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Models\TransactionJournalLink;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use Log;
use Preferences;
use Session;
use URL;
use View;
/**
* Class LinkController
*
* @package FireflyIII\Http\Controllers\Transaction
*/
class LinkController extends Controller
{
/**
*
*/
public function __construct()
{
parent::__construct();
// some useful repositories:
$this->middleware(
function ($request, $next) {
View::share('title', trans('firefly.transactions'));
View::share('mainTitleIcon', 'fa-repeat');
return $next($request);
}
);
}
/**
* @param TransactionJournalLink $link
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function delete(TransactionJournalLink $link)
{
$subTitleIcon = 'fa-link';
$subTitle = trans('breadcrumbs.delete_journal_link');
$this->rememberPreviousUri('journal_links.delete.uri');
return view('transactions.links.delete', compact('link', 'subTitle', 'subTitleIcon'));
}
/**
* @param LinkTypeRepositoryInterface $repository
* @param TransactionJournalLink $link
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function destroy(LinkTypeRepositoryInterface $repository, TransactionJournalLink $link)
{
$repository->destroyLink($link);
Session::flash('success', strval(trans('firefly.deleted_link')));
Preferences::mark();
return redirect(strval(session('journal_links.delete.uri')));
}
/**
* @param JournalLinkRequest $request
* @param LinkTypeRepositoryInterface $repository
* @param JournalRepositoryInterface $journalRepository
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function store(
JournalLinkRequest $request, LinkTypeRepositoryInterface $repository, JournalRepositoryInterface $journalRepository, TransactionJournal $journal
) {
$linkInfo = $request->getLinkInfo();
if ($linkInfo['transaction_journal_id'] === 0) {
Session::flash('error', trans('firefly.invalid_link_selection'));
return redirect(route('transactions.show', [$journal->id]));
}
$linkType = $repository->find($linkInfo['link_type_id']);
$other = $journalRepository->find($linkInfo['transaction_journal_id']);
$alreadyLinked = $repository->findLink($journal, $other);
if ($alreadyLinked) {
Session::flash('error', trans('firefly.journals_error_linked'));
return redirect(route('transactions.show', [$journal->id]));
}
Log::debug(sprintf('Journal is %d, opposing is %d', $journal->id, $other->id));
$journalLink = new TransactionJournalLink;
$journalLink->linkType()->associate($linkType);
if ($linkInfo['direction'] === 'inward') {
Log::debug(sprintf('Link type is inwards ("%s"), so %d is source and %d is destination.', $linkType->inward, $other->id, $journal->id));
$journalLink->source()->associate($other);
$journalLink->destination()->associate($journal);
}
if ($linkInfo['direction'] === 'outward') {
Log::debug(sprintf('Link type is inwards ("%s"), so %d is source and %d is destination.', $linkType->outward, $journal->id, $other->id));
$journalLink->source()->associate($journal);
$journalLink->destination()->associate($other);
}
$journalLink->comment = $linkInfo['comments'];
$journalLink->save();
Session::flash('success', trans('firefly.journals_linked'));
return redirect(route('transactions.show', [$journal->id]));
}
/**
* @param LinkTypeRepositoryInterface $repository
* @param TransactionJournalLink $link
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function switch(LinkTypeRepositoryInterface $repository, TransactionJournalLink $link)
{
$repository->switchLink($link);
return redirect(URL::previous());
}
}

View File

@@ -86,7 +86,7 @@ class MassController extends Controller
foreach ($ids as $journalId) {
/** @var TransactionJournal $journal */
$journal = $repository->find(intval($journalId));
if (!is_null($journal->id) && $journalId === $journal->id) {
if (!is_null($journal->id) && intval($journalId) === $journal->id) {
$set->push($journal);
}
}
@@ -131,10 +131,9 @@ class MassController extends Controller
$filtered = new Collection;
$messages = [];
/**
* @var int $index
* @var TransactionJournal $journal
*/
foreach ($journals as $index => $journal) {
foreach ($journals as $journal) {
$sources = $journal->sourceAccountList();
$destinations = $journal->destinationAccountList();
if ($sources->count() > 1) {

View File

@@ -14,12 +14,14 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Transaction;
use Carbon\Carbon;
use ExpandedForm;
use FireflyIII\Events\StoredTransactionJournal;
use FireflyIII\Events\UpdatedTransactionJournal;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\JournalFormRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
@@ -115,7 +117,7 @@ class SingleController extends Controller
'foreign_amount' => $foreignAmount,
'native_amount' => $foreignAmount,
'amount_currency_id_amount' => $transaction->foreign_currency_id ?? 0,
'date' => $journal->date->format('Y-m-d'),
'date' => (new Carbon())->format('Y-m-d'),
'budget_id' => $budgetId,
'category' => $categoryName,
'tags' => $tags,
@@ -142,7 +144,7 @@ class SingleController extends Controller
{
$what = strtolower($what);
$uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size')));
$assetAccounts = ExpandedForm::makeSelectList($this->accounts->getActiveAccountsByType([AccountType::DEFAULT, AccountType::ASSET]));
$assetAccounts = $this->groupedActiveAccountList();
$budgets = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets());
$piggyBanks = $this->piggyBanks->getPiggyBanksWithAmount();
$piggies = ExpandedForm::makeSelectListWithEmpty($piggyBanks);
@@ -199,10 +201,10 @@ class SingleController extends Controller
}
/**
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $transactionJournal
* @param TransactionJournal $transactionJournal
*
* @return \Illuminate\Http\RedirectResponse
* @internal param JournalRepositoryInterface $repository
*/
public function destroy(TransactionJournal $transactionJournal)
{
@@ -238,7 +240,7 @@ class SingleController extends Controller
}
$what = strtolower($journal->transactionTypeStr());
$assetAccounts = ExpandedForm::makeSelectList($this->accounts->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]));
$assetAccounts = $this->groupedAccountList();
$budgetList = ExpandedForm::makeSelectListWithEmpty($this->budgets->getBudgets());
// view related code
@@ -408,6 +410,46 @@ class SingleController extends Controller
return redirect($this->getPreviousUri('transactions.edit.uri'));
}
/**
* @return array
*/
private function groupedAccountList(): array
{
$accounts = $this->accounts->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$return = [];
/** @var Account $account */
foreach ($accounts as $account) {
$type = $account->getMeta('accountRole');
if (strlen($type) === 0) {
$type = 'no_account_type';
}
$key = strval(trans('firefly.opt_group_' . $type));
$return[$key][$account->id] = $account->name;
}
return $return;
}
/**
* @return array
*/
private function groupedActiveAccountList(): array
{
$accounts = $this->accounts->getActiveAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$return = [];
/** @var Account $account */
foreach ($accounts as $account) {
$type = $account->getMeta('accountRole');
if (strlen($type) === 0) {
$type = 'no_account_type';
}
$key = strval(trans('firefly.opt_group_' . $type));
$return[$key][$account->id] = $account->name;
}
return $return;
}
/**
* @param TransactionJournal $journal
*

View File

@@ -18,6 +18,8 @@ use ExpandedForm;
use FireflyIII\Events\UpdatedTransactionJournal;
use FireflyIII\Helpers\Attachments\AttachmentHelperInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SplitJournalFormRequest;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
@@ -94,13 +96,23 @@ class SplitController extends Controller
$uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size')));
$currencies = $this->currencies->get();
$assetAccounts = ExpandedForm::makeSelectList($this->accounts->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]));
$accountList = $this->accounts->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$assetAccounts = ExpandedForm::makeSelectList($accountList);
$optionalFields = Preferences::get('transaction_journal_optional_fields', [])->data;
$budgets = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets());
$preFilled = $this->arrayFromJournal($request, $journal);
$subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]);
$subTitleIcon = 'fa-pencil';
$accountArray = [];
// account array to display currency info:
/** @var Account $account */
foreach ($accountList as $account) {
$accountArray[$account->id] = $account;
$accountArray[$account->id]['currency_id'] = intval($account->getMeta('currency_id'));
}
Session::flash('gaEventCategory', 'transactions');
Session::flash('gaEventAction', 'edit-split-' . $preFilled['what']);
@@ -114,26 +126,25 @@ class SplitController extends Controller
'transactions.split.edit',
compact(
'subTitleIcon', 'currencies', 'optionalFields',
'preFilled', 'subTitle', 'amount', 'sourceAccounts', 'uploadSize', 'destinationAccounts', 'assetAccounts',
'budgets', 'journal'
'preFilled', 'subTitle', 'uploadSize', 'assetAccounts',
'budgets', 'journal', 'accountArray', 'previous'
)
);
}
/**
* @param Request $request
* @param SplitJournalFormRequest $request
* @param JournalRepositoryInterface $repository
* @param TransactionJournal $journal
*
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function update(Request $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
public function update(SplitJournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
{
if ($this->isOpeningBalance($journal)) {
return $this->redirectToAccount($journal);
}
$data = $this->arrayFromInput($request);
$journal = $repository->updateSplitJournal($journal, $data);
/** @var array $files */
@@ -167,12 +178,13 @@ class SplitController extends Controller
}
/**
* @param Request $request
* @param SplitJournalFormRequest $request
*
* @return array
*/
private function arrayFromInput(Request $request): array
private function arrayFromInput(SplitJournalFormRequest $request): array
{
$tags = is_null($request->get('tags')) ? '' : $request->get('tags');
$array = [
'journal_description' => $request->get('journal_description'),
'journal_source_account_id' => $request->get('journal_source_account_id'),
@@ -189,7 +201,7 @@ class SplitController extends Controller
'invoice_date' => $request->get('invoice_date'),
'internal_reference' => $request->get('internal_reference'),
'notes' => $request->get('notes'),
'tags' => explode(',', $request->get('tags')),
'tags' => explode(',', $tags),
// transactions.
'transactions' => $this->getTransactionDataFromRequest($request),
@@ -200,8 +212,8 @@ class SplitController extends Controller
}
/**
* @param Request $request
* @param TransactionJournal $journal
* @param SplitJournalFormRequest|Request $request
* @param TransactionJournal $journal
*
* @return array
*/
@@ -234,6 +246,8 @@ class SplitController extends Controller
// transactions.
'transactions' => $this->getTransactionDataFromJournal($journal),
];
// update transactions array with old request data.
$array['transactions'] = $this->updateWithPrevious($array['transactions'], $request->old());
return $array;
}
@@ -282,11 +296,11 @@ class SplitController extends Controller
}
/**
* @param Request $request
* @param SplitJournalFormRequest|Request $request
*
* @return array
*/
private function getTransactionDataFromRequest(Request $request): array
private function getTransactionDataFromRequest(SplitJournalFormRequest $request): array
{
$return = [];
$transactions = $request->get('transactions');
@@ -312,5 +326,36 @@ class SplitController extends Controller
return $return;
}
/**
* @param $array
* @param $old
*
* @return array
*/
private function updateWithPrevious($array, $old): array
{
if (count($old) === 0 || !isset($old['transactions'])) {
return $array;
}
$old = $old['transactions'];
foreach ($old as $index => $row) {
if (isset($array[$index])) {
$array[$index] = array_merge($array[$index], $row);
continue;
}
// take some info from first transaction, that should at least exist.
$array[$index] = $row;
$array[$index]['transaction_currency_id'] = $array[0]['transaction_currency_id'];
$array[$index]['transaction_currency_code'] = $array[0]['transaction_currency_code'];
$array[$index]['transaction_currency_symbol'] = $array[0]['transaction_currency_symbol'];
$array[$index]['foreign_amount'] = round($array[0]['foreign_destination_amount'] ?? '0', 12);
$array[$index]['foreign_currency_id'] = $array[0]['foreign_currency_id'];
$array[$index]['foreign_currency_code'] = $array[0]['foreign_currency_code'];
$array[$index]['foreign_currency_symbol'] = $array[0]['foreign_currency_symbol'];
}
return $array;
}
}

View File

@@ -17,9 +17,11 @@ use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Helpers\Filter\InternalTransferFilter;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionJournal;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Repositories\Journal\JournalTaskerInterface;
use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
@@ -27,7 +29,6 @@ use Log;
use Navigation;
use Preferences;
use Response;
use Steam;
use View;
/**
@@ -70,15 +71,13 @@ class TransactionController extends Controller
// default values:
$subTitleIcon = config('firefly.transactionIconsByWhat.' . $what);
$types = config('firefly.transactionTypesByWhat.' . $what);
$page = intval($request->get('page')) === 0 ? 1 : intval($request->get('page'));
$page = intval($request->get('page'));
$pageSize = intval(Preferences::get('transactionPageSize', 50)->data);
$count = 0;
$loop = 0;
$range = Preferences::get('viewRange', '1M')->data;
$start = null;
$end = null;
$periods = new Collection;
$path = '/transactions/' . $what;
$path = route('transactions.index', [$what]);
// prep for "all" view.
if ($moment === 'all') {
@@ -86,14 +85,14 @@ class TransactionController extends Controller
$first = $repository->first();
$start = $first->date ?? new Carbon;
$end = new Carbon;
$path = '/transactions/' . $what . '/all/';
$path = route('transactions.index', [$what, 'all']);
}
// prep for "specific date" view.
if (strlen($moment) > 0 && $moment !== 'all') {
$start = new Carbon($moment);
$end = Navigation::endOfPeriod($start, $range);
$path = '/transactions/' . $what . '/' . $moment;
$path = route('transactions.index', [$what, $moment]);
$subTitle = trans(
'firefly.title_' . $what . '_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
@@ -111,32 +110,14 @@ class TransactionController extends Controller
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
// grab journals, but be prepared to jump a period back to get the right ones:
Log::info('Now at transaction loop start.');
while ($count === 0 && $loop < 3) {
$loop++;
Log::info('Count is zero, search for journals.');
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setTypes($types)->setLimit($pageSize)->setPage($page)->withOpposingAccount();
$collector->removeFilter(InternalTransferFilter::class);
$journals = $collector->getPaginatedJournals();
$journals->setPath($path);
$count = $journals->getCollection()->count();
if ($count === 0 && $loop < 3) {
$start->subDay();
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfPeriod($start, $range);
Log::info(sprintf('Count is still zero, go back in time to "%s" and "%s"!', $start->format('Y-m-d'), $end->format('Y-m-d')));
}
}
if ($moment !== 'all' && $loop > 1) {
$subTitle = trans(
'firefly.title_' . $what . '_between',
['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)]
);
}
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($start, $end)->setTypes($types)->setLimit($pageSize)->setPage($page)->withOpposingAccount();
$collector->removeFilter(InternalTransferFilter::class);
$journals = $collector->getPaginatedJournals();
$journals->setPath($path);
return view('transactions.index', compact('subTitle', 'what', 'subTitleIcon', 'journals', 'periods', 'start', 'end', 'moment'));
@@ -170,23 +151,26 @@ class TransactionController extends Controller
}
/**
* @param TransactionJournal $journal
* @param JournalTaskerInterface $tasker
* @param TransactionJournal $journal
* @param JournalTaskerInterface $tasker
*
* @param LinkTypeRepositoryInterface $linkTypeRepository
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
*/
public function show(TransactionJournal $journal, JournalTaskerInterface $tasker)
public function show(TransactionJournal $journal, JournalTaskerInterface $tasker, LinkTypeRepositoryInterface $linkTypeRepository)
{
if ($this->isOpeningBalance($journal)) {
return $this->redirectToAccount($journal);
}
$linkTypes = $linkTypeRepository->get();
$links = $linkTypeRepository->getLinks($journal);
$events = $tasker->getPiggyBankEvents($journal);
$transactions = $tasker->getTransactionsOverview($journal);
$what = strtolower($journal->transaction_type_type ?? $journal->transactionType->type);
$subTitle = trans('firefly.' . $what) . ' "' . e($journal->description) . '"';
return view('transactions.show', compact('journal', 'events', 'subTitle', 'what', 'transactions'));
return view('transactions.show', compact('journal', 'events', 'subTitle', 'what', 'transactions', 'linkTypes', 'links'));
}
@@ -204,7 +188,7 @@ class TransactionController extends Controller
$start = $first->date ?? new Carbon;
$range = Preferences::get('viewRange', '1M')->data;
$start = Navigation::startOfPeriod($start, $range);
$end = Navigation::endOfX(new Carbon, $range);
$end = Navigation::endOfX(new Carbon, $range, null);
$entries = new Collection;
$types = config('firefly.transactionTypesByWhat.' . $what);
@@ -230,35 +214,24 @@ class TransactionController extends Controller
$collector = app(JournalCollectorInterface::class);
$collector->setAllAssetAccounts()->setRange($end, $currentEnd)->withOpposingAccount()->setTypes($types);
$collector->removeFilter(InternalTransferFilter::class);
$set = $collector->getJournals();
$sum = $set->sum('transaction_amount');
$journals = $set->count();
$journals = $collector->getJournals();
$sum = $journals->sum('transaction_amount');
// count per currency:
$sums = $this->sumPerCurrency($journals);
$dateStr = $end->format('Y-m-d');
$dateName = Navigation::periodShow($end, $range);
$array = [
'string' => $dateStr,
'name' => $dateName,
'count' => $journals,
'spent' => 0,
'earned' => 0,
'transferred' => 0,
'date' => clone $end,
'string' => $dateStr,
'name' => $dateName,
'sum' => $sum,
'sums' => $sums,
'date' => clone $end,
];
Log::debug(sprintf('What is %s', $what));
switch ($what) {
case 'withdrawal':
$array['spent'] = $sum;
break;
case 'deposit':
$array['earned'] = $sum;
break;
case 'transfers':
case 'transfer':
$array['transferred'] = Steam::positive($sum);
break;
if ($journals->count() > 0) {
$entries->push($array);
}
$entries->push($array);
$end = Navigation::subtractPeriod($end, $range, 1);
}
Log::debug('End of loop');
@@ -267,4 +240,41 @@ class TransactionController extends Controller
return $entries;
}
/**
* @param Collection $collection
*
* @return array
*/
private function sumPerCurrency(Collection $collection): array
{
$return = [];
/** @var Transaction $transaction */
foreach ($collection as $transaction) {
$currencyId = $transaction->transaction_currency_id;
// save currency information:
if (!isset($return[$currencyId])) {
$currencySymbol = $transaction->transaction_currency_symbol;
$decimalPlaces = $transaction->transaction_currency_dp;
$currencyCode = $transaction->transaction_currency_code;
$return[$currencyId] = [
'currency' => [
'id' => $currencyId,
'code' => $currencyCode,
'symbol' => $currencySymbol,
'dp' => $decimalPlaces,
],
'sum' => '0',
'count' => 0,
];
}
// save amount:
$return[$currencyId]['sum'] = bcadd($return[$currencyId]['sum'], $transaction->transaction_amount);
$return[$currencyId]['count']++;
}
asort($return);
return $return;
}
}

View File

@@ -1,14 +1,15 @@
<?php
declare(strict_types=1);
/**
* Kernel.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http;
@@ -21,42 +22,24 @@ use FireflyIII\Http\Middleware\Range;
use FireflyIII\Http\Middleware\RedirectIfAuthenticated;
use FireflyIII\Http\Middleware\RedirectIfTwoFactorAuthenticated;
use FireflyIII\Http\Middleware\Sandstorm;
use FireflyIII\Http\Middleware\StartFireflySession;
use FireflyIII\Http\Middleware\TrimStrings;
use FireflyIII\Http\Middleware\TrustProxies;
use FireflyIII\Http\Middleware\VerifyCsrfToken;
use Illuminate\Auth\Middleware\AuthenticateWithBasicAuth;
use Illuminate\Auth\Middleware\Authorize;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
use Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode;
use Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull;
use Illuminate\Foundation\Http\Middleware\ValidatePostSize;
use Illuminate\Routing\Middleware\SubstituteBindings;
use Illuminate\Routing\Middleware\ThrottleRequests;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\View\Middleware\ShareErrorsFromSession;
/**
* Class Kernel
*
* @package FireflyIII\Http
*/
class Kernel extends HttpKernel
{
/**
* The bootstrap classes for the application.
*
* Next upgrade verify these are the same.
*
* @var array
*/
protected $bootstrappers
= [
'Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables',
'Illuminate\Foundation\Bootstrap\LoadConfiguration',
'Illuminate\Foundation\Bootstrap\HandleExceptions',
'Illuminate\Foundation\Bootstrap\RegisterFacades',
'Illuminate\Foundation\Bootstrap\RegisterProviders',
'Illuminate\Foundation\Bootstrap\BootProviders',
];
/**
* The application's global HTTP middleware stack.
*
@@ -67,6 +50,10 @@ class Kernel extends HttpKernel
protected $middleware
= [
CheckForMaintenanceMode::class,
ValidatePostSize::class,
TrimStrings::class,
ConvertEmptyStringsToNull::class,
TrustProxies::class,
];
/**
@@ -83,7 +70,7 @@ class Kernel extends HttpKernel
Sandstorm::class,
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartFireflySession::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
@@ -95,7 +82,7 @@ class Kernel extends HttpKernel
Sandstorm::class,
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartFireflySession::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
@@ -108,7 +95,7 @@ class Kernel extends HttpKernel
Sandstorm::class,
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartFireflySession::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
@@ -123,7 +110,7 @@ class Kernel extends HttpKernel
Sandstorm::class,
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartFireflySession::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
@@ -138,7 +125,7 @@ class Kernel extends HttpKernel
Sandstorm::class,
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartFireflySession::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
@@ -156,7 +143,7 @@ class Kernel extends HttpKernel
Sandstorm::class,
EncryptCookies::class,
AddQueuedCookiesToResponse::class,
StartFireflySession::class,
StartSession::class,
ShareErrorsFromSession::class,
VerifyCsrfToken::class,
SubstituteBindings::class,
@@ -174,6 +161,7 @@ class Kernel extends HttpKernel
],
];
/**
* The application's route middleware.
*
@@ -189,6 +177,5 @@ class Kernel extends HttpKernel
'can' => Authorize::class,
'guest' => RedirectIfAuthenticated::class,
'throttle' => ThrottleRequests::class,
'range' => Range::class,
];
}

View File

@@ -44,8 +44,13 @@ class Authenticate
return redirect()->guest('login');
}
if (intval(auth()->user()->blocked) === 1) {
$message = strval(trans('firefly.block_account_logout'));
if (auth()->user()->blocked_code === 'email_changed') {
$message = strval(trans('firefly.email_changed_logout'));
}
Session::flash('logoutMessage', $message);
Auth::guard($guard)->logout();
Session::flash('logoutMessage', trans('firefly.block_account_logout'));
return redirect()->guest('login');
}

View File

@@ -1,25 +1,21 @@
<?php
declare(strict_types=1);
/**
* EncryptCookies.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Middleware;
use Illuminate\Cookie\Middleware\EncryptCookies as BaseEncrypter;
use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;
/**
* Class EncryptCookies
*
* @package FireflyIII\Http\Middleware
*/
class EncryptCookies extends BaseEncrypter
class EncryptCookies extends Middleware
{
/**
* The names of the cookies that should not be encrypted.

View File

@@ -98,7 +98,12 @@ class Range
$locale = array_map('trim', $locale);
setlocale(LC_TIME, $locale);
setlocale(LC_MONETARY, $locale);
$moneyResult = setlocale(LC_MONETARY, $locale);
// send error to view if could not set money format
if ($moneyResult === false) {
View::share('invalidMonetaryLocale', true);
}
// save some formats:

View File

@@ -1,25 +1,21 @@
<?php
declare(strict_types=1);
/**
* RedirectIfAuthenticated.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
/**
* Class RedirectIfAuthenticated
*
* @package FireflyIII\Http\Middleware
*/
class RedirectIfAuthenticated
{
/**
@@ -34,7 +30,7 @@ class RedirectIfAuthenticated
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
return redirect('/');
return redirect('/home');
}
return $next($request);

View File

@@ -1,54 +0,0 @@
<?php
/**
* StartFireflySession.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Middleware;
use Illuminate\Http\Request;
use Illuminate\Session\Middleware\StartSession;
use Illuminate\Session\SessionManager;
/**
* Class StartFireflySession
*
* @package FireflyIII\Http\Middleware
*/
class StartFireflySession extends StartSession
{
/**
* Create a new session middleware.
*
* @param \Illuminate\Session\SessionManager $manager
*/
public function __construct(SessionManager $manager)
{
parent::__construct($manager);
}
/**
* Store the current URL for the request if necessary.
*
* @param \Illuminate\Http\Request $request
* @param \Illuminate\Contracts\Session\Session $session
*
* @return void
*/
protected function storeCurrentUrl(Request $request, $session)
{
$fullUrl = $request->fullUrl();
if ($request->method() === 'GET' && $request->route() && !$request->ajax()) {
if (strpos($fullUrl, '/javascript/') === false) {
$session->setPreviousUrl($fullUrl);
}
}
}
}

View File

@@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
/**
* TrimStrings.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace FireflyIII\Http\Middleware;
use Illuminate\Foundation\Http\Middleware\TrimStrings as Middleware;
class TrimStrings extends Middleware
{
/**
* The names of the attributes that should not be trimmed.
*
* @var array
*/
protected $except
= [
'password',
'password_confirmation',
];
}

View File

@@ -0,0 +1,40 @@
<?php
declare(strict_types=1);
/**
* TrustProxies.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
namespace FireflyIII\Http\Middleware;
use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;
class TrustProxies extends Middleware
{
/**
* The current proxy header mappings.
*
* @var array
*/
protected $headers
= [
Request::HEADER_FORWARDED => 'FORWARDED',
Request::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR',
Request::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST',
Request::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT',
Request::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO',
];
/**
* The trusted proxies for this application.
*
* @var array
*/
protected $proxies;
}

View File

@@ -1,27 +1,21 @@
<?php
declare(strict_types=1);
/**
* VerifyCsrfToken.php
* Copyright (C) 2016 thegrumpydictator@gmail.com
*
* Copyright (c) 2017 thegrumpydictator@gmail.com
* This software may be modified and distributed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International License.
*
* See the LICENSE file for details.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Middleware;
use Carbon\Carbon;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as BaseVerifier;
use Symfony\Component\HttpFoundation\Cookie;
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware;
/**
* Class VerifyCsrfToken
*
* @package FireflyIII\Http\Middleware
*/
class VerifyCsrfToken extends BaseVerifier
class VerifyCsrfToken extends Middleware
{
/**
* The URIs that should be excluded from CSRF verification.
@@ -32,26 +26,4 @@ class VerifyCsrfToken extends BaseVerifier
= [
//
];
/**
* Add the CSRF token to the response cookies.
*
* @param \Illuminate\Http\Request $request
* @param \Symfony\Component\HttpFoundation\Response $response
*
* @return \Symfony\Component\HttpFoundation\Response
*/
protected function addCookieToResponse($request, $response)
{
$config = config('session');
$response->headers->setCookie(
new Cookie(
'XSRF-TOKEN', $request->session()->token(), Carbon::now()->getTimestamp() + 60 * $config['lifetime'],
$config['path'], $config['domain'], $config['secure'], true
)
);
return $response;
}
}

View File

@@ -75,13 +75,13 @@ class AccountFormRequest extends Request
return [
'id' => $idRule,
'name' => $nameRule,
'openingBalance' => 'numeric|required_with:openingBalanceDate',
'openingBalanceDate' => 'date|required_with:openingBalance',
'iban' => 'iban',
'BIC' => 'bic',
'virtualBalance' => 'numeric',
'openingBalance' => 'numeric|required_with:openingBalanceDate|nullable',
'openingBalanceDate' => 'date|required_with:openingBalance|nullable',
'iban' => 'iban|nullable',
'BIC' => 'bic|nullable',
'virtualBalance' => 'numeric|nullable',
'currency_id' => 'exists:transaction_currencies,id',
'accountNumber' => 'between:1,255|uniqueAccountNumberForUser',
'accountNumber' => 'between:1,255|uniqueAccountNumberForUser|nullable',
'accountRole' => 'in:' . $accountRoles,
'active' => 'boolean',
'ccType' => 'in:' . $ccPaymentTypes,

View File

@@ -47,11 +47,11 @@ class AttachmentFormRequest extends Request
*/
public function rules()
{
// fixed
return [
'title' => 'between:1,255',
'description' => 'between:1,65536',
'notes' => 'between:1,65536',
'title' => 'between:1,255|nullable',
'description' => 'between:1,65536|nullable',
'notes' => 'between:1,65536|nullable',
];
}
}

View File

@@ -61,7 +61,7 @@ class BillFormRequest extends Request
$nameRule .= ',' . intval($this->get('id'));
$matchRule .= ',' . intval($this->get('id'));
}
// is OK
$rules = [
'name' => $nameRule,
'match' => $matchRule,

View File

@@ -47,6 +47,7 @@ class BudgetFormRequest extends Request
*/
public function rules()
{
// fixed
/** @var BudgetRepositoryInterface $repository */
$repository = app(BudgetRepositoryInterface::class);
$nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name';

View File

@@ -35,8 +35,11 @@ class BudgetIncomeRequest extends Request
*/
public function rules()
{
// fixed
return [
'amount' => 'numeric|required|min:0',
'start' => 'required|date|before:end',
'end' => 'required|date|after:start',
];
}
}

View File

@@ -54,6 +54,7 @@ class CategoryFormRequest extends Request
$nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,' . intval($this->get('id'));
}
// fixed
return [
'name' => $nameRule,
];

View File

@@ -46,6 +46,7 @@ class ConfigurationRequest extends Request
*/
public function rules()
{
// fixed
$rules = [
'single_user_mode' => 'between:0,1|numeric',
'is_demo_site' => 'between:0,1|numeric',

View File

@@ -48,7 +48,7 @@ class CurrencyFormRequest extends Request
*/
public function rules()
{
// fixed
$rules = [
'name' => 'required|max:48|min:1|unique:transaction_currencies,name',
'code' => 'required|min:3|max:3|unique:transaction_currencies,code',

View File

@@ -35,6 +35,7 @@ class DeleteAccountFormRequest extends Request
*/
public function rules()
{
// fixed
return [
'password' => 'required',
];

Some files were not shown because too many files have changed in this diff Show More