Compare commits

...

59 Commits

Author SHA1 Message Date
James Cole
e6442dd8af Merge branch 'release/5.2.4' 2020-04-26 10:02:42 +02:00
James Cole
7905e0bd70 Bump to 5.2.4 2020-04-26 10:02:25 +02:00
James Cole
f4b1da352d no message 2020-04-26 07:08:33 +02:00
James Cole
0d33348941 Fix #3251 2020-04-26 06:57:59 +02:00
James Cole
c7c875e95f Fix #3251 2020-04-26 06:54:12 +02:00
James Cole
19d24b3e2a Clean up templates 2020-04-26 06:45:42 +02:00
James Cole
8fed6b6657 Fix #3287 2020-04-22 09:28:20 +02:00
James Cole
b5eafa1910 Merge tag '5.2.3' into develop
5.2.3
2020-04-22 06:33:23 +02:00
James Cole
c15501937f Merge branch 'release/5.2.3' 2020-04-22 06:33:22 +02:00
James Cole
4c743bd5b0 Update meta files for new release. 2020-04-22 06:29:34 +02:00
James Cole
44289cbd95 Fix #3284 2020-04-22 06:09:29 +02:00
James Cole
b2f1642cfe Fix #3281 2020-04-21 08:17:31 +02:00
James Cole
341ef0220c New translations. 2020-04-19 11:07:14 +02:00
James Cole
9df88115bc Update packages. 2020-04-19 11:05:14 +02:00
James Cole
c7273edb5e Updated language strings and meta config. 2020-04-19 06:52:12 +02:00
James Cole
c398aa2b69 Add support for British English and allow the user to set a locale. 2020-04-19 06:51:40 +02:00
James Cole
aa786eaaf3 Clean up language setting. 2020-04-19 06:11:49 +02:00
James Cole
e58a5e12d6 Fix #3270 2020-04-19 06:10:49 +02:00
James Cole
12b3575c5c Fix method reference 2020-04-19 06:09:55 +02:00
James Cole
3ca186dc8f Remove unused method. 2020-04-19 06:09:43 +02:00
James Cole
1535f596f6 Add two new support functions. 2020-04-19 06:07:43 +02:00
James Cole
2cc326caa1 Fix #3272 2020-04-19 06:05:39 +02:00
James Cole
43436ae942 Fix issue with casting. 2020-04-19 06:00:11 +02:00
James Cole
fbfd8475de Fix #3264 2020-04-15 16:17:45 +02:00
James Cole
405752f353 Merge tag '5.2.2' into develop
5.2.2
2020-04-14 21:01:03 +02:00
James Cole
2af98b259a Merge branch 'release/5.2.2' 2020-04-14 21:01:02 +02:00
James Cole
015242a666 Update meta files for new release. 2020-04-14 20:56:30 +02:00
James Cole
54933fda2e Fix #3263 2020-04-14 17:23:58 +02:00
James Cole
852d057a47 Fix #3259 2020-04-13 07:57:46 +02:00
James Cole
1778f0b4f3 Fix storing of virtual balance. 2020-04-13 07:57:32 +02:00
James Cole
6daf083b3f Clean up some code. 2020-04-12 06:24:35 +02:00
James Cole
4a7d9b130a Fix issue with multi-currency in asset accounts. 2020-04-12 06:23:35 +02:00
James Cole
4163efba55 Clean up phpdoc 2020-04-11 06:42:47 +02:00
James Cole
db5847b49b Consistent in minimum password length 2020-04-11 06:42:40 +02:00
James Cole
6829003f5e Change to safer hash methods. 2020-04-11 06:42:21 +02:00
James Cole
047927718e Merge branch 'release/5.2.1' 2020-04-10 21:23:53 +02:00
James Cole
91deb22a3f Merge tag '5.2.1' into develop
5.2.1
2020-04-10 21:23:53 +02:00
James Cole
1629ca0739 Update for some bugs. 2020-04-10 21:20:04 +02:00
James Cole
8b87204f10 User unable to store budgets without auto budget info. 2020-04-10 21:16:46 +02:00
James Cole
f920d90e3d Fix chart problem 2020-04-10 21:16:29 +02:00
James Cole
1cb91282af Merge tag '5.2.0' into develop
5.2.0
2020-04-10 13:51:23 +02:00
James Cole
a6ce294131 Merge branch 'release/5.2.0' 2020-04-10 13:51:22 +02:00
James Cole
34ceb69776 Update last minute files. 2020-04-10 13:50:37 +02:00
James Cole
eed68b5d95 Fix some code quality issues. 2020-04-10 10:47:24 +02:00
James Cole
79374c11ee Fix for #3248 2020-04-10 10:12:12 +02:00
James Cole
404f9df6d3 Bad link to model. 2020-04-10 07:29:15 +02:00
James Cole
4b716e35b9 Prep changelog for new release. 2020-04-10 07:20:45 +02:00
James Cole
166fc7a3e2 Fix trait 2020-04-09 20:33:55 +02:00
James Cole
06afbc7a0a Fix chart 2020-04-09 06:27:43 +02:00
James Cole
49a98de63a Add YNAB 2020-04-09 06:27:29 +02:00
James Cole
5b572c0da2 Expand readme. 2020-04-09 06:27:20 +02:00
James Cole
59014b1a87 Meta files for the next release. 2020-04-08 06:54:16 +02:00
James Cole
4aec1f06e0 Fix issue updating categories. 2020-04-08 06:43:58 +02:00
James Cole
136af9625a Better link for tags. 2020-04-07 18:19:29 +02:00
James Cole
edac26f757 Merge pull request #3236 from SuperSandro2000/patch-1
Add missing date based on releases page
2020-04-05 07:54:01 +02:00
Sandro
ac54dd05bf Add missing date based on releases page 2020-04-05 07:31:30 +02:00
James Cole
7948058364 Fix #3234 2020-04-05 07:14:17 +02:00
James Cole
f13a6f7bf9 New php docs [skip ci] 2020-04-05 07:10:59 +02:00
James Cole
e1a5d143c5 Merge tag '5.2.0-beta.1' into develop
5.2.0-beta.1
2020-04-02 06:54:50 +02:00
200 changed files with 4464 additions and 1177 deletions

View File

@@ -22,6 +22,10 @@ APP_KEY=SomeRandomStringOf32CharsExactly
# If text is still in English, remember that not everything may have been translated.
DEFAULT_LANGUAGE=en_US
# The locale defines how numbers are formatted.
# by default this value is the same as whatever the language is.
DEFAULT_LOCALE=equal
# Change this value to your preferred time zone.
# Example: Europe/Amsterdam
# For a list of supported time zones, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

View File

