diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index ae69e9a77f..c6699d24e3 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -59,6 +59,48 @@ class ResetPasswordController extends Controller $this->middleware('guest'); } + /** + * Reset the given user's password. + * + * @param \Illuminate\Http\Request $request + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse + * @throws \Illuminate\Validation\ValidationException + */ + public function reset(Request $request) + { + $loginProvider = config('firefly.login_provider'); + if ('eloquent' !== $loginProvider) { + $message = sprintf('Cannot reset password when authenticating over "%s".', $loginProvider); + + return view('error', compact('message')); + } + + $rules = [ + 'token' => 'required', + 'email' => 'required|email', + 'password' => 'required|confirmed|min:6|secure_password', + ]; + + $this->validate($request, $rules, $this->validationErrorMessages()); + + // Here we will attempt to reset the user's password. If it is successful we + // will update the password on an actual user model and persist it to the + // database. Otherwise we will parse the error and return the response. + $response = $this->broker()->reset( + $this->credentials($request), function ($user, $password) { + $this->resetPassword($user, $password); + } + ); + + // If the password was successfully reset, we will redirect the user back to + // the application's home authenticated view. If there is an error we can + // redirect them back to where they came from with their error message. + return $response === Password::PASSWORD_RESET + ? $this->sendResetResponse($request, $response) + : $this->sendResetFailedResponse($request, $response); + } + /** * Display the password reset view for the given token. * @@ -89,57 +131,7 @@ class ResetPasswordController extends Controller /** @noinspection PhpUndefinedFieldInspection */ return view('auth.passwords.reset')->with( - ['token' => $token, 'email' => $request->email, 'allowRegistration' => $allowRegistration,'pageTitle' => $pageTitle] + ['token' => $token, 'email' => $request->email, 'allowRegistration' => $allowRegistration, 'pageTitle' => $pageTitle] ); } - - /** - * Reset the given user's password. - * - * @param \Illuminate\Http\Request $request - * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Http\JsonResponse - * @throws \Illuminate\Validation\ValidationException - */ - public function reset(Request $request) - { - $loginProvider = config('firefly.login_provider'); - if ('eloquent' !== $loginProvider) { - $message = sprintf('Cannot reset password when authenticating over "%s".', $loginProvider); - - return view('error', compact('message')); - } - - $this->validate($request, $this->rules(), $this->validationErrorMessages()); - - // Here we will attempt to reset the user's password. If it is successful we - // will update the password on an actual user model and persist it to the - // database. Otherwise we will parse the error and return the response. - $response = $this->broker()->reset( - $this->credentials($request), function ($user, $password) { - $this->resetPassword($user, $password); - } - ); - - // If the password was successfully reset, we will redirect the user back to - // the application's home authenticated view. If there is an error we can - // redirect them back to where they came from with their error message. - return $response === Password::PASSWORD_RESET - ? $this->sendResetResponse($request, $response) - : $this->sendResetFailedResponse($request, $response); - } - - /** - * Get the password reset validation rules. - * - * @return array - */ - protected function rules() - { - return [ - 'token' => 'required', - 'email' => 'required|email', - 'password' => 'required|confirmed|min:6|secure_password', - ]; - } } diff --git a/app/Http/Controllers/Budget/ShowController.php b/app/Http/Controllers/Budget/ShowController.php index 170cf4ec19..0c136764f9 100644 --- a/app/Http/Controllers/Budget/ShowController.php +++ b/app/Http/Controllers/Budget/ShowController.php @@ -31,12 +31,10 @@ use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Budget; use FireflyIII\Models\BudgetLimit; use FireflyIII\Models\TransactionType; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; -use FireflyIII\Support\CacheProperties; +use FireflyIII\Support\Http\Controllers\AugumentData; use FireflyIII\Support\Http\Controllers\PeriodOverview; use Illuminate\Http\Request; -use Illuminate\Support\Collection; /** * @@ -44,10 +42,7 @@ use Illuminate\Support\Collection; */ class ShowController extends Controller { - use PeriodOverview; - - /** @var BudgetRepositoryInterface The budget repository */ - private $repository; + use PeriodOverview, AugumentData; /** * ShowController constructor. @@ -62,7 +57,6 @@ class ShowController extends Controller function ($request, $next) { app('view')->share('title', (string)trans('firefly.budgets')); app('view')->share('mainTitleIcon', 'fa-tasks'); - $this->repository = app(BudgetRepositoryInterface::class); return $next($request); } @@ -203,39 +197,4 @@ class ShowController extends Controller return view('budgets.show', compact('limits', 'budget', 'budgetLimit', 'transactions', 'subTitle')); } - - /** - * Gets all budget limits for a budget. - * - * @param Budget $budget - * @param Carbon $start - * @param Carbon $end - * - * @return Collection - */ - protected function getLimits(Budget $budget, Carbon $start, Carbon $end): Collection // get data + augment with info - { - // properties for cache - $cache = new CacheProperties; - $cache->addProperty($start); - $cache->addProperty($end); - $cache->addProperty($budget->id); - $cache->addProperty('get-limits'); - - if ($cache->has()) { - return $cache->get(); // @codeCoverageIgnore - } - - $set = $this->repository->getBudgetLimits($budget, $start, $end); - $limits = new Collection(); - - /** @var BudgetLimit $entry */ - foreach ($set as $entry) { - $entry->spent = $this->repository->spentInPeriod(new Collection([$budget]), new Collection(), $entry->start_date, $entry->end_date); - $limits->push($entry); - } - $cache->store($limits); - - return $set; - } } diff --git a/app/Http/Controllers/Category/NoCategoryController.php b/app/Http/Controllers/Category/NoCategoryController.php index a38fcf0c55..8dbc24f45f 100644 --- a/app/Http/Controllers/Category/NoCategoryController.php +++ b/app/Http/Controllers/Category/NoCategoryController.php @@ -30,7 +30,7 @@ use FireflyIII\Helpers\Filter\InternalTransferFilter; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; -use FireflyIII\Support\CacheProperties; +use FireflyIII\Support\Http\Controllers\PeriodOverview; use Illuminate\Http\Request; use Illuminate\Support\Collection; use Log; @@ -41,7 +41,7 @@ use Log; */ class NoCategoryController extends Controller { - + use PeriodOverview; /** @var JournalRepositoryInterface Journals and transactions overview */ private $journalRepos; @@ -135,92 +135,4 @@ class NoCategoryController extends Controller return view('categories.no-category', compact('transactions', 'subTitle', 'periods', 'start', 'end')); } - - - /** - * Show period overview for no category view. - * - * @param Carbon $theDate - * - * @return Collection - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - protected function getNoCategoryPeriodOverview(Carbon $theDate): Collection // period overview method. - { - Log::debug(sprintf('Now in getNoCategoryPeriodOverview(%s)', $theDate->format('Y-m-d'))); - $range = app('preferences')->get('viewRange', '1M')->data; - $first = $this->journalRepos->firstNull(); - $start = null === $first ? new Carbon : $first->date; - $end = $theDate ?? new Carbon; - - Log::debug(sprintf('Start for getNoCategoryPeriodOverview() is %s', $start->format('Y-m-d'))); - Log::debug(sprintf('End for getNoCategoryPeriodOverview() is %s', $end->format('Y-m-d'))); - - // properties for cache - $cache = new CacheProperties; - $cache->addProperty($start); - $cache->addProperty($end); - $cache->addProperty('no-category-period-entries'); - - if ($cache->has()) { - return $cache->get(); // @codeCoverageIgnore - } - - $dates = app('navigation')->blockPeriods($start, $end, $range); - $entries = new Collection; - - foreach ($dates as $date) { - - // count journals without category in this period: - /** @var TransactionCollectorInterface $collector */ - $collector = app(TransactionCollectorInterface::class); - $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory() - ->withOpposingAccount()->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]); - $collector->removeFilter(InternalTransferFilter::class); - $count = $collector->getTransactions()->count(); - - // amount transferred - /** @var TransactionCollectorInterface $collector */ - $collector = app(TransactionCollectorInterface::class); - $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory() - ->withOpposingAccount()->setTypes([TransactionType::TRANSFER]); - $collector->removeFilter(InternalTransferFilter::class); - $transferred = app('steam')->positive((string)$collector->getTransactions()->sum('transaction_amount')); - - // amount spent - /** @var TransactionCollectorInterface $collector */ - $collector = app(TransactionCollectorInterface::class); - $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory()->withOpposingAccount()->setTypes( - [TransactionType::WITHDRAWAL] - ); - $spent = $collector->getTransactions()->sum('transaction_amount'); - - // amount earned - /** @var TransactionCollectorInterface $collector */ - $collector = app(TransactionCollectorInterface::class); - $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory()->withOpposingAccount()->setTypes( - [TransactionType::DEPOSIT] - ); - $earned = $collector->getTransactions()->sum('transaction_amount'); - /** @noinspection PhpUndefinedMethodInspection */ - $dateStr = $date['end']->format('Y-m-d'); - $dateName = app('navigation')->periodShow($date['end'], $date['period']); - $entries->push( - [ - 'string' => $dateStr, - 'name' => $dateName, - 'count' => $count, - 'spent' => $spent, - 'earned' => $earned, - 'transferred' => $transferred, - 'start' => clone $date['start'], - 'end' => clone $date['end'], - ] - ); - } - Log::debug('End of loops'); - $cache->store($entries); - - return $entries; - } } diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index 498d60fd75..33b24f0596 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -35,6 +35,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\CacheProperties; use FireflyIII\Support\Http\Controllers\AugumentData; +use FireflyIII\Support\Http\Controllers\ChartGeneration; use FireflyIII\Support\Http\Controllers\DateCalculation; use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; @@ -49,7 +50,7 @@ use Log; */ class AccountController extends Controller { - use DateCalculation, AugumentData; + use DateCalculation, AugumentData, ChartGeneration; /** @var GeneratorInterface Chart generation methods. */ protected $generator; @@ -604,103 +605,4 @@ class AccountController extends Controller return response()->json($data); } - - - /** - * Shows an overview of the account balances for a set of accounts. - * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end - * - * @return array - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - protected function accountBalanceChart(Collection $accounts, Carbon $start, Carbon $end): array // chart helper method. - { - // chart properties for cache: - $cache = new CacheProperties(); - $cache->addProperty($start); - $cache->addProperty($end); - $cache->addProperty('chart.account.account-balance-chart'); - $cache->addProperty($accounts); - if ($cache->has()) { - return $cache->get(); // @codeCoverageIgnore - } - Log::debug('Regenerate chart.account.account-balance-chart from scratch.'); - - /** @var CurrencyRepositoryInterface $repository */ - $repository = app(CurrencyRepositoryInterface::class); - /** @var AccountRepositoryInterface $accountRepos */ - $accountRepos = app(AccountRepositoryInterface::class); - - $default = app('amount')->getDefaultCurrency(); - $chartData = []; - /** @var Account $account */ - foreach ($accounts as $account) { - $currency = $repository->findNull((int)$accountRepos->getMetaValue($account, 'currency_id')); - if (null === $currency) { - $currency = $default; - } - $currentSet = [ - 'label' => $account->name, - 'currency_symbol' => $currency->symbol, - 'entries' => [], - ]; - - $currentStart = clone $start; - $range = app('steam')->balanceInRange($account, $start, clone $end); - $previous = array_values($range)[0]; - while ($currentStart <= $end) { - $format = $currentStart->format('Y-m-d'); - $label = $currentStart->formatLocalized((string)trans('config.month_and_day')); - $balance = isset($range[$format]) ? round($range[$format], 12) : $previous; - $previous = $balance; - $currentStart->addDay(); - $currentSet['entries'][$label] = $balance; - } - $chartData[] = $currentSet; - } - $data = $this->generator->multiSet($chartData); - $cache->store($data); - - return $data; - } - - /** - * Small helper function for the revenue and expense account charts. - * - * @param array $names - * - * @return array - */ - private function expandNames(array $names): array - { - $result = []; - foreach ($names as $entry) { - $result[$entry['name']] = 0; - } - - return $result; - } - - /** - * Small helper function for the revenue and expense account charts. - * - * @param Collection $accounts - * - * @return array - */ - private function extractNames(Collection $accounts): array - { - $return = []; - /** @var Account $account */ - foreach ($accounts as $account) { - $return[$account->id] = $account->name; - } - - return $return; - } } diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php index f87a00efa5..01fe25a965 100644 --- a/app/Http/Controllers/Chart/CategoryController.php +++ b/app/Http/Controllers/Chart/CategoryController.php @@ -32,6 +32,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\CacheProperties; +use FireflyIII\Support\Http\Controllers\AugumentData; use FireflyIII\Support\Http\Controllers\DateCalculation; use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; @@ -42,7 +43,7 @@ use Log; */ class CategoryController extends Controller { - use DateCalculation; + use DateCalculation, AugumentData; /** @var GeneratorInterface Chart generation methods. */ protected $generator; @@ -479,21 +480,4 @@ class CategoryController extends Controller return $data; } - - /** - * Small helper function for the revenue and expense account charts. - * - * @param array $names - * - * @return array - */ - private function expandNames(array $names): array - { - $result = []; - foreach ($names as $entry) { - $result[$entry['name']] = 0; - } - - return $result; - } } diff --git a/app/Http/Controllers/Json/AutoCompleteController.php b/app/Http/Controllers/Json/AutoCompleteController.php index dbd993aedd..635e9d262a 100644 --- a/app/Http/Controllers/Json/AutoCompleteController.php +++ b/app/Http/Controllers/Json/AutoCompleteController.php @@ -25,20 +25,12 @@ namespace FireflyIII\Http\Controllers\Json; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\TransactionCollectorInterface; use FireflyIII\Http\Controllers\Controller; -use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\TransactionJournal; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\Bill\BillRepositoryInterface; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\Repositories\Category\CategoryRepositoryInterface; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use FireflyIII\Repositories\Journal\JournalRepositoryInterface; -use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Support\CacheProperties; +use FireflyIII\Support\Http\Controllers\AutoCompleteCollector; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Support\Collection; /** * Class AutoCompleteController. @@ -47,6 +39,7 @@ use Illuminate\Support\Collection; */ class AutoCompleteController extends Controller { + use AutoCompleteCollector; /** * List of all journals. @@ -203,7 +196,8 @@ class AutoCompleteController extends Controller $return = array_filter( $return, function (array $array) use ($search) { $haystack = $array['name']; - $result = stripos($haystack, $search); + $result = stripos($haystack, $search); + return !(false === $result); } ); @@ -257,121 +251,4 @@ class AutoCompleteController extends Controller return response()->json($return); } - - /** - * @param array $unfiltered - * @param string $query - * - * @return array|null - */ - private function filterResult(?array $unfiltered, string $query): ?array - { - if (null === $unfiltered) { - return null; // @codeCoverageIgnore - } - if ('' === $query) { - sort($unfiltered); - - return $unfiltered; - } - $return = []; - if ('' !== $query) { - $return = array_values( - array_filter( - $unfiltered, function (string $value) use ($query) { - return !(false === stripos($value, $query)); - }, ARRAY_FILTER_USE_BOTH - ) - ); - } - sort($return); - - - return $return; - } - - /** - * @param string $query - * @param array $types - * - * @return array - */ - private function getAccounts(array $types): array - { - $repository = app(AccountRepositoryInterface::class); - // find everything: - /** @var Collection $collection */ - $collection = $repository->getAccountsByType($types); - $filtered = $collection->filter( - function (Account $account) { - return $account->active === true; - } - ); - $return = array_values(array_unique($filtered->pluck('name')->toArray())); - - return $return; - - } - - /** - * @return array - */ - private function getBills(): array - { - $repository = app(BillRepositoryInterface::class); - - return array_unique($repository->getActiveBills()->pluck('name')->toArray()); - } - - /** - * @return array - */ - private function getBudgets(): array - { - $repository = app(BudgetRepositoryInterface::class); - - return array_unique($repository->getBudgets()->pluck('name')->toArray()); - } - - /** - * @return array - */ - private function getCategories(): array - { - $repository = app(CategoryRepositoryInterface::class); - - return array_unique($repository->getCategories()->pluck('name')->toArray()); - } - - /** - * @return array - */ - private function getCurrencyNames(): array - { - /** @var CurrencyRepositoryInterface $repository */ - $repository = app(CurrencyRepositoryInterface::class); - - return $repository->get()->pluck('name')->toArray(); - } - - /** - * @return array - */ - private function getTags(): array - { - /** @var TagRepositoryInterface $repository */ - $repository = app(TagRepositoryInterface::class); - - return array_unique($repository->get()->pluck('tag')->toArray()); - } - - /** - * @return array - */ - private function getTransactionTypes(): array - { - $repository = app(JournalRepositoryInterface::class); - - return array_unique($repository->getTransactionTypes()->pluck('type')->toArray()); - } } diff --git a/app/Http/Controllers/System/CronController.php b/app/Http/Controllers/System/CronController.php index 33e57aa517..d38c2f5987 100644 --- a/app/Http/Controllers/System/CronController.php +++ b/app/Http/Controllers/System/CronController.php @@ -23,14 +23,15 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\System; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Support\Cronjobs\RecurringCronjob; +use FireflyIII\Support\Http\Controllers\CronRunner; /** * Class CronController */ class CronController { + use CronRunner; + /** * @param string $token * @@ -43,24 +44,4 @@ class CronController return implode("
\n", $results); } - - /** - * @return string - */ - private function runRecurring(): string - { - /** @var RecurringCronjob $recurring */ - $recurring = app(RecurringCronjob::class); - try { - $result = $recurring->fire(); - } catch (FireflyException $e) { - return $e->getMessage(); - } - if (false === $result) { - return 'The recurring transaction cron job did not fire.'; - } - - return 'The recurring transaction cron job fired successfully.'; - } - -} \ No newline at end of file +} diff --git a/app/Support/Http/Controllers/AugumentData.php b/app/Support/Http/Controllers/AugumentData.php index bd014b77c1..6776c8532c 100644 --- a/app/Support/Http/Controllers/AugumentData.php +++ b/app/Support/Http/Controllers/AugumentData.php @@ -33,6 +33,7 @@ use FireflyIII\Models\Transaction; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; +use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; /** @@ -68,6 +69,41 @@ trait AugumentData return $combined; } + /** + * Small helper function for the revenue and expense account charts. + * + * @param array $names + * + * @return array + */ + protected function expandNames(array $names): array + { + $result = []; + foreach ($names as $entry) { + $result[$entry['name']] = 0; + } + + return $result; + } + + /** + * Small helper function for the revenue and expense account charts. + * + * @param Collection $accounts + * + * @return array + */ + protected function extractNames(Collection $accounts): array + { + $return = []; + /** @var Account $account */ + foreach ($accounts as $account) { + $return[$account->id] = $account->name; + } + + return $return; + } + /** * Returns the budget limits belonging to the given budget and valid on the given day. * @@ -168,6 +204,43 @@ trait AugumentData return $return; } + /** + * Gets all budget limits for a budget. + * + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + protected function getLimits(Budget $budget, Carbon $start, Carbon $end): Collection // get data + augment with info + { + /** @var BudgetRepositoryInterface $repository */ + $repository = app(BudgetRepositoryInterface::class); + // properties for cache + $cache = new CacheProperties; + $cache->addProperty($start); + $cache->addProperty($end); + $cache->addProperty($budget->id); + $cache->addProperty('get-limits'); + + if ($cache->has()) { + return $cache->get(); // @codeCoverageIgnore + } + + $set = $repository->getBudgetLimits($budget, $start, $end); + $limits = new Collection(); + + /** @var BudgetLimit $entry */ + foreach ($set as $entry) { + $entry->spent = $repository->spentInPeriod(new Collection([$budget]), new Collection(), $entry->start_date, $entry->end_date); + $limits->push($entry); + } + $cache->store($limits); + + return $set; + } + /** * Helper function that groups expenses. * @@ -260,4 +333,4 @@ trait AugumentData return $grouped; } -} \ No newline at end of file +} diff --git a/app/Support/Http/Controllers/AutoCompleteCollector.php b/app/Support/Http/Controllers/AutoCompleteCollector.php new file mode 100644 index 0000000000..719640f082 --- /dev/null +++ b/app/Support/Http/Controllers/AutoCompleteCollector.php @@ -0,0 +1,155 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Support\Http\Controllers; + +use FireflyIII\Models\Account; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use FireflyIII\Repositories\Category\CategoryRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\Tag\TagRepositoryInterface; +use Illuminate\Support\Collection; + +/** + * Trait AutoCompleteCollector + */ +trait AutoCompleteCollector +{ + + /** + * @param array $unfiltered + * @param string $query + * + * @return array|null + */ + protected function filterResult(?array $unfiltered, string $query): ?array + { + if (null === $unfiltered) { + return null; // @codeCoverageIgnore + } + if ('' === $query) { + sort($unfiltered); + + return $unfiltered; + } + $return = []; + if ('' !== $query) { + $return = array_values( + array_filter( + $unfiltered, function (string $value) use ($query) { + return !(false === stripos($value, $query)); + }, ARRAY_FILTER_USE_BOTH + ) + ); + } + sort($return); + + + return $return; + } + + /** + * @param array $types + * + * @return array + */ + protected function getAccounts(array $types): array + { + $repository = app(AccountRepositoryInterface::class); + // find everything: + /** @var Collection $collection */ + $collection = $repository->getAccountsByType($types); + $filtered = $collection->filter( + function (Account $account) { + return true === $account->active; + } + ); + + return array_values(array_unique($filtered->pluck('name')->toArray())); + } + + /** + * @return array + */ + protected function getBills(): array + { + $repository = app(BillRepositoryInterface::class); + + return array_unique($repository->getActiveBills()->pluck('name')->toArray()); + } + + /** + * @return array + */ + protected function getBudgets(): array + { + $repository = app(BudgetRepositoryInterface::class); + + return array_unique($repository->getBudgets()->pluck('name')->toArray()); + } + + /** + * @return array + */ + protected function getCategories(): array + { + $repository = app(CategoryRepositoryInterface::class); + + return array_unique($repository->getCategories()->pluck('name')->toArray()); + } + + /** + * @return array + */ + protected function getCurrencyNames(): array + { + /** @var CurrencyRepositoryInterface $repository */ + $repository = app(CurrencyRepositoryInterface::class); + + return $repository->get()->pluck('name')->toArray(); + } + + /** + * @return array + */ + protected function getTags(): array + { + /** @var TagRepositoryInterface $repository */ + $repository = app(TagRepositoryInterface::class); + + return array_unique($repository->get()->pluck('tag')->toArray()); + } + + /** + * @return array + */ + protected function getTransactionTypes(): array + { + $repository = app(JournalRepositoryInterface::class); + + return array_unique($repository->getTransactionTypes()->pluck('type')->toArray()); + } +} diff --git a/app/Support/Http/Controllers/ChartGeneration.php b/app/Support/Http/Controllers/ChartGeneration.php new file mode 100644 index 0000000000..06a9937351 --- /dev/null +++ b/app/Support/Http/Controllers/ChartGeneration.php @@ -0,0 +1,106 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Support\Http\Controllers; + +use Carbon\Carbon; +use FireflyIII\Generator\Chart\Basic\GeneratorInterface; +use FireflyIII\Models\Account; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Support\CacheProperties; +use Illuminate\Support\Collection; +use Log; + +/** + * Trait ChartGeneration + */ +trait ChartGeneration +{ + /** + * Shows an overview of the account balances for a set of accounts. + * + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * + * @return array + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + protected function accountBalanceChart(Collection $accounts, Carbon $start, Carbon $end): array // chart helper method. + { + + // chart properties for cache: + $cache = new CacheProperties(); + $cache->addProperty($start); + $cache->addProperty($end); + $cache->addProperty('chart.account.account-balance-chart'); + $cache->addProperty($accounts); + if ($cache->has()) { + return $cache->get(); // @codeCoverageIgnore + } + Log::debug('Regenerate chart.account.account-balance-chart from scratch.'); + /** @var GeneratorInterface $generator */ + $generator = app(GeneratorInterface::class); + + /** @var CurrencyRepositoryInterface $repository */ + $repository = app(CurrencyRepositoryInterface::class); + /** @var AccountRepositoryInterface $accountRepos */ + $accountRepos = app(AccountRepositoryInterface::class); + + $default = app('amount')->getDefaultCurrency(); + $chartData = []; + /** @var Account $account */ + foreach ($accounts as $account) { + $currency = $repository->findNull((int)$accountRepos->getMetaValue($account, 'currency_id')); + if (null === $currency) { + $currency = $default; + } + $currentSet = [ + 'label' => $account->name, + 'currency_symbol' => $currency->symbol, + 'entries' => [], + ]; + + $currentStart = clone $start; + $range = app('steam')->balanceInRange($account, $start, clone $end); + $previous = array_values($range)[0]; + while ($currentStart <= $end) { + $format = $currentStart->format('Y-m-d'); + $label = $currentStart->formatLocalized((string)trans('config.month_and_day')); + $balance = isset($range[$format]) ? round($range[$format], 12) : $previous; + $previous = $balance; + $currentStart->addDay(); + $currentSet['entries'][$label] = $balance; + } + $chartData[] = $currentSet; + } + $data = $generator->multiSet($chartData); + $cache->store($data); + + return $data; + } + +} \ No newline at end of file diff --git a/app/Support/Http/Controllers/CronRunner.php b/app/Support/Http/Controllers/CronRunner.php new file mode 100644 index 0000000000..3bbb3d34c0 --- /dev/null +++ b/app/Support/Http/Controllers/CronRunner.php @@ -0,0 +1,53 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Support\Http\Controllers; + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Support\Cronjobs\RecurringCronjob; + +/** + * Trait CronRunner + */ +trait CronRunner +{ + /** + * @return string + */ + protected function runRecurring(): string + { + /** @var RecurringCronjob $recurring */ + $recurring = app(RecurringCronjob::class); + try { + $result = $recurring->fire(); + } catch (FireflyException $e) { + return $e->getMessage(); + } + if (false === $result) { + return 'The recurring transaction cron job did not fire.'; + } + + return 'The recurring transaction cron job fired successfully.'; + } + +} diff --git a/app/Support/Http/Controllers/PeriodOverview.php b/app/Support/Http/Controllers/PeriodOverview.php index dc2d55bc8a..16251024e9 100644 --- a/app/Support/Http/Controllers/PeriodOverview.php +++ b/app/Support/Http/Controllers/PeriodOverview.php @@ -38,10 +38,13 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; +use Log; /** * Trait PeriodOverview. * + * TODO verify this all works as expected. + * * - Group expenses, income, etc. under this period. * - Returns collection of arrays. Possible fields are: * - start (string), @@ -55,6 +58,7 @@ use Illuminate\Support\Collection; */ trait PeriodOverview { + /** * This method returns "period entries", so nov-2015, dec-2015, etc etc (this depends on the users session range) * and for each period, the amount of money spent and earned. This is a complex operation which is cached for @@ -255,6 +259,95 @@ trait PeriodOverview return $entries; } + /** + * TODO has to be synced with the others. + * + * Show period overview for no category view. + * + * @param Carbon $theDate + * + * @return Collection + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ + protected function getNoCategoryPeriodOverview(Carbon $theDate): Collection // period overview method. + { + Log::debug(sprintf('Now in getNoCategoryPeriodOverview(%s)', $theDate->format('Y-m-d'))); + $range = app('preferences')->get('viewRange', '1M')->data; + $first = $this->journalRepos->firstNull(); + $start = null === $first ? new Carbon : $first->date; + $end = $theDate ?? new Carbon; + + Log::debug(sprintf('Start for getNoCategoryPeriodOverview() is %s', $start->format('Y-m-d'))); + Log::debug(sprintf('End for getNoCategoryPeriodOverview() is %s', $end->format('Y-m-d'))); + + // properties for cache + $cache = new CacheProperties; + $cache->addProperty($start); + $cache->addProperty($end); + $cache->addProperty('no-category-period-entries'); + + if ($cache->has()) { + return $cache->get(); // @codeCoverageIgnore + } + + $dates = app('navigation')->blockPeriods($start, $end, $range); + $entries = new Collection; + + foreach ($dates as $date) { + + // count journals without category in this period: + /** @var TransactionCollectorInterface $collector */ + $collector = app(TransactionCollectorInterface::class); + $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory() + ->withOpposingAccount()->setTypes([TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER]); + $collector->removeFilter(InternalTransferFilter::class); + $count = $collector->getTransactions()->count(); + + // amount transferred + /** @var TransactionCollectorInterface $collector */ + $collector = app(TransactionCollectorInterface::class); + $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory() + ->withOpposingAccount()->setTypes([TransactionType::TRANSFER]); + $collector->removeFilter(InternalTransferFilter::class); + $transferred = app('steam')->positive((string)$collector->getTransactions()->sum('transaction_amount')); + + // amount spent + /** @var TransactionCollectorInterface $collector */ + $collector = app(TransactionCollectorInterface::class); + $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory()->withOpposingAccount()->setTypes( + [TransactionType::WITHDRAWAL] + ); + $spent = $collector->getTransactions()->sum('transaction_amount'); + + // amount earned + /** @var TransactionCollectorInterface $collector */ + $collector = app(TransactionCollectorInterface::class); + $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory()->withOpposingAccount()->setTypes( + [TransactionType::DEPOSIT] + ); + $earned = $collector->getTransactions()->sum('transaction_amount'); + /** @noinspection PhpUndefinedMethodInspection */ + $dateStr = $date['end']->format('Y-m-d'); + $dateName = app('navigation')->periodShow($date['end'], $date['period']); + $entries->push( + [ + 'string' => $dateStr, + 'name' => $dateName, + 'count' => $count, + 'spent' => $spent, + 'earned' => $earned, + 'transferred' => $transferred, + 'start' => clone $date['start'], + 'end' => clone $date['end'], + ] + ); + } + Log::debug('End of loops'); + $cache->store($entries); + + return $entries; + } + /** * This shows a period overview for a tag. It goes back in time and lists all relevant transactions and sums. *