@@ -16,10 +16,10 @@ I am running Firefly III version x.x.x, and my problem is:
<!-- Please add extra info here, such as OS, browser, and the output from the /debug page of your Firefly III installation (click the version at the bottom). -->
**Bonus points**
<!-- Earn bonus points by checking the boxes -->
<!-- Before you submit, verify the following please: -->
- [ ] Nobody reported this bug before
- [ ] I have added a stack trace from my log files <!-- (see https://bit.ly/FF3-get-debug-info) -->
- [ ] I have added a screenshot.
- [ ] I was able to replicate it on the demo site https://demo.firefly-iii.org/
<!-- - [ ] I donated money (this is a joke :wink:)-->
- I searched and nobody reported this bug before
- I have added a stack trace from my log files <!-- (see https://bit.ly/FF3-get-debug-info) -->
- I have added a screenshot.
- I was able to replicate it on the demo site https://demo.firefly-iii.org/
<!-- - I donated money (this is a joke ;)-->

View File

@@ -16,8 +16,8 @@ I am running Firefly III version x.x.x.
<!-- Complete the following checklist for bonus points -->
- [ ] I have read the FAQ at https://bit.ly/FF3-FAQ
- [ ] I added a screenshot
- [ ] I added log files <!-- (see https://bit.ly/FF3-get-debug-info) -->
- [ ] I was able to replicate the issue on the demo site.
<!-- - [ ] I donated money (this is a joke :wink:)-->
- I have read the FAQ at https://bit.ly/FF3-FAQ
- I added a screenshot
- I added log files <!-- (see https://bit.ly/FF3-get-debug-info) -->
- I was able to replicate the issue on the demo site.
<!-- - I donated money (this is a joke :wink:)-->

1
.gitignore vendored
View File

@@ -1,4 +1,5 @@
/node_modules
/frontend/node_modules
/public/hot
/public/storage
/storage/*.key

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* CorrectOpeningBalanceCurrencies.php
* Copyright (c) 2020 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* FixLongDescriptions.php
* Copyright (c) 2020 james@firefly-iii.org
@@ -65,7 +66,7 @@ class FixLongDescriptions extends Command
$groups = TransactionGroup::get(['id', 'title']);
/** @var TransactionGroup $group */
foreach ($groups as $group) {
if (strlen($group->title) > self::MAX_LENGTH) {
if (strlen((string)$group->title) > self::MAX_LENGTH) {
$group->title = substr($group->title, 0, self::MAX_LENGTH);
$group->save();
$this->line(sprintf('Truncated description of transaction group #%d', $group->id));

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* FixRecurringTransactions.php
* Copyright (c) 2020 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* ExportData.php
* Copyright (c) 2020 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* RestoreOAuthKeys.php
* Copyright (c) 2020 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* MigrateRecurrenceMeta.php
* Copyright (c) 2020 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* MigrateTagLocations.php
* Copyright (c) 2020 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* DuplicateTransactionException.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -98,7 +98,7 @@ class AccountFactory
'user_id' => $this->user->id,
'account_type_id' => $type->id,
'name' => $data['name'],
'virtual_balance' => $data['virtual_balance'] ?? '0',
'virtual_balance' => $data['virtual_balance'] ?? null,
'active' => true === $data['active'],
'iban' => $data['iban'],
];
@@ -109,12 +109,12 @@ class AccountFactory
// remove virtual balance when not an asset account or a liability
if (!in_array($type->type, $this->canHaveVirtual, true)) {
$databaseData['virtual_balance'] = '0';
$databaseData['virtual_balance'] = null;
}
// fix virtual balance when it's empty
if ('' === $databaseData['virtual_balance']) {
$databaseData['virtual_balance'] = '0';
if ('' === (string)$databaseData['virtual_balance']) {
$databaseData['virtual_balance'] = null;
}
$return = Account::create($databaseData);

View File

@@ -280,25 +280,29 @@ class TransactionJournalFactory
/** create or get source and destination accounts */
$sourceInfo = [
'id' => (int) $row['source_id'],
'name' => $row['source_name'],
'iban' => $row['source_iban'],
'number' => $row['source_number'],
'bic' => $row['source_bic'],
'id' => (int) $row['source_id'],
'name' => $row['source_name'],
'iban' => $row['source_iban'],
'number' => $row['source_number'],
'bic' => $row['source_bic'],
'currency_id' => $currency->id,
];
$destInfo = [
'id' => (int) $row['destination_id'],
'name' => $row['destination_name'],
'iban' => $row['destination_iban'],
'number' => $row['destination_number'],
'bic' => $row['destination_bic'],
'id' => (int) $row['destination_id'],
'name' => $row['destination_name'],
'iban' => $row['destination_iban'],
'number' => $row['destination_number'],
'bic' => $row['destination_bic'],
'currency_id' => $currency->id,
];
Log::debug('Source info:', $sourceInfo);
Log::debug('Destination info:', $destInfo);
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
Log::debug('Now calling getAccount for the source.');
$sourceAccount = $this->getAccount($type->type, 'source', $sourceInfo);
Log::debug('Now calling getAccount for the destination.');
$destinationAccount = $this->getAccount($type->type, 'destination', $destInfo);
Log::debug('Done with getAccount(2x)');
$currency = $this->getCurrencyByAccount($type->type, $currency, $sourceAccount, $destinationAccount);
$foreignCurrency = $this->compareCurrencies($currency, $foreignCurrency);
$foreignCurrency = $this->getForeignByAccount($type->type, $foreignCurrency, $destinationAccount);
@@ -468,6 +472,7 @@ class TransactionJournalFactory
*/
private function getCurrency(?TransactionCurrency $currency, Account $account): TransactionCurrency
{
Log::debug('Now in getCurrency()');
$preference = $this->accountRepository->getAccountCurrency($account);
if (null === $preference && null === $currency) {
// return user's default:
@@ -489,6 +494,7 @@ class TransactionJournalFactory
*/
private function getCurrencyByAccount(string $type, ?TransactionCurrency $currency, Account $source, Account $destination): TransactionCurrency
{
Log::debug('Now ingetCurrencyByAccount()');
switch ($type) {
default:
case TransactionType::WITHDRAWAL:
@@ -538,15 +544,15 @@ class TransactionJournalFactory
$dataRow = $row->getArrayCopy();
unset($dataRow['import_hash_v2'], $dataRow['original_source']);
$json = json_encode($dataRow);
$json = json_encode($dataRow, JSON_THROW_ON_ERROR, 512);
if (false === $json) {
// @codeCoverageIgnoreStart
$json = json_encode((string) microtime());
$json = json_encode((string) microtime(), JSON_THROW_ON_ERROR, 512);
Log::error(sprintf('Could not hash the original row! %s', json_last_error_msg()), $dataRow);
// @codeCoverageIgnoreEnd
}
$hash = hash('sha256', $json);
Log::debug(sprintf('The hash is: %s', $hash));
Log::debug(sprintf('The hash is: %s', $hash), $dataRow);
return $hash;
}
@@ -601,7 +607,7 @@ class TransactionJournalFactory
// validate source account.
$sourceId = isset($data['source_id']) ? (int) $data['source_id'] : null;
$sourceName = $data['source_name'] ?? null;
$sourceName = isset($data['source_name']) ? (string) $data['source_name'] : null;
$validSource = $this->accountValidator->validateSource($sourceId, $sourceName, null);
// do something with result:
@@ -611,7 +617,7 @@ class TransactionJournalFactory
Log::debug('Source seems valid.');
// validate destination account
$destinationId = isset($data['destination_id']) ? (int) $data['destination_id'] : null;
$destinationName = (string)($data['destination_name'] ?? null);
$destinationName = isset($data['destination_name']) ? (string) $data['destination_name'] : null;
$validDestination = $this->accountValidator->validateDestination($destinationId, $destinationName, null);
// do something with result:
if (false === $validDestination) {

View File

@@ -154,14 +154,14 @@ class MonthReportGenerator implements ReportGeneratorInterface
$journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date');
}
$locale = app('steam')->getLocale();
$return = [
'journals' => $journals,
'currency' => $currency,
'exists' => count($journals) > 0,
'end' => $this->end->formatLocalized((string) trans('config.month_and_day')),
'end' => $this->end->formatLocalized((string) trans('config.month_and_day', [], $locale)),
'endBalance' => app('steam')->balance($account, $this->end),
'dayBefore' => $date->formatLocalized((string) trans('config.month_and_day')),
'dayBefore' => $date->formatLocalized((string) trans('config.month_and_day', [], $locale)),
'dayBeforeBalance' => $dayBeforeBalance,
];

View File

@@ -165,7 +165,8 @@ class UserEventHandler
$user = $event->user;
$ipAddress = $event->ipAddress;
$token = app('preferences')->getForUser($user, 'email_change_undo_token', 'invalid');
$uri = route('profile.undo-email-change', [$token->data, hash('sha256', $oldEmail)]);
$hashed = hash('sha256', sprintf('%s%s', (string) config('app.key'), $oldEmail));
$uri = route('profile.undo-email-change', [$token->data,$hashed]);
try {
Mail::to($oldEmail)->send(new UndoEmailChangeMail($newEmail, $oldEmail, $uri, $ipAddress));
// @codeCoverageIgnoreStart

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* TelemetryController.php
* Copyright (c) 2020 thegrumpydictator@gmail.com

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**

View File

@@ -86,7 +86,6 @@ class IndexController extends Controller
}
/**
* TODO the "budgeted" progress bar doesn't update.
* Show all budgets.
*
* @param Request $request
@@ -106,7 +105,6 @@ class IndexController extends Controller
$budgeted = '0';
$spent = '0';
// new period stuff:
$periodTitle = app('navigation')->periodShow($start, $range);
$prevLoop = $this->getPreviousPeriods($start, $range);

View File

@@ -432,9 +432,15 @@ class AccountController extends Controller
$cache->addProperty($end);
$cache->addProperty($account->id);
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
return response()->json($cache->get()); // @codeCoverageIgnore
}
$currencies = $this->accountRepository->getUsedCurrencies($account);
// if the account is not expense or revenue, just use the account's default currency.
if (!in_array($account->accountType->type, [AccountType::REVENUE, AccountType::EXPENSE], true)) {
$currencies = [$this->accountRepository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency()];
}
/** @var TransactionCurrency $currency */
foreach ($currencies as $currency) {
$chartData[] = $this->periodByCurrency($start, $end, $account, $currency);
@@ -565,6 +571,7 @@ class AccountController extends Controller
*/
private function periodByCurrency(Carbon $start, Carbon $end, Account $account, TransactionCurrency $currency): array
{
$locale = app('steam')->getLocale();
$step = $this->calculateStep($start, $end);
$result = [
'label' => sprintf('%s (%s)', $account->name, $currency->symbol),
@@ -576,7 +583,7 @@ class AccountController extends Controller
switch ($step) {
case '1D':
// per day the entire period, balance for every day.
$format = (string) trans('config.month_and_day');
$format = (string) trans('config.month_and_day', [], $locale);
$range = app('steam')->balanceInRange($account, $start, $end, $currency);
$previous = array_values($range)[0];
while ($end >= $current) {

View File

@@ -111,6 +111,7 @@ class BillController extends Controller
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
}
$locale = app('steam')->getLocale();
/** @var GroupCollectorInterface $collector */
$collector = app(GroupCollectorInterface::class);
@@ -131,7 +132,7 @@ class BillController extends Controller
];
foreach ($journals as $journal) {
$date = $journal['date']->formatLocalized((string) trans('config.month_and_day'));
$date = $journal['date']->formatLocalized((string) trans('config.month_and_day', [], $locale));
$chartData[0]['entries'][$date] = $bill->amount_min; // minimum amount of bill
$chartData[1]['entries'][$date] = $bill->amount_max; // maximum amount of bill

View File

@@ -179,14 +179,14 @@ class BudgetController extends Controller
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
}
$locale = app('steam')->getLocale();
$entries = [];
$amount = $budgetLimit->amount;
$budgetCollection = new Collection([$budget]);
while ($start <= $end) {
$spent = $this->opsRepository->spentInPeriod($budgetCollection, new Collection, $start, $start);
$amount = bcadd($amount, $spent);
$format = $start->formatLocalized((string)trans('config.month_and_day'));
$format = $start->formatLocalized((string)trans('config.month_and_day', [], $locale));
$entries[$format] = $amount;
$start->addDay();

View File

@@ -76,6 +76,7 @@ class PiggyBankController extends Controller
}
$set = $repository->getEvents($piggyBank);
$set = $set->reverse();
$locale =app('steam')->getLocale();
// get first event or start date of piggy bank or today
$startDate = $piggyBank->start_date ?? new Carbon;
@@ -99,7 +100,7 @@ class PiggyBankController extends Controller
}
);
$currentSum = $filtered->sum('amount');
$label = $oldest->formatLocalized((string) trans('config.month_and_day'));
$label = $oldest->formatLocalized((string) trans('config.month_and_day', [], $locale));
$chartData[$label] = $currentSum;
$oldest = app('navigation')->addPeriod($oldest, $step, 0);
}
@@ -110,7 +111,7 @@ class PiggyBankController extends Controller
}
);
$finalSum = $finalFiltered->sum('amount');
$finalLabel = $today->formatLocalized((string) trans('config.month_and_day'));
$finalLabel = $today->formatLocalized((string) trans('config.month_and_day', [], $locale));
$chartData[$finalLabel] = $finalSum;
$data = $this->generator->singleSet($piggyBank->name, $chartData);

View File

@@ -79,6 +79,7 @@ class ReportController extends Controller
if ($cache->has()) {
return response()->json($cache->get()); // @codeCoverageIgnore
}
$locale = app('steam')->getLocale();
$current = clone $start;
$chartData = [];
/** @var NetWorthInterface $helper */
@@ -110,7 +111,7 @@ class ReportController extends Controller
/** @var array $netWorthItem */
foreach ($result as $netWorthItem) {
$currencyId = $netWorthItem['currency']->id;
$label = $current->formatLocalized((string) trans('config.month_and_day'));
$label = $current->formatLocalized((string) trans('config.month_and_day', [], $locale));
if (!isset($chartData[$currencyId])) {
$chartData[$currencyId] = [
'label' => 'Net worth in ' . $netWorthItem['currency']->name,

View File

@@ -450,8 +450,6 @@ class TagReportController extends Controller
$data = $this->generator->multiCurrencyPieChart($result);
return response()->json($data);
return response()->json($data);
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* TransactionController.php
* Copyright (c) 2020 thegrumpydictator@gmail.com
@@ -137,6 +138,7 @@ class TransactionController extends Controller
$collector->setTypes([TransactionType::DEPOSIT]);
break;
case 'transfers':
case 'transfer':
$collector->setTypes([TransactionType::TRANSFER]);
break;
}
@@ -204,6 +206,7 @@ class TransactionController extends Controller
$collector->setTypes([TransactionType::DEPOSIT]);
break;
case 'transfers':
case 'transfer':
$collector->setTypes([TransactionType::TRANSFER]);
break;
}
@@ -270,6 +273,7 @@ class TransactionController extends Controller
$collector->setTypes([TransactionType::DEPOSIT]);
break;
case 'transfers':
case 'transfer':
$collector->setTypes([TransactionType::TRANSFER]);
break;
}

View File

@@ -85,17 +85,20 @@ class Controller extends BaseController
$this->middleware(
function ($request, $next) {
$locale = app('steam')->getLocale();
// translations for specific strings:
$this->monthFormat = (string) trans('config.month');
$this->monthAndDayFormat = (string) trans('config.month_and_day');
$this->dateTimeFormat = (string) trans('config.date_time');
$this->monthFormat = (string) trans('config.month', [], $locale);
$this->monthAndDayFormat = (string) trans('config.month_and_day', [], $locale);
$this->dateTimeFormat = (string) trans('config.date_time', [], $locale);
// get shown-intro-preference:
if (auth()->check()) {
$language = $this->getLanguage();
$language = app('steam')->getLanguage();
$locale = app('steam')->getLocale();
$page = $this->getPageName();
$shownDemo = $this->hasSeenDemo();
app('view')->share('language', $language);
app('view')->share('locale', $locale);
app('view')->share('shownDemo', $shownDemo);
app('view')->share('current_route_name', $page);
app('view')->share('original_route_name', Route::currentRouteName());

View File

@@ -126,7 +126,6 @@ class DebugController extends Controller
$phpOs = str_replace($search, $replace, PHP_OS);
$interface = PHP_SAPI;
$now = Carbon::now()->format('Y-m-d H:i:s e');
$extensions = implode(', ', get_loaded_extensions());
$drivers = implode(', ', DB::availableDrivers());
$currentDriver = DB::getDriverName();
$userAgent = $request->header('user-agent');
@@ -143,7 +142,7 @@ class DebugController extends Controller
// set languages, see what happens:
$original = setlocale(LC_ALL, 0);
$localeAttempts = [];
$parts = explode(',', (string) trans('config.locale'));
$parts = app('steam')->getLocaleArray(app('steam')->getLocale());
foreach ($parts as $code) {
$code = trim($code);
$localeAttempts[$code] = var_export(setlocale(LC_ALL, $code), true);
@@ -178,7 +177,6 @@ class DebugController extends Controller
'debug',
compact(
'phpVersion',
'extensions',
'localeAttempts',
'appEnv',
'appDebug',

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* IndexController.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -126,7 +126,7 @@ class JavascriptController extends Controller
/** @noinspection NullPointerExceptionInspection */
$lang = $pref->data;
$dateRange = $this->getDateRangeConfig();
$uid = substr(hash('sha256', auth()->user()->id . auth()->user()->email), 0, 12);
$uid = substr(hash('sha256', sprintf('%s-%s-%s', (string) config('app.key'), auth()->user()->id, auth()->user()->email)), 0, 12);
$data = [
'currencyCode' => $currency->code,

View File

@@ -263,7 +263,7 @@ class BoxController extends Controller
*/
public function netWorth(): JsonResponse
{
$date = Carbon::now()->startOfDay();
$date = Carbon::now()->endOfDay();
// start and end in the future? use $end
if ($this->notInSessionRange($date)) {

View File

@@ -151,6 +151,7 @@ class RecurrenceController extends Controller
$today = Carbon::now()->startOfDay();
$date = Carbon::createFromFormat('Y-m-d', $string)->startOfDay();
$preSelected = (string) $request->get('pre_select');
$locale = app('steam')->getLocale();
Log::debug(sprintf('date = %s, today = %s. date > today? %s', $date->toAtomString(), $today->toAtomString(), var_export($date > $today, true)));
Log::debug(sprintf('past = true? %s', var_export('true' === (string) $request->get('past'), true)));
@@ -163,7 +164,7 @@ class RecurrenceController extends Controller
$dayOfWeek = (string) trans(sprintf('config.dow_%s', $date->dayOfWeekIso));
$ndom = sprintf('ndom,%s,%s', $date->weekOfMonth, $date->dayOfWeekIso);
$yearly = sprintf('yearly,%s', $date->format('Y-m-d'));
$yearlyDate = $date->formatLocalized((string) trans('config.month_and_day_no_year'));
$yearlyDate = $date->formatLocalized((string) trans('config.month_and_day_no_year', [], $locale));
$result = [
'daily' => ['label' => (string) trans('firefly.recurring_daily'), 'selected' => 0 === strpos($preSelected, 'daily')],
$weekly => ['label' => (string) trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]),

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use FireflyIII\Http\Requests\NewUserFormRequest;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface;
use FireflyIII\Support\Http\Controllers\CreateStuff;
@@ -110,6 +111,12 @@ class NewUserController extends Controller
// store currency preference:
app('preferences')->set('currencyPreference', $currency->code);
// store frontpage preferences:
$accounts = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
app('preferences')->set('frontPageAccounts', $accounts);
// mark.
app('preferences')->mark();
// set default optional fields:

View File

@@ -31,6 +31,7 @@ use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\View\View;
use JsonException;
/**
* Class PreferencesController.
@@ -90,8 +91,9 @@ class PreferencesController extends Controller
$viewRange = $viewRangePref->data;
$frontPageAccounts = app('preferences')->get('frontPageAccounts', $accountIds);
$language = app('preferences')->get('language', config('firefly.default_language', 'en_US'))->data;
$language = app('steam')->getLanguage();
$languages = config('firefly.languages');
$locale = app('preferences')->get('locale', config('firefly.default_locale', 'equal'))->data;
$listPageSize = app('preferences')->get('listPageSize', 50)->data;
$customFiscalYear = app('preferences')->get('customFiscalYear', 0)->data;
$fiscalYearStartStr = app('preferences')->get('fiscalYearStart', '01-01')->data;
@@ -100,6 +102,15 @@ class PreferencesController extends Controller
ksort($languages);
// list of locales also has "equal" which makes it equal to whatever the language is.
try {
$locales = json_decode(file_get_contents(resource_path(sprintf('lang/%s/locales.json', $language))), true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
Log::error($e->getMessage());
$locales = [];
}
$locales = ['equal' => (string) trans('firefly.equal_to_language')] + $locales;
// an important fallback is that the frontPageAccount array gets refilled automatically
// when it turns up empty.
if (0 === count($frontPageAccounts->data)) {
@@ -113,6 +124,8 @@ class PreferencesController extends Controller
'groupedAccounts',
'frontPageAccounts',
'languages',
'locales',
'locale',
'tjOptionalFields',
'viewRange',
'customFiscalYear',
@@ -172,6 +185,11 @@ class PreferencesController extends Controller
session()->flash('info', 'All translations are supplied by volunteers. There might be errors and mistakes. I appreciate your feedback.');
}
// same for locale:
/** @var Preference $currentLocale */
$locale = $request->get('locale');
app('preferences')->set('locale', $locale);
// optional fields for transactions:
$setOptions = $request->get('tj');
$optionalTj = [

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* DataController.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -555,7 +555,7 @@ class ProfileController extends Controller
/** @var string $match */
$match = null;
foreach ($set as $entry) {
$hashed = hash('sha256', $entry->data);
$hashed = hash('sha256', sprintf('%s%s', (string) config('app.key'), $entry->data));
if ($hashed === $hash) {
$match = $entry->data;
break;

View File

@@ -110,8 +110,13 @@ class IndexController extends Controller
$array['first_date'] = new Carbon($array['first_date']);
$array['repeat_until'] = null === $array['repeat_until'] ? null : new Carbon($array['repeat_until']);
$array['latest_date'] = null === $array['latest_date'] ? null : new Carbon($array['latest_date']);
$array['occurrences'] = array_slice($this->recurring->getOccurrencesInRange($recurrence->recurrenceRepetitions->first(), $today, $year), 0, 1);
$recurring[] = $array;
$array['occurrences'] = [];
if (0 !== $recurrence->recurrenceRepetitions->count()) {
$array['ocurrences'] = array_slice($this->recurring->getOccurrencesInRange($recurrence->recurrenceRepetitions->first(), $today, $year), 0, 1);
}
$recurring[] = $array;
}
$paginator = new LengthAwarePaginator($recurring, $total, $pageSize, $page);
$paginator->setPath(route('recurring.index'));

View File

@@ -301,7 +301,6 @@ class BudgetController extends Controller
$report[$budgetId]['currencies'][$currencyId]['sum_pct'] = $pct;
}
}
return view('reports.budget.partials.budgets', compact('sums', 'report'));
}
@@ -317,6 +316,7 @@ class BudgetController extends Controller
*/
public function general(Collection $accounts, Carbon $start, Carbon $end)
{
$report = [
'budgets' => [],
'sums' => [],
@@ -488,6 +488,7 @@ class BudgetController extends Controller
foreach ($expenses as $currency) {
foreach ($currency['budgets'] as $budget) {
$count = 0;
$total = '0';
foreach ($budget['transaction_journals'] as $journal) {
$count++;
$key = sprintf('%d-%d', $budget['id'], $currency['currency_id']);
@@ -506,7 +507,7 @@ class BudgetController extends Controller
$report[$key]['entries'][$dateKey] = $report[$key] ['entries'][$dateKey] ?? '0';
$report[$key]['entries'][$dateKey] = bcadd($journal['amount'], $report[$key] ['entries'][$dateKey]);
$report[$key]['sum'] = bcadd($report[$key] ['sum'], $journal['amount']);
$report[$key]['avg'] = bcdiv($report[$key]['sum'], (string) $count);
$report[$key]['avg'] = bcdiv($report[$key]['sum'], (string) count($periods));
}
}
}

View File

@@ -206,9 +206,9 @@ class ConvertController extends Controller
// double check its not an empty string.
$sourceId = '' === $sourceId || null === $sourceId ? null : (int) $sourceId;
$sourceName = '' === $sourceName ? null : $sourceName;
$sourceName = '' === $sourceName ? null : (string) $sourceName;
$destinationId = '' === $destinationId || null === $destinationId ? null : (int) $destinationId;
$destinationName = (string)('' === $destinationName ? null : $destinationName);
$destinationName = '' === $destinationName ? null : (string) $destinationName;
$validSource = $validator->validateSource($sourceId, $sourceName, null);
$validDestination = $validator->validateDestination($destinationId, $destinationName, null);

View File

@@ -108,6 +108,7 @@ class ShowController extends Controller
if (!Str::contains($transaction['notes'], $search)) {
$groupArray['transactions'][$index]['notes'] = e($transaction['notes']);
}
$groupArray['transactions'][$index]['tags'] = $this->repository->getTagObjects($groupArray['transactions'][$index]['transaction_journal_id']);
}
$events = $this->repository->getPiggyEvents($transactionGroup);

View File

@@ -26,6 +26,7 @@ use App;
use Carbon\Carbon;
use Closure;
use FireflyIII\Repositories\Journal\JournalRepositoryInterface;
use FireflyIII\Support\Http\Controllers\RequestInformation;
use Illuminate\Http\Request;
/**
@@ -33,6 +34,7 @@ use Illuminate\Http\Request;
*/
class Range
{
use RequestInformation;
/**
* Handle an incoming request.
*
@@ -72,16 +74,16 @@ class Range
*/
private function configureView(): void
{
$pref = app('preferences')->get('language', config('firefly.default_language', 'en_US'));
/** @noinspection NullPointerExceptionInspection */
$lang = $pref->data;
App::setLocale($lang);
Carbon::setLocale(substr($lang, 0, 2));
$locale = explode(',', (string) trans('config.locale'));
$locale = array_map('trim', $locale);
// get locale preference:
$language = app('steam')->getLanguage();
$locale = app('steam')->getLocale();
App::setLocale($language);
Carbon::setLocale(substr($locale, 0, 2));
setlocale(LC_TIME, $locale);
$moneyResult = setlocale(LC_MONETARY, $locale);
$localeArray = app('steam')->getLocaleArray($locale);
setlocale(LC_TIME, $localeArray);
$moneyResult = setlocale(LC_MONETARY, $localeArray);
// send error to view if could not set money format
if (false === $moneyResult) {
@@ -89,12 +91,12 @@ class Range
}
// save some formats:
$monthAndDayFormat = (string) trans('config.month_and_day');
$dateTimeFormat = (string) trans('config.date_time');
$monthAndDayFormat = (string) trans('config.month_and_day', [], $locale);
$dateTimeFormat = (string) trans('config.date_time', [], $locale);
$defaultCurrency = app('amount')->getDefaultCurrency();
// also format for moment JS:
$madMomentJS = (string) trans('config.month_and_day_moment_js');
$madMomentJS = (string) trans('config.month_and_day_moment_js', [], $locale);
app('view')->share('madMomentJS', $madMomentJS);
app('view')->share('monthAndDayFormat', $monthAndDayFormat);

View File

@@ -68,7 +68,7 @@ class BudgetFormStoreRequest extends Request
'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name',
'active' => 'numeric|between:0,1',
'auto_budget_type' => 'numeric|between:0,2',
'auto_budget_currency_id' => 'required|exists:transaction_currencies,id',
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
'auto_budget_amount' => 'min:0|max:1000000000',
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
];

View File

@@ -78,7 +78,7 @@ class BudgetFormUpdateRequest extends Request
'name' => $nameRule,
'active' => 'numeric|between:0,1',
'auto_budget_option' => 'numeric|between:0,2',
'auto_budget_currency_id' => 'required|exists:transaction_currencies,id',
'auto_budget_currency_id' => 'exists:transaction_currencies,id',
'auto_budget_amount' => 'min:0|max:1000000000',
'auto_budget_period' => 'in:daily,weekly,monthly,quarterly,half_year,yearly',
];

View File

@@ -53,7 +53,7 @@ class PiggyBankFormRequest extends Request
'account_id' => $this->integer('account_id'),
'targetamount' => $this->string('targetamount'),
'targetdate' => $this->date('targetdate'),
'notes' => $this->string('notes'),
'notes' => $this->nlString('notes'),
];
}

View File

@@ -50,7 +50,7 @@ class ProfileFormRequest extends Request
// fixed
return [
'current_password' => 'required',
'new_password' => 'required|confirmed|secure_password',
'new_password' => 'required|confirmed|secure_password|min:16',
'new_password_confirmation' => 'required',
];
}

View File

@@ -252,7 +252,11 @@ class Account extends Model
*/
public function setVirtualBalanceAttribute($value): void
{
$this->attributes['virtual_balance'] = (string) $value;
$value = (string)$value;
if('' === $value) {
$value = null;
}
$this->attributes['virtual_balance'] = $value;
}
/**

View File

@@ -83,7 +83,7 @@ class AccountMeta extends Model
*/
public function getDataAttribute($value)
{
return json_decode($value);
return json_decode($value, true, 512, JSON_THROW_ON_ERROR);
}
/**

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* AutoBudget.php
* Copyright (c) 2020 thegrumpydictator@gmail.com

View File

@@ -89,6 +89,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read int|null $attachments_count
* @property-read int|null $notes_count
* @property-read int|null $transaction_journals_count
* @property bool $name_encrypted
* @property bool $match_encrypted
*/
class Bill extends Model
{

View File

@@ -77,6 +77,10 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read int|null $budgetlimits_count
* @property-read int|null $transaction_journals_count
* @property-read int|null $transactions_count
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property bool $encrypted
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\BudgetLimit[] $budgetlimits
*/
class Budget extends Model
{

View File

@@ -70,6 +70,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read int|null $attachments_count
* @property-read int|null $transaction_journals_count
* @property-read int|null $transactions_count
* @property bool $encrypted
*/
class Category extends Model
{

View File

@@ -35,8 +35,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Class ImportJob.
*
* @codeCoverageIgnore
* @deprecated
* @codeCoverageIgnore
* @deprecated
* @property array $transactions
* @property array $configuration
* @property User $user
@@ -73,6 +73,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|ImportJob whereUserId($value)
* @mixin Eloquent
* @property-read int|null $attachments_count
* @property int $id
* @property array|null $extended_status
*/
class ImportJob extends Model
{

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* Location.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -51,6 +51,10 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
* @method static Builder|PiggyBankEvent whereTransactionJournalId($value)
* @method static Builder|PiggyBankEvent whereUpdatedAt($value)
* @mixin Eloquent
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property \Illuminate\Support\Carbon $date
* @property-read \FireflyIII\Models\TransactionJournal|null $transactionJournal
*/
class PiggyBankEvent extends Model
{

View File

@@ -50,6 +50,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|Preference whereUpdatedAt($value)
* @method static Builder|Preference whereUserId($value)
* @mixin Eloquent
* @property-read \FireflyIII\User $user
*/
class Preference extends Model
{

View File

@@ -76,6 +76,7 @@ use Illuminate\Support\Collection;
* @method static Builder|RecurrenceTransaction withoutTrashed()
* @mixin Eloquent
* @property-read int|null $recurrence_transaction_meta_count
* @property int $transaction_currency_id
*/
class RecurrenceTransaction extends Model
{

View File

@@ -69,6 +69,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @mixin Eloquent
* @property-read int|null $rules_count
* @method static \Illuminate\Database\Eloquent\Builder|RuleGroup whereStopProcessing($value)
* @property string|null $description
*/
class RuleGroup extends Model
{

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* Telemetry.php
* Copyright (c) 2020 thegrumpydictator@gmail.com

View File

@@ -132,6 +132,9 @@ use Illuminate\Database\Eloquent\SoftDeletes;
* @mixin Eloquent
* @property-read int|null $budgets_count
* @property-read int|null $categories_count
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property bool $reconciled
*/
class Transaction extends Model
{

View File

@@ -67,6 +67,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read int|null $budget_limits_count
* @property-read int|null $transaction_journals_count
* @property-read int|null $transactions_count
* @property string $name
*/
class TransactionCurrency extends Model
{

View File

@@ -121,6 +121,18 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read int|null $transaction_journal_meta_count
* @property-read int|null $transactions_count
* @method static EloquentBuilder|TransactionJournal whereTransactionGroupId($value)
* @property int $user_id
* @property int|null $transaction_group_id
* @property int|null $transaction_currency_id
* @property \Illuminate\Support\Carbon|null $interest_date
* @property \Illuminate\Support\Carbon|null $book_date
* @property \Illuminate\Support\Carbon|null $process_date
* @property int $order
* @property bool $encrypted
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Budget[] $budgets
* @property-read \FireflyIII\Models\TransactionGroup|null $transactionGroup
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\TransactionJournalMeta[] $transactionJournalMeta
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Transaction[] $transactions
*/
class TransactionJournal extends Model
{

View File

@@ -48,7 +48,7 @@ use FireflyIII\Services\FireflyIIIOrg\Update\UpdateRequest;
use FireflyIII\Services\FireflyIIIOrg\Update\UpdateRequestInterface;
use FireflyIII\Services\IP\IpifyOrg;
use FireflyIII\Services\IP\IPRetrievalInterface;
use FireflyIII\Services\Password\PwndVerifierV3;
use FireflyIII\Services\Password\PwndVerifierV2;
use FireflyIII\Services\Password\Verifier;
use FireflyIII\Support\Amount;
use FireflyIII\Support\ExpandedForm;
@@ -189,7 +189,7 @@ class FireflyServiceProvider extends ServiceProvider
$this->app->bind(ExchangeRateInterface::class, $class);
// password verifier thing
$this->app->bind(Verifier::class, PwndVerifierV3::class);
$this->app->bind(Verifier::class, PwndVerifierV2::class);
// IP thing:
$this->app->bind(IPRetrievalInterface::class, IpifyOrg::class);

View File

@@ -79,6 +79,8 @@ class BudgetRepository implements BudgetRepositoryInterface
$budget->order = $index + 1;
$budget->save();
}
// other budgets, set to 0.
$this->user->budgets()->where('active', 0)->update(['order' => 0]);
return true;
}
@@ -187,12 +189,12 @@ class BudgetRepository implements BudgetRepositoryInterface
*/
public function getActiveBudgets(): Collection
{
//throw new \RuntimeException;
/** @var Collection $set */
$set = $this->user->budgets()->where('active', 1)
->orderBy('order', 'DESC')
->orderBy('order', 'ASC')
->orderBy('name', 'ASC')
->get();
return $set;
}
@@ -202,7 +204,7 @@ class BudgetRepository implements BudgetRepositoryInterface
public function getBudgets(): Collection
{
/** @var Collection $set */
$set = $this->user->budgets()->orderBy('order', 'DESC')
$set = $this->user->budgets()->orderBy('order', 'ASC')
->orderBy('name', 'ASC')->get();
return $set;
@@ -227,7 +229,7 @@ class BudgetRepository implements BudgetRepositoryInterface
{
/** @var Collection $set */
$set = $this->user->budgets()
->orderBy('order', 'DESC')
->orderBy('order', 'ASC')
->orderBy('name', 'ASC')->where('active', 0)->get();
return $set;
@@ -277,11 +279,13 @@ class BudgetRepository implements BudgetRepositoryInterface
*/
public function store(array $data): Budget
{
$order = $this->getMaxOrder();
try {
$newBudget = Budget::create(
[
'user_id' => $this->user->id,
'name' => $data['name'],
'order' => $order + 1,
]
);
} catch (QueryException $e) {
@@ -487,4 +491,9 @@ class BudgetRepository implements BudgetRepositoryInterface
{
return $budget->attachments()->get();
}
public function getMaxOrder(): int
{
return (int)$this->user->budgets()->max('order');
}
}

View File

@@ -58,6 +58,11 @@ interface BudgetRepositoryInterface
*/
public function destroyAutoBudget(Budget $budget): void;
/**
* @return int
*/
public function getMaxOrder(): int;
/**
* @return bool

View File

@@ -267,6 +267,7 @@ class CategoryRepository implements CategoryRepositoryInterface
{
/** @var CategoryUpdateService $service */
$service = app(CategoryUpdateService::class);
$service->setUser($this->user);
return $service->update($category, $data);
}

View File

@@ -384,7 +384,7 @@ class ImportJobRepository implements ImportJobRepositoryInterface
$attachment = new Attachment; // create Attachment object.
$attachment->user()->associate($job->user);
$attachment->attachable()->associate($job);
$attachment->md5 = md5($content);
$attachment->md5 = substr(hash('sha256', $content), 0, 32); // limit due to DB.
$attachment->filename = $name;
$attachment->mime = 'plain/txt';
$attachment->size = strlen($content);

View File

@@ -45,6 +45,7 @@ use FireflyIII\Services\Internal\Update\GroupUpdateService;
use FireflyIII\Support\NullArrayObject;
use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection;
use Log;
/**
@@ -468,4 +469,15 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface
return $return;
}
/**
* @inheritDoc
*/
public function getTagObjects(int $journalId): Collection
{
/** @var TransactionJournal $journal */
$journal = $this->user->transactionJournals()->find($journalId);
return $journal->tags()->get();
}
}

View File

@@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\TransactionGroup;
use FireflyIII\Support\NullArrayObject;
use FireflyIII\User;
use Illuminate\Support\Collection;
/**
* Interface TransactionGroupRepositoryInterface
@@ -122,6 +123,15 @@ interface TransactionGroupRepositoryInterface
*/
public function getTags(int $journalId): array;
/**
* Get the tags for a journal (by ID) as Tag objects.
*
* @param int $journalId
*
* @return Collection
*/
public function getTagObjects(int $journalId): Collection;
/**
* Set the user.
*

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* IsTransferAccount.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* LessThanPiggyTarget.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* UpdateRequest.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* UpdateRequestInterface.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -237,7 +237,6 @@ trait AccountServiceTrait
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
return $group;

View File

@@ -345,6 +345,7 @@ trait JournalServiceTrait
*/
private function createAccount(?Account $account, array $data, string $preferredType): Account
{
Log::debug('Now in createAccount()', $data);
// return new account.
if (null === $account) {
$data['name'] = $data['name'] ?? '(no name)';
@@ -359,22 +360,25 @@ trait JournalServiceTrait
'account_type_id' => null,
'account_type' => $preferredType,
'name' => $data['name'],
'virtual_balance' => null,
'active' => true,
'iban' => $data['iban'],
'currency_id' => $data['currency_id'] ?? null,
]
);
// store BIC
if (null !== $data['bic']) {
/** @var AccountMetaFactory $metaFactory */
$metaFactory = app(AccountMetaFactory::class);
$metaFactory->create(['account_id' => $result->id, 'name' => 'BIC', 'data' => $data['bic']]);
$metaFactory->create(['account_id' => $account->id, 'name' => 'BIC', 'data' => $data['bic']]);
}
// store account number
if (null !== $data['number']) {
/** @var AccountMetaFactory $metaFactory */
$metaFactory = app(AccountMetaFactory::class);
$metaFactory->create(['account_id' => $result->id, 'name' => 'account_number', 'data' => $data['bic']]);
$metaFactory->create(['account_id' => $account->id, 'name' => 'account_number', 'data' => $data['bic']]);
}
}
return $account;

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* LocationServiceTrait.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -35,6 +35,9 @@ use Log;
*/
class CategoryUpdateService
{
private $user;
/**
* Constructor.
*/
@@ -43,6 +46,9 @@ class CategoryUpdateService
if ('testing' === config('app.env')) {
Log::warning(sprintf('%s should not be instantiated in the TEST environment!', get_class($this)));
}
if(auth()->check()) {
$this->user = auth()->user();
}
}
/**
@@ -106,4 +112,12 @@ class CategoryUpdateService
}
}
/**
* @param mixed $user
*/
public function setUser($user): void
{
$this->user = $user;
}
}

View File

@@ -58,8 +58,11 @@ class PwndVerifierV2 implements Verifier
$rest = substr($hash, 5);
$uri = sprintf('https://api.pwnedpasswords.com/range/%s', $prefix);
$opt = [
'headers' => ['User-Agent' => 'Firefly III v' . config('firefly.version')],
'timeout' => 5];
'headers' => [
'User-Agent' => 'Firefly III v' . config('firefly.version'),
'Add-Padding' => 'true',
],
'timeout' => 3.1415];
Log::debug(sprintf('hash prefix is %s', $prefix));
Log::debug(sprintf('rest is %s', $rest));
@@ -87,7 +90,7 @@ class PwndVerifierV2 implements Verifier
return true;
}
Log::debug(sprintf('Could not find %s, return FALSE.', $rest));
Log::debug(sprintf('Found %s, return FALSE.', $rest));
return false;
}

View File

@@ -1,96 +0,0 @@
<?php
/**
* PwndVerifierV3.php
* Copyright (c) 2019 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Password;
use Exception;
use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException;
use Log;
use RuntimeException;
/**
* Class PwndVerifierV3
* @codeCoverageIgnore
* @codeCoverageIgnore
* @deprecated
*/
class PwndVerifierV3 implements Verifier
{
/**
* Verify the given password against (some) service.
*
* @param string $password
*
* @return bool
*/
public function validPassword(string $password): bool
{
Log::debug('Now in API v3.');
$hash = strtoupper(sha1($password));
$prefix = substr($hash, 0, 5);
$rest = substr($hash, 5);
$uri = sprintf('https://api.pwnedpasswords.com/%s/%s', 'range', $prefix);
Log::debug(sprintf('URI is %s', $uri));
$headers = [
'User-Agent' => sprintf('Firefly III v%s', config('firefly.version')),
];
Log::debug('Headers', $headers);
$opts = [
'headers' => $headers,
'timeout' => 5,
];
Log::debug(sprintf('hash prefix is %s', $prefix));
Log::debug(sprintf('rest is %s', $rest));
try {
$client = new Client;
$res = $client->request('GET', $uri, $opts);
} catch (GuzzleException|Exception $e) {
Log::error(sprintf('Could not verify password security: %s', $e->getMessage()));
return true;
}
Log::debug(sprintf('Status code returned is %d', $res->getStatusCode()));
if (404 === $res->getStatusCode()) {
return true;
}
$body = $res->getBody()->getContents();
try {
$strpos = stripos($body, $rest);
} catch (RuntimeException $e) {
Log::error(sprintf('Could not get body from Pwnd result: %s', $e->getMessage()));
$strpos = false;
}
if (false === $strpos) {
Log::debug(sprintf('%s was not found in result body. Return true.', $rest));
return true;
}
Log::debug(sprintf('Found %s, so return FALSE.', $rest));
return false;
}
}

View File

@@ -325,9 +325,11 @@ class Amount
*/
public function getLocaleInfo(): array
{
$locale = explode(',', (string) trans('config.locale'));
$locale = array_map('trim', $locale);
setlocale(LC_MONETARY, $locale);
// get config from preference, not from translation:
$locale = app('steam')->getLocale();
$array = app('steam')->getLocaleArray($locale);
setlocale(LC_MONETARY, $array);
$info = localeconv();
// correct variables
$info['n_cs_precedes'] = $this->getLocaleField($info, 'n_cs_precedes');

View File

@@ -101,8 +101,8 @@ class CacheProperties
{
$content = '';
foreach ($this->properties as $property) {
$content .= json_encode($property);
$content .= json_encode($property, JSON_THROW_ON_ERROR, 512);
}
$this->hash = substr(sha1($content), 0, 16);
$this->hash = substr(hash('sha256', $content), 0, 16);
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* AutoBudgetCronjob.php
* Copyright (c) 2020 thegrumpydictator@gmail.com

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* ExportDataGenerator.php
* Copyright (c) 2019 james@firefly-iii.org
@@ -556,7 +557,7 @@ class ExportDataGenerator
$recurrence->description,
$recurrence->first_date ? $recurrence->first_date->format('Y-m-d') : null,
$recurrence->repeat_until ? $recurrence->repeat_until->format('Y-m-d') : null,
$recurrence->latest_date ? $recurrence->repeat_until->format('Y-m-d') : null,
$recurrence->latest_date ? $recurrence->latest_date->format('Y-m-d') : null,
$recurrence->repetitions,
$recurrence->apply_rules,
$recurrence->active,
@@ -659,7 +660,7 @@ class ExportDataGenerator
$collector = app(GroupCollectorInterface::class);
$collector->setUser($this->user);
$collector->setRange($this->start, $this->end)->withAccountInformation()->withCategoryInformation()->withBillInformation()
->withBudgetInformation();
->withBudgetInformation()->withTagInformation();
$journals = $collector->getExtractedJournals();
$records = [];
@@ -689,8 +690,9 @@ class ExportDataGenerator
$journal['category_name'],
$journal['budget_name'],
$journal['bill_name'],
implode(',', $journal['tags']),
$this->mergeTags($journal['tags']),
];
}
//load the CSV document from a string
@@ -705,4 +707,22 @@ class ExportDataGenerator
return $csv->getContent(); //returns the CSV document as a string
}
/**
* @param array $tags
*
* @return string
*/
private function mergeTags(array $tags): string
{
if (0 === count($tags)) {
return '';
}
$smol = [];
foreach ($tags as $tag) {
$smol[] = $tag['name'];
}
return implode(',', $smol);
}
}

View File

@@ -61,6 +61,7 @@ trait ChartGeneration
return $cache->get(); // @codeCoverageIgnore
}
Log::debug('Regenerate chart.account.account-balance-chart from scratch.');
$locale = app('steam')->getLocale();
/** @var GeneratorInterface $generator */
$generator = app(GeneratorInterface::class);
@@ -89,7 +90,7 @@ trait ChartGeneration
$previous = array_values($range)[0];
while ($currentStart <= $end) {
$format = $currentStart->format('Y-m-d');
$label = $currentStart->formatLocalized((string)trans('config.month_and_day'));
$label = $currentStart->formatLocalized((string)trans('config.month_and_day', [], $locale));
$balance = isset($range[$format]) ? round($range[$format], 12) : $previous;
$previous = $balance;
$currentStart->addDay();

View File

@@ -119,19 +119,6 @@ trait RequestInformation
return '<p>' . trans('firefly.route_has_no_help') . '</p>'; // @codeCoverageIgnore
}
/**
* Get user's language.
*
* @return string
*/
protected function getLanguage(): string // get preference
{
/** @var string $language */
$language = app('preferences')->get('language', config('firefly.default_language', 'en_US'))->data;
return $language;
}
/**
* Get a list of triggers.
*
@@ -300,7 +287,7 @@ trait RequestInformation
$data,
[
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:6|secure_password|confirmed',
'password' => 'required|string|min:16|secure_password|confirmed',
]
);
}

View File

@@ -171,6 +171,9 @@ class StageImportDataHandler
$foreignCurrencyCode = $value;
Log::debug(sprintf('Foreign currency code is now %s', $value));
break;
case 'time':
// ignore time because it breaks the duplicate detector.
break;
default:
$notes .= $key . ': ' . $value . ' ' . "\n"; // for newline in Markdown.
}
@@ -180,30 +183,30 @@ class StageImportDataHandler
// transaction data:
'transactions' => [
[
'date' => $transaction->getMadeOn()->format('Y-m-d'),
'tags' => $tags,
'user' => $this->importJob->user_id,
'notes' => $notes,
'date' => $transaction->getMadeOn()->format('Y-m-d'),
'tags' => $tags,
'user' => $this->importJob->user_id,
'notes' => trim($notes),
// all custom fields:
'external_id' => (string)$transaction->getId(),
'external_id' => (string)$transaction->getId(),
// journal data:
'description' => $transaction->getDescription(),
'piggy_bank_id' => null,
'piggy_bank_name' => null,
'bill_id' => null,
'bill_name' => null,
'original-source' => sprintf('spectre-v%s', config('firefly.version')),
'type' => $type,
'currency_id' => null,
'currency_code' => $currencyCode,
'amount' => $amount,
'budget_id' => null,
'budget_name' => null,
'category_id' => null,
'category_name' => $transaction->getCategory(),
'source_id' => $source->id,
'description' => $transaction->getDescription(),
'piggy_bank_id' => null,
'piggy_bank_name' => null,
'bill_id' => null,
'bill_name' => null,
'original-source' => sprintf('spectre-v%s', config('firefly.version')),
'type' => $type,
'currency_id' => null,
'currency_code' => $currencyCode,
'amount' => $amount,
'budget_id' => null,
'budget_name' => null,
'category_id' => null,
'category_name' => $transaction->getCategory(),
'source_id' => $source->id,
'source_name' => null,
'destination_id' => $destination->id,
'destination_name' => null,

View File

@@ -287,10 +287,11 @@ class Navigation
*/
public function listOfPeriods(Carbon $start, Carbon $end): array
{
$locale = app('steam')->getLocale();
// define period to increment
$increment = 'addDay';
$format = $this->preferredCarbonFormat($start, $end);
$displayFormat = (string)trans('config.month_and_day');
$displayFormat = (string)trans('config.month_and_day', [], $locale);
// increment by month (for year)
if ($start->diffInMonths($end) > 1) {
$increment = 'addMonth';
@@ -391,13 +392,14 @@ class Navigation
*/
public function preferredCarbonLocalizedFormat(Carbon $start, Carbon $end): string
{
$format = (string)trans('config.month_and_day');
$locale = app('steam')->getLocale();
$format = (string)trans('config.month_and_day', [], $locale);
if ($start->diffInMonths($end) > 1) {
$format = (string)trans('config.month');
$format = (string)trans('config.month', [], $locale);
}
if ($start->diffInMonths($end) > 12) {
$format = (string)trans('config.year');
$format = (string)trans('config.year', [], $locale);
}
return $format;

View File

@@ -26,7 +26,6 @@ use Cache;
use Exception;
use FireflyIII\Models\Preference;
use FireflyIII\User;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Support\Collection;
use Log;
use Session;
@@ -200,7 +199,7 @@ class Preferences
$lastActivity = implode(',', $lastActivity);
}
return md5($lastActivity);
return hash('sha256', $lastActivity);
}
/**

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* AccountSearch.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* GenericSearchInterface.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* TransactionSearch.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* TransferSearch.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -70,11 +70,10 @@ class Steam
->where('transactions.transaction_currency_id', $currency->id)
->get(['transactions.amount'])->toArray();
$nativeBalance = $this->sumTransactions($transactions, 'amount');
// get all balances in foreign currency:
$transactions = $account->transactions()
->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id')
->where('transaction_journals.date', '<=', $date->format('Y-m-d'))
->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59'))
->where('transactions.foreign_currency_id', $currency->id)
->where('transactions.transaction_currency_id', '!=', $currency->id)
->get(['transactions.foreign_amount'])->toArray();
@@ -585,4 +584,42 @@ class Steam
return $amount;
}
/**
* Get user's language.
*
* @return string
*/
public function getLanguage(): string // get preference
{
return app('preferences')->get('language', config('firefly.default_language', 'en_US'))->data;
}
/**
* Get user's locale.
*
* @return string
*/
public function getLocale(): string // get preference
{
/** @var string $language */
$locale = app('preferences')->get('locale', config('firefly.default_locale', 'equal'))->data;
if ('equal' === $locale) {
return $this->getLanguage();
}
return $locale;
}
/**
* @param string $locale
*
* @return array
*/
public function getLocaleArray(string $locale): array {
return [
sprintf('%s.utf8', $locale),
sprintf('%s.UTF-8', $locale),
];
}
}

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* OAuthKeys.php
* Copyright (c) 2019 james@firefly-iii.org

View File

@@ -1,4 +1,5 @@
<?php
declare(strict_types=1);
/**
* Telemetry.php
* Copyright (c) 2020 thegrumpydictator@gmail.com

View File

@@ -73,7 +73,7 @@ class SetSourceAccount implements ActionInterface
$type = $journal->transactionType->type;
// if this is a transfer or a withdrawal, the new source account must be an asset account or a default account, and it MUST exist:
if ((TransactionType::WITHDRAWAL === $type || TransactionType::TRANSFER === $type) && !$this->findAssetAccount()) {
if ((TransactionType::WITHDRAWAL === $type || TransactionType::TRANSFER === $type) && !$this->findAssetAccount($type)) {
Log::error(
sprintf(
'Cannot change source account of journal #%d because no asset account with name "%s" exists.',
@@ -119,6 +119,10 @@ class SetSourceAccount implements ActionInterface
{
// switch on type:
$allowed = config(sprintf('firefly.expected_source_types.source.%s', $type));
$allowed = is_array($allowed) ? $allowed : [];
Log::debug(sprintf('Check config for expected_source_types.source.%s, result is', $type), $allowed);
$account = $this->repository->findByName($this->action->action_value, $allowed);
if (null === $account) {

View File

@@ -138,6 +138,10 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @property-read int|null $transactions_count
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\User whereMfaSecret($value)
* @method static \Illuminate\Database\Eloquent\Builder|\FireflyIII\User whereObjectguid($value)
* @property string $password
* @property bool $blocked
* @property string|null $blocked_code
* @property-read \Illuminate\Database\Eloquent\Collection|\FireflyIII\Models\Role[] $roles
*/
class User extends Authenticatable
{

View File

@@ -73,8 +73,8 @@ trait TransactionValidation
// validate source account.
$sourceId = isset($transaction['source_id']) ? (int) $transaction['source_id'] : null;
$sourceName = $transaction['source_name'] ?? null;
$sourceIban = $transaction['source_iban'] ?? null;
$sourceName = isset($transaction['source_name']) ? (string) $transaction['source_name'] : null;
$sourceIban = isset($transaction['source_iban']) ? (string) $transaction['source_iban'] : null;
$validSource = $accountValidator->validateSource($sourceId, $sourceName, $sourceIban);
// do something with result:
@@ -86,8 +86,8 @@ trait TransactionValidation
}
// validate destination account
$destinationId = isset($transaction['destination_id']) ? (int) $transaction['destination_id'] : null;
$destinationName = $transaction['destination_name'] ?? null;
$destinationIban = $transaction['destination_iban'] ?? null;
$destinationName = isset($transaction['destination_name']) ? (string) $transaction['destination_name'] : null;
$destinationIban = isset($transaction['destination_iban']) ? (string) $transaction['destination_iban'] : null;
$validDestination = $accountValidator->validateDestination($destinationId, $destinationName, $destinationIban);
// do something with result:
if (false === $validDestination) {

View File

@@ -2,8 +2,47 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).
## [5.2.4 (API 1.1.0)] - 2020-04-26
## [5.2.0 (API 1.1.0)] - 2020-xx-xx
### Fixed
- [Issue 3287](https://github.com/firefly-iii/firefly-iii/issues/3287) Locale issue
- [Issue 3251](https://github.com/firefly-iii/firefly-iii/issues/3251) Budget order
## [5.2.3 (API 1.1.0)] - 2020-04-22
### Added
- Support for British English! 🇬🇧
- You can set your locale *and* your language now.
### Changed
- [Issue 3270](https://github.com/firefly-iii/firefly-iii/issues/3270) Wrong average in budget table.
### Fixed
- [Issue 3264](https://github.com/firefly-iii/firefly-iii/issues/3264) Error when exporting recurring transactions
- [Issue 3272](https://github.com/firefly-iii/firefly-iii/issues/3272) Rule issue when using "set source account" action.
- [Issue 3281](https://github.com/firefly-iii/firefly-iii/issues/3281) Bad markdown parsing in piggy banks.
- [Issue 3284](https://github.com/firefly-iii/firefly-iii/issues/3284) Recurring transactions with bad info couldn't be rendered.
## [5.2.2 (API 1.1.0)] - 2020-04-14
### Fixed
- [Issue 3529](https://github.com/firefly-iii/firefly-iii/issues/3529) Issue with rule execution.
- [Issue 3263](https://github.com/firefly-iii/firefly-iii/issues/3263) Issue with new user account creation.
## [5.2.2 (API 1.1.0)] - 2020-04-13
### Fixed
- Virtual balance would always be stored as "0.0" despite the field being nullable.
- The rule action "set source account" was improperly configured.
## [5.2.1 (API 1.1.0)] - 2020-04-10
Firefly III 5.2.1 fixes an issue with charts and allows users to store budgets again.
## [5.2.0 (API 1.1.0)] - 2020-04-10
- ⚠️ This will be the last version to support PHP version 7.3. The next release will require PHP **7.4**
- ⚠️ The bunq and CSV import routines have been disabled and replaced by their stand alone variants: [bunq](https://github.com/firefly-iii/bunq-importer), [CSV](https://github.com/firefly-iii/csv-importer).
This release was preceded by a number of test versions:
@@ -28,6 +67,7 @@ This release was preceded by a number of test versions:
- [Issue 2997](https://github.com/firefly-iii/firefly-iii/issues/2997) The tag list has categories.
- [Issue 3122](https://github.com/firefly-iii/firefly-iii/issues/3122) Buttons on the top of lists.
- The Docker maximum file attachment size has been increased to 64M.
- The CSV file importer has been disabled. Find the [new CSV importer on GitHub](https://github.com/firefly-iii/csv-importer).
### Fixed
- [Issue 3154](https://github.com/firefly-iii/firefly-iii/issues/3154) `bcadd()` problems for users who were already running PHP7.4.
@@ -36,13 +76,14 @@ This release was preceded by a number of test versions:
- [Issue 3202](https://github.com/firefly-iii/firefly-iii/issues/3202) A bug in the frontpage budget chart is fixed.
- [Issue 3203](https://github.com/firefly-iii/firefly-iii/issues/3203) Firefly III won't complain when using a locale that uses comma's as decimal separators.
- [Issue 3212](https://github.com/firefly-iii/firefly-iii/issues/3212) Issue with ING imports.
- [Issue 3210](https://github.com/firefly-iii/firefly-iii/issues/3210) Could not create rule based on a transaction from a dropdown menu.
- [Issue 3210](https://github.com/firefly-iii/firefly-iii/issues/3210) Could not create rule based on a transaction from a dropdown menu.
- [Issue 3234](https://github.com/firefly-iii/firefly-iii/issues/3234) Export didn't export tags.
### API
- [Issue 2828](https://github.com/firefly-iii/firefly-iii/issues/2828) Appropriate endpoints for new transaction possibilities.
- [Issue 2958](https://github.com/firefly-iii/firefly-iii/issues/2958) A new default currency endpoint.
## [5.1.1 (API 1.0.2)] - 2020-03-xx
## [5.1.1 (API 1.0.2)] - 2020-03-13
### Added
- [Issue 2672](https://github.com/firefly-iii/firefly-iii/issues/2672) Buttons to create transactions from the list of accounts is back.
@@ -2214,4 +2255,4 @@ An intermediate release because something in the Twig and Twigbridge libraries i
- Initial release.
### API
- Initial release
- Initial release

528
composer.lock generated

File diff suppressed because it is too large Load Diff

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