Code cleanup.

This commit is contained in:
James Cole 2018-07-20 14:34:56 +02:00
parent cfc2181a48
commit 44fb307da4
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
73 changed files with 1914 additions and 1423 deletions

View File

@ -44,7 +44,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
* Generate the report.
*
* @return string
* @throws \Throwable
*/
public function generate(): string
{

View File

@ -51,7 +51,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
* Generates the report.
*
* @return string
* @throws \Throwable
*/
public function generate(): string
{

View File

@ -64,7 +64,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
* Generates the report.
*
* @return string
* @throws \Throwable
*/
public function generate(): string
{

View File

@ -68,7 +68,7 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
* Generates the report.
*
* @return string
* @throws \Throwable
*/
public function generate(): string
{

View File

@ -43,7 +43,7 @@ class MonthReportGenerator implements ReportGeneratorInterface
* Generates the report.
*
* @return string
* @throws \Throwable
*/
public function generate(): string
{

View File

@ -42,7 +42,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface
* Generates the report.
*
* @return string
* @throws \Throwable
*/
public function generate(): string
{

View File

@ -42,7 +42,7 @@ class YearReportGenerator implements ReportGeneratorInterface
* Generates the report.
*
* @return string
* @throws \Throwable
*/
public function generate(): string
{

View File

@ -70,8 +70,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface
* Generate the report.
*
* @return string
* @throws \Throwable
* @throws \Throwable
*/
public function generate(): string
{

View File

@ -32,7 +32,6 @@ use Log;
/**
* Trait UpdateTrait
*
* @package FireflyIII\Helpers\Update
*/
trait UpdateTrait
{

View File

@ -177,6 +177,8 @@ class DebugController extends Controller
/**
* @return string
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function routes(): string
{

View File

@ -130,6 +130,8 @@ class ExportController extends Controller
* @param ExportJobRepositoryInterface $jobs
*
* @return JsonResponse
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function postIndex(ExportFormRequest $request, AccountRepositoryInterface $repository, ExportJobRepositoryInterface $jobs): JsonResponse
{

View File

@ -68,6 +68,8 @@ class HelpController extends Controller
* @param string $language
*
* @return string
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function getHelpText(string $route, string $language): string
{

View File

@ -26,8 +26,6 @@ use Carbon\Carbon;
use FireflyIII\Events\RequestedVersionCheckStatus;
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Http\Middleware\Installer;
use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Http\Middleware\IsSandStormUser;
use FireflyIII\Models\AccountType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
@ -36,7 +34,6 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Log;
use View;
/**
* Class HomeController.
@ -52,9 +49,6 @@ class HomeController extends Controller
app('view')->share('title', 'Firefly III');
app('view')->share('mainTitleIcon', 'fa-fire');
$this->middleware(Installer::class);
$this->middleware(IsDemoUser::class)->except(['dateRange', 'index']);
$this->middleware(IsSandStormUser::class)->only('routes');
}
/**
@ -98,7 +92,7 @@ class HomeController extends Controller
/**
* @param AccountRepositoryInterface $repository
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|View
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
*/
public function index(AccountRepositoryInterface $repository)
{
@ -110,10 +104,7 @@ class HomeController extends Controller
}
$subTitle = (string)trans('firefly.welcomeBack');
$transactions = [];
$frontPage = app('preferences')->get(
'frontPageAccounts',
$repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray()
);
$frontPage = app('preferences')->get('frontPageAccounts', $repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray());
/** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */
@ -122,7 +113,6 @@ class HomeController extends Controller
$accounts = $repository->getAccountsById($frontPage->data);
$today = new Carbon;
// zero bills? Hide some elements from view.
/** @var BillRepositoryInterface $billRepository */
$billRepository = app(BillRepositoryInterface::class);
$billCount = $billRepository->getBills()->count();
@ -134,15 +124,11 @@ class HomeController extends Controller
$transactions[] = [$set, $account];
}
// fire check update event:
/** @var User $user */
$user = auth()->user();
event(new RequestedVersionCheckStatus($user));
return view(
'index',
compact('count', 'subTitle', 'transactions', 'billCount', 'start', 'end', 'today')
);
return view('index', compact('count', 'subTitle', 'transactions', 'billCount', 'start', 'end', 'today'));
}
}

View File

@ -22,13 +22,12 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Import;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Import\Prerequisites\PrerequisitesInterface;
use FireflyIII\Models\ImportJob;
use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use FireflyIII\Support\Binder\ImportProvider;
use Illuminate\Http\Response as LaravelResponse;
use Log;
@ -37,9 +36,10 @@ use Log;
*/
class IndexController extends Controller
{
/** @var array */
public $providers;
/** @var ImportJobRepositoryInterface */
public $repository;
/** @var UserRepositoryInterface */
public $userRepository;
@ -56,6 +56,7 @@ class IndexController extends Controller
app('view')->share('title', (string)trans('firefly.import_index_title'));
$this->repository = app(ImportJobRepositoryInterface::class);
$this->userRepository = app(UserRepositoryInterface::class);
$this->providers = ImportProvider::getProviders();
return $next($request);
}
@ -69,57 +70,44 @@ class IndexController extends Controller
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @throws FireflyException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function create(string $importProvider)
{
Log::debug(sprintf('Will create job for provider "%s"', $importProvider));
// can only create "fake" for demo user.
$providers = array_keys($this->getProviders());
if (!\in_array($importProvider, $providers, true)) {
Log::error(sprintf('%s-provider is disabled. Cannot create job.', $importProvider));
session()->flash('warning', (string)trans('import.cannot_create_for_provider', ['provider' => $importProvider]));
return redirect(route('import.index'));
}
$importJob = $this->repository->create($importProvider);
Log::debug(sprintf('Created job #%d for provider %s', $importJob->id, $importProvider));
$hasPreReq = (bool)config(sprintf('import.has_prereq.%s', $importProvider));
$hasConfig = (bool)config(sprintf('import.has_job_config.%s', $importProvider));
// if job provider has no prerequisites:
if (false === $hasPreReq) {
Log::debug(sprintf('Created job #%d for provider %s', $importJob->id, $importProvider));
// no prerequisites and no config:
if (false === $hasPreReq && false === $hasConfig) {
Log::debug('Provider needs no configuration for job. Job is ready to start.');
$this->repository->updateStatus($importJob, 'ready_to_run');
Log::debug('Redirect to status-page.');
return redirect(route('import.job.status.index', [$importJob->key]));
}
// no prerequisites but job has config:
if (false === $hasPreReq && false !== $hasConfig) {
Log::debug('Provider has no prerequisites. Continue.');
// if job provider also has no configuration:
if (false === $hasConfig) {
// @codeCoverageIgnoreStart
Log::debug('Provider needs no configuration for job. Job is ready to start.');
$this->repository->updateStatus($importJob, 'ready_to_run');
Log::debug('Redirect to status-page.');
return redirect(route('import.job.status.index', [$importJob->key]));
// @codeCoverageIgnoreEnd
}
// update job to say "has_prereq".
$this->repository->setStatus($importJob, 'has_prereq');
// redirect to job configuration.
Log::debug('Redirect to configuration.');
return redirect(route('import.job.configuration.index', [$importJob->key]));
}
// job has prerequisites:
Log::debug('Job provider has prerequisites.');
// if need to set prerequisites, do that first.
$class = (string)config(sprintf('import.prerequisites.%s', $importProvider));
if (!class_exists($class)) {
throw new FireflyException(sprintf('No class to handle prerequisites for "%s".', $importProvider)); // @codeCoverageIgnore
}
/** @var PrerequisitesInterface $providerPre */
$providerPre = app($class);
$providerPre = app((string)config(sprintf('import.prerequisites.%s', $importProvider)));
$providerPre->setUser($importJob->user);
// and are not filled in:
if (!$providerPre->isComplete()) {
Log::debug('Job provider prerequisites are not yet filled in. Redirect to prerequisites-page.');
@ -128,8 +116,10 @@ class IndexController extends Controller
}
Log::debug('Prerequisites are complete.');
// update job to say "has_prereq".
// but are filled in:
$this->repository->setStatus($importJob, 'has_prereq');
// and has no config:
if (false === $hasConfig) {
// @codeCoverageIgnoreStart
Log::debug('Provider has no configuration. Job is ready to start.');
@ -139,6 +129,8 @@ class IndexController extends Controller
return redirect(route('import.job.status.index', [$importJob->key]));
// @codeCoverageIgnoreEnd
}
// but also needs config:
Log::debug('Job has configuration. Redirect to job-config.');
// Otherwise just redirect to job configuration.
@ -184,62 +176,10 @@ class IndexController extends Controller
*/
public function index()
{
$providers = $this->getProviders();
$providers = $this->providers;
$subTitle = (string)trans('import.index_breadcrumb');
$subTitleIcon = 'fa-home';
return view('import.index', compact('subTitle', 'subTitleIcon', 'providers'));
}
/**
* @return array
*/
private function getProviders(): array
{
// get and filter all import routines:
/** @var User $user */
$user = auth()->user();
/** @var array $config */
$providerNames = array_keys(config('import.enabled'));
$providers = [];
$isDemoUser = $this->userRepository->hasRole($user, 'demo');
$isDebug = (bool)config('app.debug');
foreach ($providerNames as $providerName) {
//Log::debug(sprintf('Now with provider %s', $providerName));
// only consider enabled providers
$enabled = (bool)config(sprintf('import.enabled.%s', $providerName));
$allowedForDemo = (bool)config(sprintf('import.allowed_for_demo.%s', $providerName));
$allowedForUser = (bool)config(sprintf('import.allowed_for_user.%s', $providerName));
if (false === $enabled) {
//Log::debug('Provider is not enabled. NEXT!');
continue;
}
if (true === $isDemoUser && false === $allowedForDemo) {
//Log::debug('User is demo and this provider is not allowed for demo user. NEXT!');
continue;
}
if (false === $isDemoUser && false === $allowedForUser && false === $isDebug) {
//Log::debug('User is not demo and this provider is not allowed for such users. NEXT!');
continue; // @codeCoverageIgnore
}
$providers[$providerName] = [
'has_prereq' => (bool)config('import.has_prereq.' . $providerName),
];
$class = (string)config(sprintf('import.prerequisites.%s', $providerName));
$result = false;
if ('' !== $class && class_exists($class)) {
//Log::debug('Will not check prerequisites.');
/** @var PrerequisitesInterface $object */
$object = app($class);
$object->setUser($user);
$result = $object->isComplete();
}
$providers[$providerName]['prereq_complete'] = $result;
}
Log::debug(sprintf('Enabled providers: %s', json_encode(array_keys($providers))));
return $providers;
}
}

View File

@ -66,11 +66,13 @@ class JobConfigurationController extends Controller
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*
*/
public function index(ImportJob $importJob)
{
Log::debug('Now in JobConfigurationController::index()');
// catch impossible status:
$allowed = ['has_prereq', 'need_job_config'];
if (null !== $importJob && !\in_array($importJob->status, $allowed, true)) {
Log::debug(sprintf('Job has state "%s", but we only accept %s', $importJob->status, json_encode($allowed)));
@ -91,10 +93,7 @@ class JobConfigurationController extends Controller
// @codeCoverageIgnoreEnd
}
// create configuration class:
$configurator = $this->makeConfigurator($importJob);
// is the job already configured?
if ($configurator->configurationComplete()) {
Log::debug('Config is complete, set status to ready_to_run.');
$this->repository->updateStatus($importJob, 'ready_to_run');
@ -119,6 +118,8 @@ class JobConfigurationController extends Controller
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function post(Request $request, ImportJob $importJob)
{

View File

@ -22,7 +22,6 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Import;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Import\Prerequisites\PrerequisitesInterface;
use FireflyIII\Models\ImportJob;
@ -68,7 +67,8 @@ class PrerequisitesController extends Controller
* @param ImportJob $importJob
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function index(string $importProvider, ImportJob $importJob = null)
{
@ -83,9 +83,6 @@ class PrerequisitesController extends Controller
app('view')->share('subTitle', (string)trans('import.prerequisites_breadcrumb_' . $importProvider));
$class = (string)config(sprintf('import.prerequisites.%s', $importProvider));
if (!class_exists($class)) {
throw new FireflyException(sprintf('No class to handle prerequisites for "%s".', $importProvider)); // @codeCoverageIgnore
}
/** @var User $user */
$user = auth()->user();
/** @var PrerequisitesInterface $object */
@ -121,8 +118,8 @@ class PrerequisitesController extends Controller
* @param ImportJob $importJob
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @throws FireflyException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function post(Request $request, string $importProvider, ImportJob $importJob = null)
{
@ -139,9 +136,6 @@ class PrerequisitesController extends Controller
$class = (string)config(sprintf('import.prerequisites.%s', $importProvider));
if (!class_exists($class)) {
throw new FireflyException(sprintf('Cannot find class %s', $class)); // @codeCoverageIgnore
}
/** @var User $user */
$user = auth()->user();
/** @var PrerequisitesInterface $object */

View File

@ -136,6 +136,7 @@ class JavascriptController extends Controller
/**
* @return array
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
private function getDateRangeConfig(): array
{

View File

@ -39,6 +39,9 @@ use Illuminate\Http\JsonResponse;
/**
* Class AutoCompleteController.
*
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class AutoCompleteController extends Controller
{

View File

@ -22,13 +22,13 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Json;
use Amount;
use Carbon\Carbon;
use FireflyIII\Helpers\Collector\JournalCollectorInterface;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType;
use FireflyIII\Models\Transaction;
use FireflyIII\Models\TransactionCurrency;
use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
@ -47,6 +47,8 @@ class BoxController extends Controller
* @param BudgetRepositoryInterface $repository
*
* @return JsonResponse
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function available(BudgetRepositoryInterface $repository): JsonResponse
{
@ -99,6 +101,8 @@ class BoxController extends Controller
* @param CurrencyRepositoryInterface $repository
*
* @return JsonResponse
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function balance(CurrencyRepositoryInterface $repository): JsonResponse
{
@ -150,17 +154,18 @@ class BoxController extends Controller
}
// format amounts:
foreach ($sums as $currencyId => $amount) {
$keys = array_keys($sums);
foreach ($keys as $currencyId) {
$currency = $repository->findNull($currencyId);
$sums[$currencyId] = Amount::formatAnything($currency, $sums[$currencyId], false);
$incomes[$currencyId] = Amount::formatAnything($currency, $incomes[$currencyId] ?? '0', false);
$expenses[$currencyId] = Amount::formatAnything($currency, $expenses[$currencyId] ?? '0', false);
$sums[$currencyId] = app('amount')->formatAnything($currency, $sums[$currencyId], false);
$incomes[$currencyId] = app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false);
$expenses[$currencyId] = app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false);
}
if (0 === \count($sums)) {
$currency = app('amount')->getDefaultCurrency();
$sums[$currency->id] = Amount::formatAnything($currency, '0', false);
$incomes[$currency->id] = Amount::formatAnything($currency, '0', false);
$expenses[$currency->id] = Amount::formatAnything($currency, '0', false);
$sums[$currency->id] = app('amount')->formatAnything($currency, '0', false);
$incomes[$currency->id] = app('amount')->formatAnything($currency, '0', false);
$expenses[$currency->id] = app('amount')->formatAnything($currency, '0', false);
}
$response = [
@ -214,28 +219,23 @@ class BoxController extends Controller
/**
* @param AccountRepositoryInterface $repository
*
* @param CurrencyRepositoryInterface $currencyRepos
* @param AccountRepositoryInterface $repository
*
* @return JsonResponse
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function netWorth(AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepos): JsonResponse
public function netWorth(AccountRepositoryInterface $repository): JsonResponse
{
$date = new Carbon(date('Y-m-d')); // needed so its per day.
/** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */
$end = session('end', Carbon::now()->endOfMonth());
// start and end in the future? use $end
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
$date = $end;
}
// start and end in the past? use $end
if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) {
$date = $end;
if ($this->notInSessionRange($date)) {
/** @var Carbon $date */
$date = session('end', Carbon::now()->endOfMonth());
}
// start in the past, end in the future? use $date
$cache = new CacheProperties;
$cache->addProperty($date);
@ -245,20 +245,13 @@ class BoxController extends Controller
}
$netWorth = [];
$accounts = $repository->getActiveAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
$currency = app('amount')->getDefaultCurrency();
$balances = app('steam')->balancesByAccounts($accounts, $date);
/** @var Account $account */
foreach ($accounts as $account) {
$accountCurrency = null;
$accountCurrency = $this->getCurrencyOrDefault($account);
$balance = $balances[$account->id] ?? '0';
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
if (0 !== $currencyId) {
$accountCurrency = $currencyRepos->findNull($currencyId);
}
if (null === $accountCurrency) {
$accountCurrency = $currency;
}
// if the account is a credit card, subtract the virtual balance from the balance,
// to better reflect that this is not money that is actually "yours".
@ -287,4 +280,53 @@ class BoxController extends Controller
return response()->json($return);
}
/**
* @param Account $account
*
* @return TransactionCurrency
*/
private function getCurrencyOrDefault(Account $account): TransactionCurrency
{
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
/** @var CurrencyRepositoryInterface $currencyRepos */
$currencyRepos = app(CurrencyRepositoryInterface::class);
$currency = app('amount')->getDefaultCurrency();
$accountCurrency = null;
$currencyId = (int)$repository->getMetaValue($account, 'currency_id');
if (0 !== $currencyId) {
$accountCurrency = $currencyRepos->findNull($currencyId);
}
if (null === $accountCurrency) {
$accountCurrency = $currency;
}
return $accountCurrency;
}
/**
* @param Carbon $date
*
* @return bool
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function notInSessionRange(Carbon $date): bool
{
/** @var Carbon $start */
$start = session('start', Carbon::now()->startOfMonth());
/** @var Carbon $end */
$end = session('end', Carbon::now()->endOfMonth());
$result = false;
if ($start->greaterThanOrEqualTo($date) && $end->greaterThanOrEqualTo($date)) {
$result = true;
}
// start and end in the past? use $end
if ($start->lessThanOrEqualTo($date) && $end->lessThanOrEqualTo($date)) {
$result = true;
}
return $result;
}
}

View File

@ -36,7 +36,7 @@ class FrontpageController extends Controller
* @param PiggyBankRepositoryInterface $repository
*
* @return JsonResponse
* @throws \Throwable
*/
public function piggyBanks(PiggyBankRepositoryInterface $repository): JsonResponse
{

View File

@ -158,6 +158,7 @@ class IntroController
* @param string $specificPage
*
* @return array
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function getSpecificSteps(string $route, string $specificPage): array
{

View File

@ -42,6 +42,8 @@ use Illuminate\Support\Collection;
/**
*
* Class ReconcileController
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ReconcileController extends Controller
{
@ -84,7 +86,10 @@ class ReconcileController extends Controller
* @return JsonResponse
*
* @throws FireflyException
* @throws \Throwable
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function overview(Request $request, Account $account, Carbon $start, Carbon $end): JsonResponse
{
@ -140,7 +145,7 @@ class ReconcileController extends Controller
* @return mixed
*
* @throws FireflyException
* @throws \Throwable
*/
public function transactions(Account $account, Carbon $start, Carbon $end)
{

View File

@ -0,0 +1,175 @@
<?php
/**
* RecurrenceController.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Json;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
/**
* Class RecurrenceController
*/
class RecurrenceController extends Controller
{
/** @var RecurringRepositoryInterface */
private $recurring;
/**
*
*/
public function __construct()
{
parent::__construct();
// translations:
$this->middleware(
function ($request, $next) {
$this->recurring = app(RecurringRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param Request $request
*
* @throws FireflyException
* @return JsonResponse
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function events(Request $request): JsonResponse
{
$return = [];
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
$firstDate = Carbon::createFromFormat('Y-m-d', $request->get('first_date'));
$endDate = '' !== (string)$request->get('end_date') ? Carbon::createFromFormat('Y-m-d', $request->get('end_date')) : null;
$endsAt = (string)$request->get('ends');
$repetitionType = explode(',', $request->get('type'))[0];
$repetitions = (int)$request->get('reps');
$repetitionMoment = '';
$start->startOfDay();
// if $firstDate is beyond $end, simply return an empty array.
if ($firstDate->gt($end)) {
return response()->json([]);
}
// if $firstDate is beyond start, use that one:
$actualStart = clone $firstDate;
if ($repetitionType === 'weekly' || $repetitionType === 'monthly') {
$repetitionMoment = explode(',', $request->get('type'))[1] ?? '1';
}
if ($repetitionType === 'ndom') {
$repetitionMoment = str_ireplace('ndom,', '', $request->get('type'));
}
if ($repetitionType === 'yearly') {
$repetitionMoment = explode(',', $request->get('type'))[1] ?? '2018-01-01';
}
$repetition = new RecurrenceRepetition;
$repetition->repetition_type = $repetitionType;
$repetition->repetition_moment = $repetitionMoment;
$repetition->repetition_skip = (int)$request->get('skip');
$repetition->weekend = (int)$request->get('weekend');
$actualEnd = clone $end;
switch ($endsAt) {
default:
throw new FireflyException(sprintf('Cannot generate events for type that ends at "%s".', $endsAt));
case 'forever':
// simply generate up until $end. No change from default behavior.
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
break;
case 'until_date':
$actualEnd = $endDate ?? clone $end;
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
break;
case 'times':
$occurrences = $this->recurring->getXOccurrences($repetition, $actualStart, $repetitions);
break;
}
/** @var Carbon $current */
foreach ($occurrences as $current) {
if ($current->gte($start)) {
$event = [
'id' => $repetitionType . $firstDate->format('Ymd'),
'title' => 'X',
'allDay' => true,
'start' => $current->format('Y-m-d'),
'end' => $current->format('Y-m-d'),
'editable' => false,
'rendering' => 'background',
];
$return[] = $event;
}
}
return response()->json($return);
}
/**
* @param Request $request
*
* @return JsonResponse
*/
public function suggest(Request $request): JsonResponse
{
$today = new Carbon;
$date = Carbon::createFromFormat('Y-m-d', $request->get('date'));
$preSelected = (string)$request->get('pre_select');
$result = [];
if ($date > $today || 'true' === (string)$request->get('past')) {
$weekly = sprintf('weekly,%s', $date->dayOfWeekIso);
$monthly = sprintf('monthly,%s', $date->day);
$dayOfWeek = 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(trans('config.month_and_day_no_year'));
$result = [
'daily' => ['label' => (string)trans('firefly.recurring_daily'), 'selected' => 0 === strpos($preSelected, 'daily')],
$weekly => ['label' => (string)trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]),
'selected' => 0 === strpos($preSelected, 'weekly')],
$monthly => ['label' => (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $date->day]),
'selected' => 0 === strpos($preSelected, 'monthly')],
$ndom => ['label' => (string)trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $date->weekOfMonth]),
'selected' => 0 === strpos($preSelected, 'ndom')],
$yearly => ['label' => (string)trans('firefly.recurring_yearly', ['date' => $yearlyDate]), 'selected' => 0 === strpos($preSelected, 'yearly')],
];
}
return response()->json($result);
}
}

View File

@ -34,7 +34,7 @@ class JsonController extends Controller
* @param Request $request
*
* @return JsonResponse
* @throws \Throwable
*/
public function action(Request $request): JsonResponse
{
@ -53,7 +53,7 @@ class JsonController extends Controller
* @param Request $request
*
* @return JsonResponse
* @throws \Throwable
*/
public function trigger(Request $request): JsonResponse
{

View File

@ -97,31 +97,17 @@ class NewUserController extends Controller
$currency = $currencyRepository->findByCodeNull('EUR');
}
// create normal asset account:
$this->createAssetAccount($request, $currency);
// create savings account
$this->createSavingsAccount($request, $currency, $language);
// create cash wallet account
$this->createCashWalletAccount($currency, $language);
$this->createAssetAccount($request, $currency); // create normal asset account
$this->createSavingsAccount($request, $currency, $language); // create savings account
$this->createCashWalletAccount($currency, $language); // create cash wallet account
// store currency preference:
app('preferences')->set('currencyPreference', $currency->code);
app('preferences')->mark();
// set default optional fields:
$visibleFields = [
'interest_date' => true,
'book_date' => false,
'process_date' => false,
'due_date' => false,
'payment_date' => false,
'invoice_date' => false,
'internal_reference' => false,
'notes' => true,
'attachments' => true,
];
$visibleFields = ['interest_date' => true, 'book_date' => false, 'process_date' => false, 'due_date' => false, 'payment_date' => false,
'invoice_date' => false, 'internal_reference' => false, 'notes' => true, 'attachments' => true,];
app('preferences')->set('transaction_journal_optional_fields', $visibleFields);
session()->flash('success', (string)trans('firefly.stored_new_accounts_new_user'));

View File

@ -40,6 +40,9 @@ use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class PiggyBankController.
*
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class PiggyBankController extends Controller
{
@ -174,6 +177,8 @@ class PiggyBankController extends Controller
* @param PiggyBank $piggyBank
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function edit(PiggyBank $piggyBank)
{
@ -212,6 +217,8 @@ class PiggyBankController extends Controller
* @param Request $request
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function index(Request $request)
{

View File

@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Popup;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Collection\BalanceLine;
use FireflyIII\Helpers\Report\PopupReportInterface;
use FireflyIII\Http\Controllers\Controller;
@ -35,9 +34,13 @@ use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Routing\Route;
use InvalidArgumentException;
use Log;
use Throwable;
/**
* Class ReportController.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ReportController extends Controller
{
@ -79,9 +82,7 @@ class ReportController extends Controller
* @param Request $request
*
* @return JsonResponse
*
* @throws FireflyException
* @throws \Throwable
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function general(Request $request): JsonResponse
{
@ -93,7 +94,8 @@ class ReportController extends Controller
switch ($attributes['location']) {
default:
throw new FireflyException('Firefly cannot handle "' . e($attributes['location']) . '" ');
$html = sprintf('Firefly III cannot handle "%s"-popups.', $attributes['location']);
break;
case 'budget-spent-amount':
$html = $this->budgetSpentAmount($attributes);
break;
@ -119,8 +121,7 @@ class ReportController extends Controller
*
* @return string
*
* @throws FireflyException
* @throws \Throwable
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function balanceAmount(array $attributes): string
{
@ -141,51 +142,60 @@ class ReportController extends Controller
break;
case BalanceLine::ROLE_TAGROLE === $role:
// row with tag info.
throw new FireflyException('Firefly cannot handle this type of info-button (BalanceLine::TagRole)');
return 'Firefly cannot handle this type of info-button (BalanceLine::TagRole)';
}
try {
$view = view('popup.report.balance-amount', compact('journals', 'budget', 'account'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render: %s', $e->getMessage()));
$view = 'Firefly III could not render the view. Please see the log files.';
}
$view = view('popup.report.balance-amount', compact('journals', 'budget', 'account'))->render();
return $view;
}
/**
* Returns all expenses inside the given budget for the given accounts.
*
* @param array $attributes
*
* @return string
* @throws \Throwable
*/
private function budgetSpentAmount(array $attributes): string
{
$budget = $this->budgetRepository->findNull((int)$attributes['budgetId']);
if (null === $budget) {
throw new FireflyException('This is an unknown budget. Apologies.');
return 'This is an unknown budget. Apologies.';
}
$journals = $this->popupHelper->byBudget($budget, $attributes);
$view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render();
try {
$view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render: %s', $e->getMessage()));
$view = 'Firefly III could not render the view. Please see the log files.';
}
return $view;
}
/**
* Returns all expenses in category in range.
*
* @param array $attributes
*
* @return string
* @throws \Throwable
*/
private function categoryEntry(array $attributes): string
{
$category = $this->categoryRepository->findNull((int)$attributes['categoryId']);
if (null === $category) {
throw new FireflyException('This is an unknown category. Apologies.');
return 'This is an unknown category. Apologies.';
}
$journals = $this->popupHelper->byCategory($category, $attributes);
$view = view('popup.report.category-entry', compact('journals', 'category'))->render();
try {
$view = view('popup.report.category-entry', compact('journals', 'category'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render: %s', $e->getMessage()));
$view = 'Firefly III could not render the view. Please see the log files.';
}
return $view;
}
@ -196,18 +206,22 @@ class ReportController extends Controller
* @param array $attributes
*
* @return string
* @throws \Throwable
*/
private function expenseEntry(array $attributes): string
{
$account = $this->accountRepository->findNull((int)$attributes['accountId']);
if (null === $account) {
throw new FireflyException('This is an unknown account. Apologies.');
return 'This is an unknown account. Apologies.';
}
$journals = $this->popupHelper->byExpenses($account, $attributes);
$view = view('popup.report.expense-entry', compact('journals', 'account'))->render();
try {
$view = view('popup.report.expense-entry', compact('journals', 'account'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render: %s', $e->getMessage()));
$view = 'Firefly III could not render the view. Please see the log files.';
}
return $view;
}
@ -218,18 +232,22 @@ class ReportController extends Controller
* @param array $attributes
*
* @return string
* @throws \Throwable
*/
private function incomeEntry(array $attributes): string
{
$account = $this->accountRepository->findNull((int)$attributes['accountId']);
if (null === $account) {
throw new FireflyException('This is an unknown category. Apologies.');
return 'This is an unknown category. Apologies.';
}
$journals = $this->popupHelper->byIncome($account, $attributes);
$view = view('popup.report.income-entry', compact('journals', 'account'))->render();
try {
$view = view('popup.report.income-entry', compact('journals', 'account'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render: %s', $e->getMessage()));
$view = 'Firefly III could not render the view. Please see the log files.';
}
return $view;
}
@ -238,8 +256,6 @@ class ReportController extends Controller
* @param array $attributes
*
* @return array
*
* @throws FireflyException
*/
private function parseAttributes(array $attributes): array
{
@ -248,13 +264,19 @@ class ReportController extends Controller
try {
$attributes['startDate'] = Carbon::createFromFormat('Ymd', $attributes['startDate']);
} catch (InvalidArgumentException $e) {
throw new FireflyException(sprintf('Could not parse start date "%s": %s', $attributes['startDate'], $e->getMessage()));
Log::debug('Not important error message: %s', $e->getMessage());
$date = new Carbon;
$date->startOfMonth();
$attributes['startDate'] = $date;
}
try {
$attributes['endDate'] = Carbon::createFromFormat('Ymd', $attributes['endDate']);
} catch (InvalidArgumentException $e) {
throw new FireflyException(sprintf('Could not parse end date "%s": %s', $attributes['endDate'], $e->getMessage()));
Log::debug('Not important error message: %s', $e->getMessage());
$date = new Carbon;
$date->startOfMonth();
$attributes['endDate'] = $date;
}
return $attributes;

View File

@ -86,6 +86,9 @@ class PreferencesController extends Controller
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function postIndex(Request $request)
{

View File

@ -49,6 +49,8 @@ use phpseclib\Crypt\RSA;
* Class ProfileController.
*
* @method Guard guard()
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
*/
class ProfileController extends Controller
{
@ -185,10 +187,10 @@ class ProfileController extends Controller
if ($repository->hasRole($user, 'demo')) {
return redirect(route('profile.index'));
}
$hasTwoFactorAuthSecret = (null !== app('preferences')->get('twoFactorAuthSecret'));
$hasSecret = (null !== app('preferences')->get('twoFactorAuthSecret'));
// if we don't have a valid secret yet, redirect to the code page to get one.
if (!$hasTwoFactorAuthSecret) {
if (!$hasSecret) {
return redirect(route('profile.code'));
}
@ -308,6 +310,8 @@ class ProfileController extends Controller
* @param TokenFormRequest $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function postCode(TokenFormRequest $request)
{
@ -316,7 +320,6 @@ class ProfileController extends Controller
session()->flash('success', (string)trans('firefly.saved_preferences'));
app('preferences')->mark();
return redirect(route('profile.index'));
}
@ -366,6 +369,8 @@ class ProfileController extends Controller
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function undoEmailChange(UserRepositoryInterface $repository, string $token, string $hash)
{
@ -382,8 +387,7 @@ class ProfileController extends Controller
throw new FireflyException('Invalid token.');
}
// found user.
// which email address to return to?
// found user.which email address to return to?
$set = app('preferences')->beginsWith($user, 'previous_email_');
/** @var string $match */
$match = null;

View File

@ -69,6 +69,7 @@ class CreateController extends Controller
* @param Request $request
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function create(Request $request)
{
@ -83,14 +84,11 @@ class CreateController extends Controller
$this->rememberPreviousUri('recurring.create.uri');
}
$request->session()->forget('recurring.create.fromStore');
// when will it end?
$repetitionEnds = [
'forever' => (string)trans('firefly.repeat_forever'),
'until_date' => (string)trans('firefly.repeat_until_date'),
'times' => (string)trans('firefly.repeat_times'),
];
// what to do in the weekend?
$weekendResponses = [
RecurrenceRepetition::WEEKEND_DO_NOTHING => (string)trans('firefly.do_nothing'),
RecurrenceRepetition::WEEKEND_SKIP_CREATION => (string)trans('firefly.skip_transaction'),
@ -98,8 +96,8 @@ class CreateController extends Controller
RecurrenceRepetition::WEEKEND_TO_MONDAY => (string)trans('firefly.jump_to_monday'),
];
// flash some data:
$hasOldInput = null !== $request->old('_token');
$hasOldInput = null !== $request->old('_token'); // flash some data
$preFilled = [
'first_date' => $tomorrow->format('Y-m-d'),
'transaction_type' => $hasOldInput ? $request->old('transaction_type') : 'withdrawal',

View File

@ -68,31 +68,29 @@ class EditController extends Controller
}
/**
* todo move to repository
* todo handle old repetition type as well.
*
* @param Request $request
* @param Recurrence $recurrence
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @throws \FireflyIII\Exceptions\FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function edit(Request $request, Recurrence $recurrence)
{
// use transformer:
$transformer = new RecurrenceTransformer(new ParameterBag);
$array = $transformer->transform($recurrence);
$budgets = app('expandedform')->makeSelectListWithEmpty($this->budgets->getActiveBudgets());
// get recurrence type:
// todo move to repository
// todo handle old repetition type as well.
/** @var RecurrenceRepetition $repetition */
$repetition = $recurrence->recurrenceRepetitions()->first();
$currentRepetitionType = $repetition->repetition_type;
$currentRepType = $repetition->repetition_type;
if ('' !== $repetition->repetition_moment) {
$currentRepetitionType .= ',' . $repetition->repetition_moment;
$currentRepType .= ',' . $repetition->repetition_moment;
}
// put previous url in session if not redirect from store (not "return_to_edit").
@ -101,9 +99,7 @@ class EditController extends Controller
}
$request->session()->forget('recurrences.edit.fromUpdate');
// assume repeats forever:
$repetitionEnd = 'forever';
// types of repetitions:
$repetitionEnd = 'forever';
$repetitionEnds = [
'forever' => (string)trans('firefly.repeat_forever'),
'until_date' => (string)trans('firefly.repeat_until_date'),
@ -116,7 +112,6 @@ class EditController extends Controller
$repetitionEnd = 'times';
}
// what to do in the weekend?
$weekendResponses = [
RecurrenceRepetition::WEEKEND_DO_NOTHING => (string)trans('firefly.do_nothing'),
RecurrenceRepetition::WEEKEND_SKIP_CREATION => (string)trans('firefly.skip_transaction'),
@ -124,10 +119,8 @@ class EditController extends Controller
RecurrenceRepetition::WEEKEND_TO_MONDAY => (string)trans('firefly.jump_to_monday'),
];
// code to handle active-checkboxes
$hasOldInput = null !== $request->old('_token');
// $hasOldInput = false;
$preFilled = [
$preFilled = [
'transaction_type' => strtolower($recurrence->transactionType->type),
'active' => $hasOldInput ? (bool)$request->old('active') : $recurrence->active,
'apply_rules' => $hasOldInput ? (bool)$request->old('apply_rules') : $recurrence->apply_rules,
@ -135,7 +128,7 @@ class EditController extends Controller
return view(
'recurring.edit',
compact('recurrence', 'array', 'weekendResponses', 'budgets', 'preFilled', 'currentRepetitionType', 'repetitionEnd', 'repetitionEnds')
compact('recurrence', 'array', 'weekendResponses', 'budgets', 'preFilled', 'currentRepType', 'repetitionEnd', 'repetitionEnds')
);
}

View File

@ -28,10 +28,8 @@ use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Recurrence;
use FireflyIII\Models\RecurrenceRepetition;
use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface;
use FireflyIII\Transformers\RecurrenceTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\ParameterBag;
@ -64,98 +62,14 @@ class IndexController extends Controller
);
}
/**
* @param Request $request
* TODO: split collection into pages
*
* @throws FireflyException
* @return JsonResponse
*/
public function events(Request $request): JsonResponse
{
$return = [];
$start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
$end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
$firstDate = Carbon::createFromFormat('Y-m-d', $request->get('first_date'));
$endDate = '' !== (string)$request->get('end_date') ? Carbon::createFromFormat('Y-m-d', $request->get('end_date')) : null;
$endsAt = (string)$request->get('ends');
$repetitionType = explode(',', $request->get('type'))[0];
$repetitions = (int)$request->get('reps');
$repetitionMoment = '';
$start->startOfDay();
// if $firstDate is beyond $end, simply return an empty array.
if ($firstDate->gt($end)) {
return response()->json([]);
}
// if $firstDate is beyond start, use that one:
$actualStart = clone $firstDate;
switch ($repetitionType) {
default:
throw new FireflyException(sprintf('Cannot handle repetition type "%s"', $repetitionType));
case 'daily':
break;
case 'weekly':
case 'monthly':
$repetitionMoment = explode(',', $request->get('type'))[1] ?? '1';
break;
case 'ndom':
$repetitionMoment = str_ireplace('ndom,', '', $request->get('type'));
break;
case 'yearly':
$repetitionMoment = explode(',', $request->get('type'))[1] ?? '2018-01-01';
break;
}
$repetition = new RecurrenceRepetition;
$repetition->repetition_type = $repetitionType;
$repetition->repetition_moment = $repetitionMoment;
$repetition->repetition_skip = (int)$request->get('skip');
$repetition->weekend = (int)$request->get('weekend');
$actualEnd = clone $end;
switch ($endsAt) {
default:
throw new FireflyException(sprintf('Cannot generate events for type that ends at "%s".', $endsAt));
case 'forever':
// simply generate up until $end. No change from default behavior.
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
break;
case 'until_date':
$actualEnd = $endDate ?? clone $end;
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
break;
case 'times':
$occurrences = $this->recurring->getXOccurrences($repetition, $actualStart, $repetitions);
break;
}
/** @var Carbon $current */
foreach ($occurrences as $current) {
if ($current->gte($start)) {
$event = [
'id' => $repetitionType . $firstDate->format('Ymd'),
'title' => 'X',
'allDay' => true,
'start' => $current->format('Y-m-d'),
'end' => $current->format('Y-m-d'),
'editable' => false,
'rendering' => 'background',
];
$return[] = $event;
}
}
return response()->json($return);
}
/**
* @param Request $request
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @throws \FireflyIII\Exceptions\FireflyException
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function index(Request $request)
{
@ -163,7 +77,6 @@ class IndexController extends Controller
$pageSize = (int)app('preferences')->get('listPageSize', 50)->data;
$collection = $this->recurring->get();
// TODO: split collection into pages
$transformer = new RecurrenceTransformer(new ParameterBag);
$recurring = [];
@ -206,38 +119,4 @@ class IndexController extends Controller
return view('recurring.show', compact('recurrence', 'subTitle', 'array', 'transactions'));
}
/**
* @param Request $request
*
* @return JsonResponse
*/
public function suggest(Request $request): JsonResponse
{
$today = new Carbon;
$date = Carbon::createFromFormat('Y-m-d', $request->get('date'));
$preSelected = (string)$request->get('pre_select');
$result = [];
if ($date > $today || 'true' === (string)$request->get('past')) {
$weekly = sprintf('weekly,%s', $date->dayOfWeekIso);
$monthly = sprintf('monthly,%s', $date->day);
$dayOfWeek = 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(trans('config.month_and_day_no_year'));
$result = [
'daily' => ['label' => (string)trans('firefly.recurring_daily'), 'selected' => 0 === strpos($preSelected, 'daily')],
$weekly => ['label' => (string)trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]),
'selected' => 0 === strpos($preSelected, 'weekly')],
$monthly => ['label' => (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $date->day]),
'selected' => 0 === strpos($preSelected, 'monthly')],
$ndom => ['label' => (string)trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $date->weekOfMonth]),
'selected' => 0 === strpos($preSelected, 'ndom')],
$yearly => ['label' => (string)trans('firefly.recurring_yearly', ['date' => $yearlyDate]), 'selected' => 0 === strpos($preSelected, 'yearly')],
];
}
return response()->json($result);
}
}

View File

@ -41,7 +41,7 @@ class AccountController extends Controller
*
* @return mixed|string
*
* @throws \Throwable
*/
public function general(Collection $accounts, Carbon $start, Carbon $end)
{

View File

@ -40,7 +40,7 @@ class BalanceController extends Controller
* @param Carbon $end
*
* @return mixed|string
* @throws \Throwable
*/
public function general(Collection $accounts, Carbon $start, Carbon $end)
{

View File

@ -41,7 +41,7 @@ class BudgetController extends Controller
* @param Carbon $end
*
* @return mixed|string
* @throws \Throwable
*/
public function general(Collection $accounts, Carbon $start, Carbon $end)
{
@ -70,7 +70,7 @@ class BudgetController extends Controller
* @param Carbon $end
*
* @return mixed|string
* @throws \Throwable
*/
public function period(Collection $accounts, Carbon $start, Carbon $end)
{

View File

@ -28,6 +28,8 @@ use FireflyIII\Models\Category;
use FireflyIII\Repositories\Category\CategoryRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Log;
use Throwable;
/**
* Class CategoryController.
@ -41,7 +43,6 @@ class CategoryController extends Controller
* @param Carbon $end
*
* @return mixed|string
* @throws \Throwable
*/
public function expenses(Collection $accounts, Carbon $start, Carbon $end)
{
@ -60,7 +61,12 @@ class CategoryController extends Controller
$data[0] = $repository->periodExpensesNoCategory($accounts, $start, $end);
$report = $this->filterReport($data);
$periods = app('navigation')->listOfPeriods($start, $end);
$result = view('reports.partials.category-period', compact('report', 'periods'))->render();
try {
$result = view('reports.partials.category-period', compact('report', 'periods'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage()));
$result = 'An error prevented Firefly III from rendering. Apologies.';
}
$cache->store($result);
@ -75,7 +81,6 @@ class CategoryController extends Controller
* @param Carbon $end
*
* @return string
* @throws \Throwable
*/
public function income(Collection $accounts, Carbon $start, Carbon $end): string
{
@ -94,8 +99,12 @@ class CategoryController extends Controller
$data[0] = $repository->periodIncomeNoCategory($accounts, $start, $end);
$report = $this->filterReport($data);
$periods = app('navigation')->listOfPeriods($start, $end);
$result = view('reports.partials.category-period', compact('report', 'periods'))->render();
try {
$result = view('reports.partials.category-period', compact('report', 'periods'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage()));
$result = 'An error prevented Firefly III from rendering. Apologies.';
}
$cache->store($result);
return $result;
@ -109,8 +118,7 @@ class CategoryController extends Controller
*
* @return mixed|string
*
* @throws \Throwable
* @internal param ReportHelperInterface $helper
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function operations(Collection $accounts, Carbon $start, Carbon $end)
{
@ -136,17 +144,18 @@ class CategoryController extends Controller
$report[$category->id] = ['name' => $category->name, 'spent' => $spent, 'earned' => $earned, 'id' => $category->id];
}
}
// sort the result
// Obtain a list of columns
$sum = [];
foreach ($report as $categoryId => $row) {
$sum[$categoryId] = (float)$row['spent'];
}
array_multisort($sum, SORT_ASC, $report);
$result = view('reports.partials.categories', compact('report'))->render();
$cache->store($result);
try {
$result = view('reports.partials.categories', compact('report'))->render();
$cache->store($result);
} catch (Throwable $e) {
Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage()));
$result = 'An error prevented Firefly III from rendering. Apologies.';
}
return $result;
}

View File

@ -18,7 +18,6 @@
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
/** @noinspection MoreThanThreeArgumentsInspection */
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Report;
@ -33,9 +32,13 @@ use FireflyIII\Models\TransactionType;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\CacheProperties;
use Illuminate\Support\Collection;
use Log;
use Throwable;
/**
* Class ExpenseController
*
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
*/
class ExpenseController extends Controller
{
@ -60,6 +63,7 @@ class ExpenseController extends Controller
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* Generates the overview per budget.
*
@ -69,7 +73,7 @@ class ExpenseController extends Controller
* @param Carbon $end
*
* @return string
* @throws \Throwable
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function budget(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): string
{
@ -85,7 +89,7 @@ class ExpenseController extends Controller
}
$combined = $this->combineAccounts($expense);
$all = new Collection;
foreach ($combined as $name => $combi) {
foreach ($combined as $combi) {
$all = $all->merge($combi);
}
// now find spent / earned:
@ -100,13 +104,19 @@ class ExpenseController extends Controller
}
$together[$categoryId]['grand_total'] = bcadd($spentInfo['grand_total'], $together[$categoryId]['grand_total']);
}
$result = view('reports.partials.exp-budgets', compact('together'))->render();
try {
$result = view('reports.partials.exp-budgets', compact('together'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage()));
$result = 'An error prevented Firefly III from rendering. Apologies.';
}
$cache->store($result);
return $result;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* Generates the overview per category (spent and earned).
*
@ -116,7 +126,8 @@ class ExpenseController extends Controller
* @param Carbon $end
*
* @return string
* @throws \Throwable
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function category(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): string
{
@ -132,7 +143,7 @@ class ExpenseController extends Controller
}
$combined = $this->combineAccounts($expense);
$all = new Collection;
foreach ($combined as $name => $combi) {
foreach ($combined as $combi) {
$all = $all->merge($combi);
}
// now find spent / earned:
@ -156,14 +167,18 @@ class ExpenseController extends Controller
}
$together[$categoryId]['grand_total'] = bcadd($earnedInfo['grand_total'], $together[$categoryId]['grand_total']);
}
$result = view('reports.partials.exp-categories', compact('together'))->render();
try {
$result = view('reports.partials.exp-categories', compact('together'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage()));
$result = 'An error prevented Firefly III from rendering. Apologies.';
}
$cache->store($result);
return $result;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* Overview of spending
*
@ -173,7 +188,6 @@ class ExpenseController extends Controller
* @param Carbon $end
*
* @return array|mixed|string
* @throws \Throwable
*/
public function spent(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
{
@ -203,14 +217,19 @@ class ExpenseController extends Controller
'earned' => $earned,
];
}
$result = view('reports.partials.exp-not-grouped', compact('result'))->render();
try {
$result = view('reports.partials.exp-not-grouped', compact('result'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage()));
$result = 'An error prevented Firefly III from rendering. Apologies.';
}
$cache->store($result);
return $result;
// for period, get spent and earned for each account (by name)
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $accounts
* @param Collection $expense
@ -218,7 +237,6 @@ class ExpenseController extends Controller
* @param Carbon $end
*
* @return string
* @throws \Throwable
*/
public function topExpense(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): string
{
@ -234,7 +252,7 @@ class ExpenseController extends Controller
}
$combined = $this->combineAccounts($expense);
$all = new Collection;
foreach ($combined as $name => $combi) {
foreach ($combined as $combi) {
$all = $all->merge($combi);
}
// get all expenses in period:
@ -248,12 +266,17 @@ class ExpenseController extends Controller
return (float)$transaction->transaction_amount;
}
);
$result = view('reports.partials.top-transactions', compact('sorted'))->render();
try {
$result = view('reports.partials.top-transactions', compact('sorted'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage()));
$result = 'An error prevented Firefly III from rendering. Apologies.';
}
$cache->store($result);
return $result;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $accounts
* @param Collection $expense
@ -261,7 +284,6 @@ class ExpenseController extends Controller
* @param Carbon $end
*
* @return mixed|string
* @throws \Throwable
*/
public function topIncome(Collection $accounts, Collection $expense, Carbon $start, Carbon $end)
{
@ -277,7 +299,7 @@ class ExpenseController extends Controller
}
$combined = $this->combineAccounts($expense);
$all = new Collection;
foreach ($combined as $name => $combi) {
foreach ($combined as $combi) {
$all = $all->merge($combi);
}
// get all expenses in period:
@ -291,7 +313,12 @@ class ExpenseController extends Controller
return (float)$transaction->transaction_amount;
}
);
$result = view('reports.partials.top-transactions', compact('sorted'))->render();
try {
$result = view('reports.partials.top-transactions', compact('sorted'))->render();
} catch (Throwable $e) {
Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage()));
$result = 'An error prevented Firefly III from rendering. Apologies.';
}
$cache->store($result);
return $result;
@ -320,6 +347,7 @@ class ExpenseController extends Controller
return $combined;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $assets
* @param Collection $opposing
@ -327,6 +355,9 @@ class ExpenseController extends Controller
* @param Carbon $end
*
* @return array
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
protected function earnedByCategory(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array
{
@ -381,6 +412,7 @@ class ExpenseController extends Controller
return $sum;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $assets
* @param Collection $opposing
@ -423,6 +455,7 @@ class ExpenseController extends Controller
return $sum;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $assets
* @param Collection $opposing
@ -430,6 +463,8 @@ class ExpenseController extends Controller
* @param Carbon $end
*
* @return array
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
protected function spentByBudget(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array
{
@ -484,6 +519,7 @@ class ExpenseController extends Controller
return $sum;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $assets
* @param Collection $opposing
@ -491,6 +527,9 @@ class ExpenseController extends Controller
* @param Carbon $end
*
* @return array
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
protected function spentByCategory(Collection $assets, Collection $opposing, Carbon $start, Carbon $end): array
{
@ -545,6 +584,7 @@ class ExpenseController extends Controller
return $sum;
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $assets
* @param Collection $opposing

View File

@ -61,7 +61,7 @@ class OperationsController extends Controller
* @param Carbon $end
*
* @return mixed|string
* @throws \Throwable
*/
public function expenses(Collection $accounts, Carbon $start, Carbon $end)
{
@ -88,7 +88,7 @@ class OperationsController extends Controller
* @param Carbon $end
*
* @return string
* @throws \Throwable
*/
public function income(Collection $accounts, Carbon $start, Carbon $end): string
{
@ -116,7 +116,7 @@ class OperationsController extends Controller
* @param Carbon $end
*
* @return mixed|string
* @throws \Throwable
*/
public function operations(Collection $accounts, Carbon $start, Carbon $end)
{

View File

@ -19,7 +19,6 @@
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
/** @noinspection CallableParameterUseCaseInTypeContextInspection */
/** @noinspection MoreThanThreeArgumentsInspection */
declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
@ -40,6 +39,7 @@ use Log;
/**
* Class ReportController.
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class ReportController extends Controller
{
@ -68,7 +68,7 @@ class ReportController extends Controller
}
);
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $accounts
* @param Collection $expense
@ -133,6 +133,7 @@ class ReportController extends Controller
return $generator->generate();
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $accounts
* @param Collection $budgets
@ -168,6 +169,7 @@ class ReportController extends Controller
return $generator->generate();
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $accounts
* @param Collection $categories
@ -259,8 +261,7 @@ class ReportController extends Controller
* @param string $reportType
*
* @return mixed
*
* @throws \Throwable
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function options(string $reportType)
{
@ -291,6 +292,10 @@ class ReportController extends Controller
* @return RedirectResponse|\Illuminate\Routing\Redirector
*
* @throws \FireflyIII\Exceptions\FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function postIndex(ReportFormRequest $request)
{
@ -358,6 +363,7 @@ class ReportController extends Controller
return redirect($uri);
}
/** @noinspection MoreThanThreeArgumentsInspection */
/**
* @param Collection $accounts
* @param Collection $tags
@ -395,7 +401,6 @@ class ReportController extends Controller
/**
* @return string
* @throws \Throwable
*/
private function accountReportOptions(): string
{
@ -416,7 +421,6 @@ class ReportController extends Controller
/**
* @return string
* @throws \Throwable
*/
private function budgetReportOptions(): string
{
@ -429,7 +433,6 @@ class ReportController extends Controller
/**
* @return string
* @throws \Throwable
*/
private function categoryReportOptions(): string
{
@ -442,7 +445,6 @@ class ReportController extends Controller
/**
* @return string
* @throws \Throwable
*/
private function noReportOptions(): string
{
@ -451,7 +453,6 @@ class ReportController extends Controller
/**
* @return string
* @throws \Throwable
*/
private function tagReportOptions(): string
{

View File

@ -0,0 +1,250 @@
<?php
/**
* CreateController.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Rule;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\RuleFormRequest;
use FireflyIII\Models\Bill;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Support\Http\Controllers\RuleManagement;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Log;
use Throwable;
/**
* Class CreateController
*/
class CreateController extends Controller
{
use RuleManagement;
/** @var BillRepositoryInterface */
private $billRepos;
/** @var RuleGroupRepositoryInterface */
private $ruleRepos;
/**
* RuleController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
$this->billRepos = app(BillRepositoryInterface::class);
$this->ruleRepos = app(RuleRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Create a new rule. It will be stored under the given $ruleGroup.
*
* TODO remove bill from this method, move to separate routine.
*
* @param Request $request
* @param RuleGroup $ruleGroup
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function create(Request $request, RuleGroup $ruleGroup)
{
$this->createDefaultRuleGroup();
$this->createDefaultRule();
$bill = null;
$billId = (int)$request->get('fromBill');
$preFilled = [
'strict' => true,
];
$oldTriggers = [];
$oldActions = [];
$returnToBill = false;
if ('true' === $request->get('return')) {
$returnToBill = true;
}
// has bill?
if ($billId > 0) {
$bill = $this->billRepos->find($billId);
}
// has old input?
if ($request->old()) {
$oldTriggers = $this->getPreviousTriggers($request);
$oldActions = $this->getPreviousActions($request);
}
// has existing bill refered to in URI?
if (null !== $bill && !$request->old()) {
// create some sensible defaults:
$preFilled['title'] = (string)trans('firefly.new_rule_for_bill_title', ['name' => $bill->name]);
$preFilled['description'] = (string)trans('firefly.new_rule_for_bill_description', ['name' => $bill->name]);
// get triggers and actions for bill:
$oldTriggers = $this->getTriggersForBill($bill);
$oldActions = $this->getActionsForBill($bill);
}
$triggerCount = \count($oldTriggers);
$actionCount = \count($oldActions);
$subTitleIcon = 'fa-clone';
$subTitle = (string)trans('firefly.make_new_rule', ['title' => $ruleGroup->title]);
$request->session()->flash('preFilled', $preFilled);
// put previous url in session if not redirect from store (not "create another").
if (true !== session('rules.create.fromStore')) {
$this->rememberPreviousUri('rules.create.uri');
}
session()->forget('rules.create.fromStore');
return view(
'rules.rule.create',
compact(
'subTitleIcon', 'oldTriggers', 'returnToBill', 'preFilled', 'bill', 'oldActions', 'triggerCount', 'actionCount', 'ruleGroup',
'subTitle'
)
);
}
/**
* @param RuleFormRequest $request
*
* @return RedirectResponse|\Illuminate\Routing\Redirector
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function store(RuleFormRequest $request)
{
$data = $request->getRuleData();
$rule = $this->ruleRepos->store($data);
session()->flash('success', (string)trans('firefly.stored_new_rule', ['title' => $rule->title]));
app('preferences')->mark();
// redirect to show bill.
if ('true' === $request->get('return_to_bill') && (int)$request->get('bill_id') > 0) {
return redirect(route('bills.show', [(int)$request->get('bill_id')])); // @codeCoverageIgnore
}
// redirect to new bill creation.
if ((int)$request->get('bill_id') > 0) {
return redirect($this->getPreviousUri('bills.create.uri')); // @codeCoverageIgnore
}
$redirect = redirect($this->getPreviousUri('rules.create.uri'));
if (1 === (int)$request->get('create_another')) {
// @codeCoverageIgnoreStart
session()->put('rules.create.fromStore', true);
$redirect = redirect(route('rules.create', [$data['rule_group_id']]))->withInput();
// @codeCoverageIgnoreEnd
}
return $redirect;
}
/**
* @param Bill $bill
*
* @return array
*/
private function getActionsForBill(Bill $bill): array
{
$result = '';
try {
$result = view(
'rules.partials.action',
[
'oldAction' => 'link_to_bill',
'oldValue' => $bill->name,
'oldChecked' => false,
'count' => 1,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::error(sprintf('Throwable was thrown in getActionsForBill(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
$result = 'Could not render view. See log files.';
}
// @codeCoverageIgnoreEnd
return [$result];
}
/**
* Create fake triggers to match the bill's properties
*
* @param Bill $bill
*
* @return array
*/
private function getTriggersForBill(Bill $bill): array
{
$result = [];
$triggers = ['currency_is', 'amount_more', 'amount_less', 'description_contains'];
$values = [
$bill->transactionCurrency()->first()->name,
round($bill->amount_min, 12),
round($bill->amount_max, 12),
$bill->name,
];
foreach ($triggers as $index => $trigger) {
try {
$string = view(
'rules.partials.trigger',
[
'oldTrigger' => $trigger,
'oldValue' => $values[$index],
'oldChecked' => false,
'count' => $index + 1,
]
)->render();
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage()));
Log::debug($e->getTraceAsString());
$string = '';
}
if ('' !== $string) {
$result[] = $string;
}
}
return $result;
}
}

View File

@ -0,0 +1,94 @@
<?php
/**
* DeleteController.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Rule;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Rule;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use Illuminate\Http\RedirectResponse;
/**
* Class DeleteController
*/
class DeleteController extends Controller
{
/** @var RuleRepositoryInterface */
private $ruleRepos;
/**
* RuleController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
$this->ruleRepos = app(RuleRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Delete a given rule.
*
* @param Rule $rule
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function delete(Rule $rule)
{
$subTitle = (string)trans('firefly.delete_rule', ['title' => $rule->title]);
// put previous url in session
$this->rememberPreviousUri('rules.delete.uri');
return view('rules.rule.delete', compact('rule', 'subTitle'));
}
/**
* Actually destroy the given rule.
*
* @param Rule $rule
*
* @return RedirectResponse
*/
public function destroy(Rule $rule): RedirectResponse
{
$title = $rule->title;
$this->ruleRepos->destroy($rule);
session()->flash('success', (string)trans('firefly.deleted_rule', ['title' => $title]));
app('preferences')->mark();
return redirect($this->getPreviousUri('rules.delete.uri'));
}
}

View File

@ -0,0 +1,219 @@
<?php
/**
* EditController.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Rule;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\RuleFormRequest;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\RuleTrigger;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Support\Http\Controllers\RuleManagement;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Log;
use Throwable;
/**
* Class EditController
*/
class EditController extends Controller
{
use RuleManagement;
/** @var RuleRepositoryInterface */
private $ruleRepos;
/**
* RuleController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
$this->ruleRepos = app(RuleRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param Request $request
* @param Rule $rule
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function edit(Request $request, Rule $rule)
{
$triggerCount = 0;
$actionCount = 0;
$oldActions = [];
$oldTriggers = [];
// has old input?
if (\count($request->old()) > 0) {
$oldTriggers = $this->getPreviousTriggers($request);
$triggerCount = \count($oldTriggers);
$oldActions = $this->getPreviousActions($request);
$actionCount = \count($oldActions);
}
// overrule old input when it has no rule data:
if (0 === $triggerCount && 0 === $actionCount) {
$oldTriggers = $this->getCurrentTriggers($rule);
$triggerCount = \count($oldTriggers);
$oldActions = $this->getCurrentActions($rule);
$actionCount = \count($oldActions);
}
$hasOldInput = null !== $request->old('_token');
$preFilled = [
'active' => $hasOldInput ? (bool)$request->old('active') : $rule->active,
'stop_processing' => $hasOldInput ? (bool)$request->old('stop_processing') : $rule->stop_processing,
'strict' => $hasOldInput ? (bool)$request->old('strict') : $rule->strict,
];
// get rule trigger for update / store-journal:
$primaryTrigger = $this->ruleRepos->getPrimaryTrigger($rule);
$subTitle = (string)trans('firefly.edit_rule', ['title' => $rule->title]);
// put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('rules.edit.fromUpdate')) {
$this->rememberPreviousUri('rules.edit.uri');
}
session()->forget('rules.edit.fromUpdate');
$request->session()->flash('preFilled', $preFilled);
return view('rules.rule.edit', compact('rule', 'subTitle', 'primaryTrigger', 'oldTriggers', 'oldActions', 'triggerCount', 'actionCount'));
}
/**
* @param RuleFormRequest $request
* @param Rule $rule
*
* @return RedirectResponse|\Illuminate\Routing\Redirector
*/
public function update(RuleFormRequest $request, Rule $rule)
{
$data = $request->getRuleData();
$this->ruleRepos->update($rule, $data);
session()->flash('success', (string)trans('firefly.updated_rule', ['title' => $rule->title]));
app('preferences')->mark();
$redirect = redirect($this->getPreviousUri('rules.edit.uri'));
if (1 === (int)$request->get('return_to_edit')) {
// @codeCoverageIgnoreStart
session()->put('rules.edit.fromUpdate', true);
$redirect = redirect(route('rules.edit', [$rule->id]))->withInput(['return_to_edit' => 1]);
// @codeCoverageIgnoreEnd
}
return $redirect;
}
/**
* @param Rule $rule
*
* @return array
*
*/
private function getCurrentActions(Rule $rule): array
{
$index = 0;
$actions = [];
/** @var RuleAction $entry */
foreach ($rule->ruleActions as $entry) {
$count = ($index + 1);
try {
$actions[] = view(
'rules.partials.action',
[
'oldAction' => $entry->action_type,
'oldValue' => $entry->action_value,
'oldChecked' => $entry->stop_processing,
'count' => $count,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
++$index;
}
return $actions;
}
/**
* @param Rule $rule
*
* @return array
*
*/
private function getCurrentTriggers(Rule $rule): array
{
$index = 0;
$triggers = [];
/** @var RuleTrigger $entry */
foreach ($rule->ruleTriggers as $entry) {
if ('user_action' !== $entry->trigger_type) {
$count = ($index + 1);
try {
$triggers[] = view(
'rules.partials.trigger',
[
'oldTrigger' => $entry->trigger_type,
'oldValue' => $entry->trigger_value,
'oldChecked' => $entry->stop_processing,
'count' => $count,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
++$index;
}
}
return $triggers;
}
}

View File

@ -0,0 +1,136 @@
<?php
/**
* RuleController.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Rule;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\Rule;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\Support\Http\Controllers\RuleManagement;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
/**
* Class IndexController
*/
class IndexController extends Controller
{
use RuleManagement;
/** @var RuleGroupRepositoryInterface */
private $ruleGroupRepos;
/** @var RuleRepositoryInterface */
private $ruleRepos;
/**
* RuleController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
$this->ruleGroupRepos = app(RuleGroupRepositoryInterface::class);
$this->ruleRepos = app(RuleRepositoryInterface::class);
return $next($request);
}
);
}
/**
* @param Rule $rule
*
* @return RedirectResponse|\Illuminate\Routing\Redirector
*/
public function down(Rule $rule)
{
$this->ruleRepos->moveDown($rule);
return redirect(route('rules.index'));
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
/** @var User $user */
$user = auth()->user();
$this->createDefaultRuleGroup();
$this->createDefaultRule();
$ruleGroups = $this->ruleGroupRepos->getRuleGroupsWithRules($user);
return view('rules.index', compact('ruleGroups'));
}
/**
* @param Request $request
* @param Rule $rule
*
* @return JsonResponse
*/
public function reorderRuleActions(Request $request, Rule $rule): JsonResponse
{
$ids = $request->get('actions');
if (\is_array($ids)) {
$this->ruleRepos->reorderRuleActions($rule, $ids);
}
return response()->json('true');
}
/**
* @param Request $request
* @param Rule $rule
*
* @return JsonResponse
*/
public function reorderRuleTriggers(Request $request, Rule $rule): JsonResponse
{
$ids = $request->get('triggers');
if (\is_array($ids)) {
$this->ruleRepos->reorderRuleTriggers($rule, $ids);
}
return response()->json('true');
}
/**
* @param Rule $rule
*
* @return RedirectResponse|\Illuminate\Routing\Redirector
* @SuppressWarnings(PHPMD.ShortMethodName)
*/
public function up(Rule $rule)
{
$this->ruleRepos->moveUp($rule);
return redirect(route('rules.index'));
}
}

View File

@ -0,0 +1,283 @@
<?php
/**
* SelectController.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Rule;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Requests\SelectTransactionsRequest;
use FireflyIII\Http\Requests\TestRuleFormRequest;
use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions;
use FireflyIII\Models\Rule;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Support\Http\Controllers\RuleManagement;
use FireflyIII\TransactionRules\TransactionMatcher;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Collection;
use Log;
use Throwable;
/**
* Class SelectController
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class SelectController extends Controller
{
use RuleManagement;
/** @var AccountRepositoryInterface */
private $accountRepos;
/**
* RuleController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
$this->accountRepos = app(AccountRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Execute the given rule on a set of existing transactions.
*
* @param SelectTransactionsRequest $request
* @param Rule $rule
*
* @return RedirectResponse
*/
public function execute(SelectTransactionsRequest $request, Rule $rule): RedirectResponse
{
// Get parameters specified by the user
/** @var User $user */
$user = auth()->user();
$accounts = $this->accountRepos->getAccountsById($request->get('accounts'));
$startDate = new Carbon($request->get('start_date'));
$endDate = new Carbon($request->get('end_date'));
// Create a job to do the work asynchronously
$job = new ExecuteRuleOnExistingTransactions($rule);
// Apply parameters to the job
$job->setUser($user);
$job->setAccounts($accounts);
$job->setStartDate($startDate);
$job->setEndDate($endDate);
// Dispatch a new job to execute it in a queue
$this->dispatch($job);
// Tell the user that the job is queued
session()->flash('success', (string)trans('firefly.applied_rule_selection', ['title' => $rule->title]));
return redirect()->route('rules.index');
}
/**
* @param Rule $rule
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function selectTransactions(Rule $rule)
{
// does the user have shared accounts?
$first = session('first')->format('Y-m-d');
$today = Carbon::create()->format('Y-m-d');
$subTitle = (string)trans('firefly.apply_rule_selection', ['title' => $rule->title]);
return view('rules.rule.select-transactions', compact('first', 'today', 'rule', 'subTitle'));
}
/**
* This method allows the user to test a certain set of rule triggers. The rule triggers are passed along
* using the URL parameters (GET), and are usually put there using a Javascript thing.
*
* This method will parse and validate those rules and create a "TransactionMatcher" which will attempt
* to find transaction journals matching the users input. A maximum range of transactions to try (range) and
* a maximum number of transactions to return (limit) are set as well.
*
* @param TestRuleFormRequest $request
*
* @return JsonResponse
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function testTriggers(TestRuleFormRequest $request): JsonResponse
{
// build trigger array from response
$triggers = $this->getValidTriggerList($request);
if (0 === \count($triggers)) {
return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]); // @codeCoverageIgnore
}
$limit = (int)config('firefly.test-triggers.limit');
$range = (int)config('firefly.test-triggers.range');
$matchingTransactions = new Collection;
/** @var TransactionMatcher $matcher */
$matcher = app(TransactionMatcher::class);
$matcher->setLimit($limit);
$matcher->setRange($range);
$matcher->setTriggers($triggers);
try {
$matchingTransactions = $matcher->findTransactionsByTriggers();
// @codeCoverageIgnoreStart
} catch (FireflyException $exception) {
Log::error(sprintf('Could not grab transactions in testTriggers(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
}
// @codeCoverageIgnoreStart
// Warn the user if only a subset of transactions is returned
$warning = '';
if ($matchingTransactions->count() === $limit) {
$warning = (string)trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]); // @codeCoverageIgnore
}
if (0 === $matchingTransactions->count()) {
$warning = (string)trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]); // @codeCoverageIgnore
}
// Return json response
$view = 'ERROR, see logs.';
try {
$view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
// @codeCoverageIgnoreStart
} catch (Throwable $exception) {
Log::error(sprintf('Could not render view in testTriggers(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
}
// @codeCoverageIgnoreEnd
return response()->json(['html' => $view, 'warning' => $warning]);
}
/**
* This method allows the user to test a certain set of rule triggers. The rule triggers are grabbed from
* the rule itself.
*
* This method will parse and validate those rules and create a "TransactionMatcher" which will attempt
* to find transaction journals matching the users input. A maximum range of transactions to try (range) and
* a maximum number of transactions to return (limit) are set as well.
*
* @param Rule $rule
*
* @return JsonResponse
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function testTriggersByRule(Rule $rule): JsonResponse
{
$triggers = $rule->ruleTriggers;
if (0 === \count($triggers)) {
return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]); // @codeCoverageIgnore
}
$limit = (int)config('firefly.test-triggers.limit');
$range = (int)config('firefly.test-triggers.range');
$matchingTransactions = new Collection;
/** @var TransactionMatcher $matcher */
$matcher = app(TransactionMatcher::class);
$matcher->setLimit($limit);
$matcher->setRange($range);
$matcher->setRule($rule);
try {
$matchingTransactions = $matcher->findTransactionsByRule();
// @codeCoverageIgnoreStart
} catch (FireflyException $exception) {
Log::error(sprintf('Could not grab transactions in testTriggersByRule(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
}
// @codeCoverageIgnoreEnd
// Warn the user if only a subset of transactions is returned
$warning = '';
if ($matchingTransactions->count() === $limit) {
$warning = (string)trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]); // @codeCoverageIgnore
}
if (0 === $matchingTransactions->count()) {
$warning = (string)trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]); // @codeCoverageIgnore
}
// Return json response
$view = 'ERROR, see logs.';
try {
$view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
// @codeCoverageIgnoreStart
} catch (Throwable $exception) {
Log::error(sprintf('Could not render view in testTriggersByRule(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
}
// @codeCoverageIgnoreEnd
return response()->json(['html' => $view, 'warning' => $warning]);
}
/**
* @param TestRuleFormRequest $request
*
* @return array
*/
private function getValidTriggerList(TestRuleFormRequest $request): array
{
$triggers = [];
$data = [
'rule-triggers' => $request->get('rule-trigger'),
'rule-trigger-values' => $request->get('rule-trigger-value'),
'rule-trigger-stop' => $request->get('rule-trigger-stop'),
];
if (\is_array($data['rule-triggers'])) {
foreach ($data['rule-triggers'] as $index => $triggerType) {
$data['rule-trigger-stop'][$index] = (int)($data['rule-trigger-stop'][$index] ?? 0.0);
$triggers[] = [
'type' => $triggerType,
'value' => $data['rule-trigger-values'][$index],
'stopProcessing' => 1 === (int)$data['rule-trigger-stop'][$index],
];
}
}
return $triggers;
}
}

View File

@ -1,875 +0,0 @@
<?php
/**
* RuleController.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Requests\RuleFormRequest;
use FireflyIII\Http\Requests\SelectTransactionsRequest;
use FireflyIII\Http\Requests\TestRuleFormRequest;
use FireflyIII\Jobs\ExecuteRuleOnExistingTransactions;
use FireflyIII\Models\Bill;
use FireflyIII\Models\Rule;
use FireflyIII\Models\RuleAction;
use FireflyIII\Models\RuleGroup;
use FireflyIII\Models\RuleTrigger;
use FireflyIII\Repositories\Account\AccountRepositoryInterface;
use FireflyIII\Repositories\Bill\BillRepositoryInterface;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use FireflyIII\TransactionRules\TransactionMatcher;
use FireflyIII\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Collection;
use Log;
use Throwable;
/**
* Class RuleController.
*/
class RuleController extends Controller
{
/** @var AccountRepositoryInterface */
private $accountRepos;
/** @var BillRepositoryInterface */
private $billRepos;
/** @var RuleGroupRepositoryInterface */
private $ruleGroupRepos;
/** @var RuleRepositoryInterface */
private $ruleRepos;
/**
* RuleController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', (string)trans('firefly.rules'));
app('view')->share('mainTitleIcon', 'fa-random');
$this->accountRepos = app(AccountRepositoryInterface::class);
$this->billRepos = app(BillRepositoryInterface::class);
$this->ruleGroupRepos = app(RuleGroupRepositoryInterface::class);
$this->ruleRepos = app(RuleRepositoryInterface::class);
return $next($request);
}
);
}
/**
* Create a new rule. It will be stored under the given $ruleGroup.
*
* @param Request $request
* @param RuleGroup $ruleGroup
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function create(Request $request, RuleGroup $ruleGroup)
{
$this->createDefaultRuleGroup();
$this->createDefaultRule();
$bill = null;
$billId = (int)$request->get('fromBill');
$preFilled = [
'strict' => true,
];
$oldTriggers = [];
$oldActions = [];
$returnToBill = false;
if ('true' === $request->get('return')) {
$returnToBill = true;
}
// has bill?
if ($billId > 0) {
$bill = $this->billRepos->find($billId);
}
// has old input?
if ($request->old()) {
$oldTriggers = $this->getPreviousTriggers($request);
$oldActions = $this->getPreviousActions($request);
}
// has existing bill refered to in URI?
if (null !== $bill && !$request->old()) {
// create some sensible defaults:
$preFilled['title'] = (string)trans('firefly.new_rule_for_bill_title', ['name' => $bill->name]);
$preFilled['description'] = (string)trans('firefly.new_rule_for_bill_description', ['name' => $bill->name]);
// get triggers and actions for bill:
$oldTriggers = $this->getTriggersForBill($bill);
$oldActions = $this->getActionsForBill($bill);
}
$triggerCount = \count($oldTriggers);
$actionCount = \count($oldActions);
$subTitleIcon = 'fa-clone';
$subTitle = (string)trans('firefly.make_new_rule', ['title' => $ruleGroup->title]);
$request->session()->flash('preFilled', $preFilled);
// put previous url in session if not redirect from store (not "create another").
if (true !== session('rules.create.fromStore')) {
$this->rememberPreviousUri('rules.create.uri');
}
session()->forget('rules.create.fromStore');
return view(
'rules.rule.create',
compact(
'subTitleIcon', 'oldTriggers', 'returnToBill', 'preFilled', 'bill', 'oldActions', 'triggerCount', 'actionCount', 'ruleGroup',
'subTitle'
)
);
}
/**
* Delete a given rule.
*
* @param Rule $rule
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function delete(Rule $rule)
{
$subTitle = (string)trans('firefly.delete_rule', ['title' => $rule->title]);
// put previous url in session
$this->rememberPreviousUri('rules.delete.uri');
return view('rules.rule.delete', compact('rule', 'subTitle'));
}
/**
* Actually destroy the given rule.
*
* @param Rule $rule
*
* @return RedirectResponse
*/
public function destroy(Rule $rule): RedirectResponse
{
$title = $rule->title;
$this->ruleRepos->destroy($rule);
session()->flash('success', (string)trans('firefly.deleted_rule', ['title' => $title]));
app('preferences')->mark();
return redirect($this->getPreviousUri('rules.delete.uri'));
}
/**
* @param Rule $rule
*
* @return RedirectResponse|\Illuminate\Routing\Redirector
*/
public function down(Rule $rule)
{
$this->ruleRepos->moveDown($rule);
return redirect(route('rules.index'));
}
/**
* @param Request $request
* @param Rule $rule
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function edit(Request $request, Rule $rule)
{
$triggerCount = 0;
$actionCount = 0;
$oldActions = [];
$oldTriggers = [];
// has old input?
if (\count($request->old()) > 0) {
$oldTriggers = $this->getPreviousTriggers($request);
$triggerCount = \count($oldTriggers);
$oldActions = $this->getPreviousActions($request);
$actionCount = \count($oldActions);
}
// overrule old input when it as no rule data:
if (0 === $triggerCount && 0 === $actionCount) {
$oldTriggers = $this->getCurrentTriggers($rule);
$triggerCount = \count($oldTriggers);
$oldActions = $this->getCurrentActions($rule);
$actionCount = \count($oldActions);
}
$hasOldInput = null !== $request->old('_token');
$preFilled = [
'active' => $hasOldInput ? (bool)$request->old('active') : $rule->active,
'stop_processing' => $hasOldInput ? (bool)$request->old('stop_processing') : $rule->stop_processing,
'strict' => $hasOldInput ? (bool)$request->old('strict') : $rule->strict,
];
// get rule trigger for update / store-journal:
$primaryTrigger = $this->ruleRepos->getPrimaryTrigger($rule);
$subTitle = (string)trans('firefly.edit_rule', ['title' => $rule->title]);
// put previous url in session if not redirect from store (not "return_to_edit").
if (true !== session('rules.edit.fromUpdate')) {
$this->rememberPreviousUri('rules.edit.uri');
}
session()->forget('rules.edit.fromUpdate');
$request->session()->flash('preFilled', $preFilled);
return view('rules.rule.edit', compact('rule', 'subTitle', 'primaryTrigger', 'oldTriggers', 'oldActions', 'triggerCount', 'actionCount'));
}
/**
* Execute the given rule on a set of existing transactions.
*
* @param SelectTransactionsRequest $request
* @param Rule $rule
*
* @return RedirectResponse
*
* @internal param RuleGroup $ruleGroup
*/
public function execute(SelectTransactionsRequest $request, Rule $rule): RedirectResponse
{
// Get parameters specified by the user
/** @var User $user */
$user = auth()->user();
$accounts = $this->accountRepos->getAccountsById($request->get('accounts'));
$startDate = new Carbon($request->get('start_date'));
$endDate = new Carbon($request->get('end_date'));
// Create a job to do the work asynchronously
$job = new ExecuteRuleOnExistingTransactions($rule);
// Apply parameters to the job
$job->setUser($user);
$job->setAccounts($accounts);
$job->setStartDate($startDate);
$job->setEndDate($endDate);
// Dispatch a new job to execute it in a queue
$this->dispatch($job);
// Tell the user that the job is queued
session()->flash('success', (string)trans('firefly.applied_rule_selection', ['title' => $rule->title]));
return redirect()->route('rules.index');
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function index()
{
/** @var User $user */
$user = auth()->user();
$this->createDefaultRuleGroup();
$this->createDefaultRule();
$ruleGroups = $this->ruleGroupRepos->getRuleGroupsWithRules($user);
return view('rules.index', compact('ruleGroups'));
}
/**
* @param Request $request
* @param Rule $rule
*
* @return JsonResponse
*/
public function reorderRuleActions(Request $request, Rule $rule): JsonResponse
{
$ids = $request->get('actions');
if (\is_array($ids)) {
$this->ruleRepos->reorderRuleActions($rule, $ids);
}
return response()->json('true');
}
/**
* @param Request $request
* @param Rule $rule
*
* @return JsonResponse
*/
public function reorderRuleTriggers(Request $request, Rule $rule): JsonResponse
{
$ids = $request->get('triggers');
if (\is_array($ids)) {
$this->ruleRepos->reorderRuleTriggers($rule, $ids);
}
return response()->json('true');
}
/**
* @param Rule $rule
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*/
public function selectTransactions(Rule $rule)
{
// does the user have shared accounts?
$first = session('first')->format('Y-m-d');
$today = Carbon::create()->format('Y-m-d');
$subTitle = (string)trans('firefly.apply_rule_selection', ['title' => $rule->title]);
return view('rules.rule.select-transactions', compact('first', 'today', 'rule', 'subTitle'));
}
/**
* @param RuleFormRequest $request
*
* @return RedirectResponse|\Illuminate\Routing\Redirector
*/
public function store(RuleFormRequest $request)
{
$data = $request->getRuleData();
$rule = $this->ruleRepos->store($data);
session()->flash('success', (string)trans('firefly.stored_new_rule', ['title' => $rule->title]));
app('preferences')->mark();
// redirect to show bill.
if ('true' === $request->get('return_to_bill') && (int)$request->get('bill_id') > 0) {
return redirect(route('bills.show', [(int)$request->get('bill_id')])); // @codeCoverageIgnore
}
// redirect to new bill creation.
if ((int)$request->get('bill_id') > 0) {
return redirect($this->getPreviousUri('bills.create.uri')); // @codeCoverageIgnore
}
$redirect = redirect($this->getPreviousUri('rules.create.uri'));
if (1 === (int)$request->get('create_another')) {
// @codeCoverageIgnoreStart
session()->put('rules.create.fromStore', true);
$redirect = redirect(route('rules.create', [$data['rule_group_id']]))->withInput();
// @codeCoverageIgnoreEnd
}
return $redirect;
}
/**
* This method allows the user to test a certain set of rule triggers. The rule triggers are passed along
* using the URL parameters (GET), and are usually put there using a Javascript thing.
*
* This method will parse and validate those rules and create a "TransactionMatcher" which will attempt
* to find transaction journals matching the users input. A maximum range of transactions to try (range) and
* a maximum number of transactions to return (limit) are set as well.
*
* @param TestRuleFormRequest $request
*
* @return JsonResponse
*/
public function testTriggers(TestRuleFormRequest $request): JsonResponse
{
// build trigger array from response
$triggers = $this->getValidTriggerList($request);
if (0 === \count($triggers)) {
return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]); // @codeCoverageIgnore
}
$limit = (int)config('firefly.test-triggers.limit');
$range = (int)config('firefly.test-triggers.range');
$matchingTransactions = new Collection;
/** @var TransactionMatcher $matcher */
$matcher = app(TransactionMatcher::class);
$matcher->setLimit($limit);
$matcher->setRange($range);
$matcher->setTriggers($triggers);
try {
$matchingTransactions = $matcher->findTransactionsByTriggers();
// @codeCoverageIgnoreStart
} catch (FireflyException $exception) {
Log::error(sprintf('Could not grab transactions in testTriggers(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
}
// @codeCoverageIgnoreStart
// Warn the user if only a subset of transactions is returned
$warning = '';
if ($matchingTransactions->count() === $limit) {
$warning = (string)trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]); // @codeCoverageIgnore
}
if (0 === $matchingTransactions->count()) {
$warning = (string)trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]); // @codeCoverageIgnore
}
// Return json response
$view = 'ERROR, see logs.';
try {
$view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
// @codeCoverageIgnoreStart
} catch (Throwable $exception) {
Log::error(sprintf('Could not render view in testTriggers(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
}
// @codeCoverageIgnoreEnd
return response()->json(['html' => $view, 'warning' => $warning]);
}
/**
* This method allows the user to test a certain set of rule triggers. The rule triggers are grabbed from
* the rule itself.
*
* This method will parse and validate those rules and create a "TransactionMatcher" which will attempt
* to find transaction journals matching the users input. A maximum range of transactions to try (range) and
* a maximum number of transactions to return (limit) are set as well.
*
* @param Rule $rule
*
* @return JsonResponse
*/
public function testTriggersByRule(Rule $rule): JsonResponse
{
$triggers = $rule->ruleTriggers;
if (0 === \count($triggers)) {
return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]); // @codeCoverageIgnore
}
$limit = (int)config('firefly.test-triggers.limit');
$range = (int)config('firefly.test-triggers.range');
$matchingTransactions = new Collection;
/** @var TransactionMatcher $matcher */
$matcher = app(TransactionMatcher::class);
$matcher->setLimit($limit);
$matcher->setRange($range);
$matcher->setRule($rule);
try {
$matchingTransactions = $matcher->findTransactionsByRule();
// @codeCoverageIgnoreStart
} catch (FireflyException $exception) {
Log::error(sprintf('Could not grab transactions in testTriggersByRule(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
}
// @codeCoverageIgnoreEnd
// Warn the user if only a subset of transactions is returned
$warning = '';
if ($matchingTransactions->count() === $limit) {
$warning = (string)trans('firefly.warning_transaction_subset', ['max_num_transactions' => $limit]); // @codeCoverageIgnore
}
if (0 === $matchingTransactions->count()) {
$warning = (string)trans('firefly.warning_no_matching_transactions', ['num_transactions' => $range]); // @codeCoverageIgnore
}
// Return json response
$view = 'ERROR, see logs.';
try {
$view = view('list.journals-tiny', ['transactions' => $matchingTransactions])->render();
// @codeCoverageIgnoreStart
} catch (Throwable $exception) {
Log::error(sprintf('Could not render view in testTriggersByRule(): %s', $exception->getMessage()));
Log::error($exception->getTraceAsString());
}
// @codeCoverageIgnoreEnd
return response()->json(['html' => $view, 'warning' => $warning]);
}
/**
* @param Rule $rule
*
* @return RedirectResponse|\Illuminate\Routing\Redirector
*/
public function up(Rule $rule)
{
$this->ruleRepos->moveUp($rule);
return redirect(route('rules.index'));
}
/**
* @param RuleFormRequest $request
* @param Rule $rule
*
* @return RedirectResponse|\Illuminate\Routing\Redirector
*/
public function update(RuleFormRequest $request, Rule $rule)
{
$data = $request->getRuleData();
$this->ruleRepos->update($rule, $data);
session()->flash('success', (string)trans('firefly.updated_rule', ['title' => $rule->title]));
app('preferences')->mark();
$redirect = redirect($this->getPreviousUri('rules.edit.uri'));
if (1 === (int)$request->get('return_to_edit')) {
// @codeCoverageIgnoreStart
session()->put('rules.edit.fromUpdate', true);
$redirect = redirect(route('rules.edit', [$rule->id]))->withInput(['return_to_edit' => 1]);
// @codeCoverageIgnoreEnd
}
return $redirect;
}
/**
*
*/
private function createDefaultRule(): void
{
if (0 === $this->ruleRepos->count()) {
$data = [
'rule_group_id' => $this->ruleRepos->getFirstRuleGroup()->id,
'stop-processing' => 0,
'title' => (string)trans('firefly.default_rule_name'),
'description' => (string)trans('firefly.default_rule_description'),
'trigger' => 'store-journal',
'strict' => true,
'rule-triggers' => [
[
'name' => 'description_is',
'value' => (string)trans('firefly.default_rule_trigger_description'),
'stop-processing' => false,
],
[
'name' => 'from_account_is',
'value' => (string)trans('firefly.default_rule_trigger_from_account'),
'stop-processing' => false,
],
],
'rule-actions' => [
[
'name' => 'prepend_description',
'value' => (string)trans('firefly.default_rule_action_prepend'),
'stop-processing' => false,
],
[
'name' => 'set_category',
'value' => (string)trans('firefly.default_rule_action_set_category'),
'stop-processing' => false,
],
],
];
$this->ruleRepos->store($data);
}
}
/**
*
*/
private function createDefaultRuleGroup(): void
{
if (0 === $this->ruleGroupRepos->count()) {
$data = [
'title' => (string)trans('firefly.default_rule_group_name'),
'description' => (string)trans('firefly.default_rule_group_description'),
];
$this->ruleGroupRepos->store($data);
}
}
/**
* @param Bill $bill
*
* @return array
*/
private function getActionsForBill(Bill $bill): array
{
$actions = [];
try {
$actions[] = view(
'rules.partials.action',
[
'oldAction' => 'link_to_bill',
'oldValue' => $bill->name,
'oldChecked' => false,
'count' => 1,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::error(sprintf('Throwable was thrown in getActionsForBill(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
return $actions;
}
/**
* @param Rule $rule
*
* @return array
*
*/
private function getCurrentActions(Rule $rule): array
{
$index = 0;
$actions = [];
/** @var RuleAction $entry */
foreach ($rule->ruleActions as $entry) {
$count = ($index + 1);
try {
$actions[] = view(
'rules.partials.action',
[
'oldAction' => $entry->action_type,
'oldValue' => $entry->action_value,
'oldChecked' => $entry->stop_processing,
'count' => $count,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
++$index;
}
return $actions;
}
/**
* @param Rule $rule
*
* @return array
*
*/
private function getCurrentTriggers(Rule $rule): array
{
$index = 0;
$triggers = [];
/** @var RuleTrigger $entry */
foreach ($rule->ruleTriggers as $entry) {
if ('user_action' !== $entry->trigger_type) {
$count = ($index + 1);
try {
$triggers[] = view(
'rules.partials.trigger',
[
'oldTrigger' => $entry->trigger_type,
'oldValue' => $entry->trigger_value,
'oldChecked' => $entry->stop_processing,
'count' => $count,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
++$index;
}
}
return $triggers;
}
/**
* @param Request $request
*
* @return array
*
*/
private function getPreviousActions(Request $request): array
{
$newIndex = 0;
$actions = [];
/** @var array $oldActions */
$oldActions = \is_array($request->old('rule-action')) ? $request->old('rule-action') : [];
foreach ($oldActions as $index => $entry) {
$count = ($newIndex + 1);
$checked = isset($request->old('rule-action-stop')[$index]) ? true : false;
try {
$actions[] = view(
'rules.partials.action',
[
'oldAction' => $entry,
'oldValue' => $request->old('rule-action-value')[$index],
'oldChecked' => $checked,
'count' => $count,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
++$newIndex;
}
return $actions;
}
/**
* @param Request $request
*
* @return array
*
*/
private function getPreviousTriggers(Request $request): array
{
$newIndex = 0;
$triggers = [];
/** @var array $oldTriggers */
$oldTriggers = \is_array($request->old('rule-trigger')) ? $request->old('rule-trigger') : [];
foreach ($oldTriggers as $index => $entry) {
$count = ($newIndex + 1);
$oldChecked = isset($request->old('rule-trigger-stop')[$index]) ? true : false;
try {
$triggers[] = view(
'rules.partials.trigger',
[
'oldTrigger' => $entry,
'oldValue' => $request->old('rule-trigger-value')[$index],
'oldChecked' => $oldChecked,
'count' => $count,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
++$newIndex;
}
return $triggers;
}
/**
* Create fake triggers to match the bill's properties
*
* @param Bill $bill
*
* @return array
*/
private function getTriggersForBill(Bill $bill): array
{
$triggers = [];
/** @noinspection BadExceptionsProcessingInspection */
try {
$triggers[] = view(
'rules.partials.trigger',
[
'oldTrigger' => 'currency_is',
'oldValue' => $bill->transactionCurrency()->first()->name,
'oldChecked' => false,
'count' => 1,
]
)->render();
$triggers[] = view(
'rules.partials.trigger',
[
'oldTrigger' => 'amount_more',
'oldValue' => round($bill->amount_min, 12),
'oldChecked' => false,
'count' => 2,
]
)->render();
$triggers[] = view(
'rules.partials.trigger',
[
'oldTrigger' => 'amount_less',
'oldValue' => round($bill->amount_max, 12),
'oldChecked' => false,
'count' => 3,
]
)->render();
$triggers[] = view(
'rules.partials.trigger',
[
'oldTrigger' => 'description_contains',
'oldValue' => $bill->name, 12,
'oldChecked' => false,
'count' => 4,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage()));
Log::debug($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
return $triggers;
}
/**
* @param TestRuleFormRequest $request
*
* @return array
*/
private function getValidTriggerList(TestRuleFormRequest $request): array
{
$triggers = [];
$data = [
'rule-triggers' => $request->get('rule-trigger'),
'rule-trigger-values' => $request->get('rule-trigger-value'),
'rule-trigger-stop' => $request->get('rule-trigger-stop'),
];
if (\is_array($data['rule-triggers'])) {
foreach ($data['rule-triggers'] as $index => $triggerType) {
$data['rule-trigger-stop'][$index] = (int)($data['rule-trigger-stop'][$index] ?? 0.0);
$triggers[] = [
'type' => $triggerType,
'value' => $data['rule-trigger-values'][$index],
'stopProcessing' => 1 === (int)$data['rule-trigger-stop'][$index],
];
}
}
return $triggers;
}
}

View File

@ -35,6 +35,8 @@ use Illuminate\Http\Request;
/**
* Class RuleGroupController.
*
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
*/
class RuleGroupController extends Controller
{
@ -231,6 +233,8 @@ class RuleGroupController extends Controller
* @param RuleGroup $ruleGroup
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @SuppressWarnings(PHPMD.ShortMethodName)
*/
public function up(RuleGroupRepositoryInterface $repository, RuleGroup $ruleGroup)
{

View File

@ -73,7 +73,7 @@ class SearchController extends Controller
* @param SearchInterface $searcher
*
* @return \Illuminate\Http\JsonResponse
* @throws \Throwable
*/
public function search(Request $request, SearchInterface $searcher): JsonResponse
{

View File

@ -166,7 +166,12 @@ class TagController extends Controller
* @param Tag $tag
* @param string|null $moment
*
* TODO will be cleaned up and separated
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function show(Request $request, Tag $tag, string $moment = null)
{
@ -286,6 +291,8 @@ class TagController extends Controller
* @param Tag $tag
*
* @return Collection
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
private function getPeriodOverview(Tag $tag): Collection
{

View File

@ -87,6 +87,8 @@ class BulkController extends Controller
* @param BulkEditJournalRequest $request
*
* @return mixed
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function update(BulkEditJournalRequest $request)
{

View File

@ -82,16 +82,14 @@ class ConvertController extends Controller
$subTitle = (string)trans('firefly.convert_to_' . $destinationType->type, ['description' => $journal->description]);
$subTitleIcon = 'fa-exchange';
// cannot convert to its own type.
if ($sourceType->type === $destinationType->type) {
if ($sourceType->type === $destinationType->type) { // cannot convert to its own type.
Log::debug('This is already a transaction of the expected type..');
session()->flash('info', (string)trans('firefly.convert_is_already_type_' . $destinationType->type));
return redirect(route('transactions.show', [$journal->id]));
}
// cannot convert split.
if ($journal->transactions()->count() > 2) {
if ($journal->transactions()->count() > 2) { // cannot convert split.
Log::info('This journal has more than two transactions.');
session()->flash('error', (string)trans('firefly.cannot_convert_split_journal'));
@ -119,7 +117,8 @@ class ConvertController extends Controller
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @throws FireflyException
* @throws FireflyException
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function postIndex(Request $request, TransactionType $destinationType, TransactionJournal $journal)
{
@ -172,6 +171,9 @@ class ConvertController extends Controller
* @return Account
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function getDestinationAccount(TransactionJournal $journal, TransactionType $destinationType, array $data): Account
{
@ -228,6 +230,9 @@ class ConvertController extends Controller
* @return Account
*
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function getSourceAccount(TransactionJournal $journal, TransactionType $destinationType, array $data): Account
{

View File

@ -101,13 +101,7 @@ class LinkController extends Controller
Log::debug('We are here (store)');
$linkInfo = $request->getLinkInfo();
if (0 === $linkInfo['transaction_journal_id']) {
session()->flash('error', (string)trans('firefly.invalid_link_selection'));
return redirect(route('transactions.show', [$journal->id]));
}
$other = $this->journalRepository->findNull($linkInfo['transaction_journal_id']);
$other = $this->journalRepository->findNull($linkInfo['transaction_journal_id']);
if (null === $other) {
session()->flash('error', (string)trans('firefly.invalid_link_selection'));

View File

@ -42,6 +42,8 @@ use Symfony\Component\HttpFoundation\ParameterBag;
/**
* Class MassController.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class MassController extends Controller
{
@ -85,29 +87,24 @@ class MassController extends Controller
* @param MassDeleteJournalRequest $request
*
* @return mixed
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function destroy(MassDeleteJournalRequest $request)
{
$ids = $request->get('confirm_mass_delete');
$set = new Collection;
$ids = $request->get('confirm_mass_delete');
$count = 0;
if (\is_array($ids)) {
/** @var string $journalId */
foreach ($ids as $journalId) {
/** @var TransactionJournal $journal */
$journal = $this->repository->findNull((int)$journalId);
if (null !== $journal && (int)$journalId === $journal->id) {
$set->push($journal);
$this->repository->destroy($journal);
++$count;
}
}
}
unset($journal);
$count = 0;
/** @var TransactionJournal $journal */
foreach ($set as $journal) {
$this->repository->destroy($journal);
++$count;
}
app('preferences')->mark();
session()->flash('success', (string)trans('firefly.mass_deleted_transactions_success', ['amount' => $count]));
@ -127,20 +124,16 @@ class MassController extends Controller
$user = auth()->user();
$subTitle = (string)trans('firefly.mass_edit_journals');
/** @var AccountRepositoryInterface $repository */
$repository = app(AccountRepositoryInterface::class);
$accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]);
// get budgets
/** @var BudgetRepositoryInterface $budgetRepository */
$budgetRepository = app(BudgetRepositoryInterface::class);
$budgets = $budgetRepository->getBudgets();
// put previous url in session
$this->rememberPreviousUri('transactions.mass-edit.uri');
// use the collector to get them.
$transformer = new TransactionTransformer(new ParameterBag);
/** @var JournalCollectorInterface $collector */
$collector = app(JournalCollectorInterface::class);
@ -148,12 +141,7 @@ class MassController extends Controller
$collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation();
$collector->setJournals($journals);
$collector->addFilter(TransactionViewFilter::class);
$collection = $collector->getJournals();
// add some filters:
// transform to array
$collection = $collector->getJournals();
$transactions = $collection->map(
function (Transaction $transaction) use ($transformer) {
$transformed = $transformer->transform($transaction);
@ -173,6 +161,8 @@ class MassController extends Controller
* @param JournalRepositoryInterface $repository
*
* @return mixed
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function update(MassEditJournalRequest $request, JournalRepositoryInterface $repository)
{

View File

@ -41,6 +41,8 @@ use View;
/**
* Class SingleController.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class SingleController extends Controller
{
@ -82,6 +84,8 @@ class SingleController extends Controller
* @param TransactionJournal $journal
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function cloneTransaction(TransactionJournal $journal)
{
@ -137,6 +141,8 @@ class SingleController extends Controller
* @param string|null $what
*
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function create(Request $request, string $what = null)
{
@ -203,8 +209,6 @@ class SingleController extends Controller
* @param TransactionJournal $transactionJournal
*
* @return \Illuminate\Http\RedirectResponse
*
* @internal param JournalRepositoryInterface $repository
*/
public function destroy(TransactionJournal $transactionJournal): RedirectResponse
{
@ -229,6 +233,9 @@ class SingleController extends Controller
* @param JournalRepositoryInterface $repository
*
* @return mixed
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function edit(TransactionJournal $journal, JournalRepositoryInterface $repository)
{
@ -319,6 +326,10 @@ class SingleController extends Controller
*
* @return RedirectResponse
* @throws \FireflyIII\Exceptions\FireflyException
*
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function store(JournalFormRequest $request, JournalRepositoryInterface $repository): RedirectResponse
{
@ -377,6 +388,9 @@ class SingleController extends Controller
* @param TransactionJournal $journal
*
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function update(JournalFormRequest $request, JournalRepositoryInterface $repository, TransactionJournal $journal)
{

View File

@ -42,6 +42,7 @@ use View;
/**
* Class SplitController.
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class SplitController extends Controller
{
@ -122,6 +123,9 @@ class SplitController extends Controller
* @param TransactionJournal $journal
*
* @return $this|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function update(SplitJournalFormRequest $request, TransactionJournal $journal)
{
@ -216,6 +220,8 @@ class SplitController extends Controller
*
* @return array
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function getTransactionDataFromJournal(TransactionJournal $journal): array
{
@ -253,6 +259,9 @@ class SplitController extends Controller
* @param $old
*
* @return array
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function updateWithPrevious($array, $old): array
{

View File

@ -45,6 +45,8 @@ use View;
/**
* Class TransactionController.
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class TransactionController extends Controller
{
@ -174,6 +176,7 @@ class TransactionController extends Controller
* @param Request $request
*
* @return \Illuminate\Http\JsonResponse
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function reorder(Request $request): JsonResponse
{
@ -241,6 +244,9 @@ class TransactionController extends Controller
* @param Carbon $date
*
* @return Collection
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function getPeriodOverview(string $what, Carbon $date): Collection
{
@ -277,7 +283,6 @@ class TransactionController extends Controller
'name' => $dateName,
'sums' => $sums,
'sum' => $sum,
'start' => $currentDate['start']->format('Y-m-d'),
'end' => $currentDate['end']->format('Y-m-d'),
]

View File

@ -41,7 +41,7 @@ class StartFireflySession extends StartSession
{
$uri = $request->fullUrl();
$strpos = strpos($uri, 'jscript');
if (false === $strpos && 'GET' === $request->method() && $request->route() && !$request->ajax()) {
if (false === $strpos && 'GET' === $request->method() && !$request->ajax()) {
$session->setPreviousUrl($uri);
}
}

View File

@ -40,7 +40,7 @@ class TrustProxies extends Middleware
*
* @var array|string
*/
protected $proxies;
protected $proxies = [];
/**
* TrustProxies constructor.
@ -49,17 +49,8 @@ class TrustProxies extends Middleware
*/
public function __construct(Repository $config)
{
$trustedProxies = env('TRUSTED_PROXIES', null);
if (false !== $trustedProxies && null !== $trustedProxies && \strlen($trustedProxies) > 0) {
if ('*' === $trustedProxies || '**' === $trustedProxies) {
$this->proxies = $trustedProxies;
}
if ('*' !== $trustedProxies && '**' !== $trustedProxies) {
$this->proxies = explode(',', $trustedProxies);
}
}
$trustedProxies = (string)env('TRUSTED_PROXIES', null);
$this->proxies = explode(',', $trustedProxies);
parent::__construct($config);
}
}

View File

@ -45,6 +45,8 @@ class JournalFormRequest extends Request
* Returns and validates the data required to store a new journal. Can handle both single transaction journals and split journals.
*
* @return array
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function getJournalData(): array
{
@ -240,61 +242,79 @@ class JournalFormRequest extends Request
$type = $data['what'] ?? 'invalid';
Log::debug(sprintf('Type is %s', $type));
if ('withdrawal' === $type) {
$selectedCurrency = (int)($data['amount_currency_id_amount'] ?? 0);
$accountCurrency = (int)($data['source_account_currency'] ?? 0);
Log::debug(sprintf('Selected currency is %d, account currency is %d', $selectedCurrency, $accountCurrency));
$nativeAmount = (string)($data['native_amount'] ?? '');
if ($selectedCurrency !== $accountCurrency && '' === $nativeAmount
&& 0 !== $selectedCurrency
&& 0 !== $accountCurrency
) {
Log::debug('ADD validation error on native_amount');
$validator->errors()->add('native_amount', (string)trans('validation.numeric_native'));
return;
}
$this->validateWithdrawal($validator);
}
// same thing for deposits:
if ('deposit' === $type) {
$selectedCurrency = (int)($data['amount_currency_id_amount'] ?? 0);
$accountCurrency = (int)($data['destination_account_currency'] ?? 0);
$nativeAmount = (string)($data['native_amount'] ?? '');
if ($selectedCurrency !== $accountCurrency && '' === $nativeAmount
&& 0 !== $selectedCurrency
&& 0 !== $accountCurrency
) {
$validator->errors()->add('native_amount', (string)trans('validation.numeric_native'));
return;
}
$this->validateDeposit($validator);
}
// and for transfers
if ('transfer' === $type) {
$this->validateTransfer($validator);
}
}
$sourceCurrency = (int)($data['source_account_currency'] ?? 0);
$destinationCurrency = (int)($data['destination_account_currency'] ?? 0);
$sourceAmount = (string)($data['source_amount'] ?? '');
$destinationAmount = (string)($data['destination_amount'] ?? '');
/**
* @param Validator $validator
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function validateDeposit(Validator $validator): void
{
$selectedCurrency = (int)($data['amount_currency_id_amount'] ?? 0);
$accountCurrency = (int)($data['destination_account_currency'] ?? 0);
$nativeAmount = (string)($data['native_amount'] ?? '');
if ($selectedCurrency !== $accountCurrency && '' === $nativeAmount && 0 !== $selectedCurrency && 0 !== $accountCurrency) {
$validator->errors()->add('native_amount', (string)trans('validation.numeric_native'));
Log::debug(sprintf('Source currency is %d, destination currency is %d', $sourceCurrency, $destinationCurrency));
return;
}
}
if ($sourceCurrency !== $destinationCurrency && '' === $sourceAmount
&& 0 !== $sourceCurrency
&& 0 !== $destinationCurrency
) {
$validator->errors()->add('source_amount', (string)trans('validation.numeric_source'));
}
/**
* @param Validator $validator
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function validateTransfer(Validator $validator): void
{
$sourceCurrency = (int)($data['source_account_currency'] ?? 0);
$destinationCurrency = (int)($data['destination_account_currency'] ?? 0);
$sourceAmount = (string)($data['source_amount'] ?? '');
$destinationAmount = (string)($data['destination_amount'] ?? '');
if ($sourceCurrency !== $destinationCurrency && '' === $destinationAmount
&& 0 !== $sourceCurrency
&& 0 !== $destinationCurrency
) {
$validator->errors()->add('destination_amount', (string)trans('validation.numeric_destination'));
$validator->errors()->add('destination_amount', (string)trans('validation.numeric', ['attribute' => 'destination_amount']));
}
Log::debug(sprintf('Source currency is %d, destination currency is %d', $sourceCurrency, $destinationCurrency));
if ($sourceCurrency !== $destinationCurrency && '' === $sourceAmount && 0 !== $sourceCurrency && 0 !== $destinationCurrency) {
$validator->errors()->add('source_amount', (string)trans('validation.numeric_source'));
}
if ($sourceCurrency !== $destinationCurrency && '' === $destinationAmount && 0 !== $sourceCurrency && 0 !== $destinationCurrency) {
$validator->errors()->add('destination_amount', (string)trans('validation.numeric_destination'));
$validator->errors()->add('destination_amount', (string)trans('validation.numeric', ['attribute' => 'destination_amount']));
}
}
/**
* @param Validator $validator
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function validateWithdrawal(Validator $validator): void
{
$data = $validator->getData();
$selectedCurrency = (int)($data['amount_currency_id_amount'] ?? 0);
$accountCurrency = (int)($data['source_account_currency'] ?? 0);
Log::debug(sprintf('Selected currency is %d, account currency is %d', $selectedCurrency, $accountCurrency));
$nativeAmount = (string)($data['native_amount'] ?? '');
if ($selectedCurrency !== $accountCurrency && '' === $nativeAmount
&& 0 !== $selectedCurrency
&& 0 !== $accountCurrency
) {
Log::debug('ADD validation error on native_amount');
$validator->errors()->add('native_amount', (string)trans('validation.numeric_native'));
return;
}

View File

@ -48,6 +48,9 @@ class RecurrenceFormRequest extends Request
/**
* @return array
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function getAll(): array
{
@ -132,6 +135,10 @@ class RecurrenceFormRequest extends Request
/**
* @return array
* @throws FireflyException
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function rules(): array
{
@ -222,6 +229,8 @@ class RecurrenceFormRequest extends Request
/**
* @return array
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
private function parseRepetitionData(): array
{

View File

@ -27,6 +27,8 @@ use Illuminate\Foundation\Http\FormRequest;
/**
* Class Request.
*
* @SuppressWarnings(PHPMD.NumberOfChildren)
*/
class Request extends FormRequest
{
@ -71,6 +73,8 @@ class Request extends FormRequest
* @param string $field
*
* @return string
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function string(string $field): string
{

View File

@ -40,6 +40,9 @@ class RuleFormRequest extends Request
/**
* @return array
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function getRuleData(): array
{

View File

@ -40,6 +40,9 @@ class SplitJournalFormRequest extends Request
/**
* @return array
*
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function getAll(): array
{
@ -147,6 +150,8 @@ class SplitJournalFormRequest extends Request
/**
* @param Validator $validator
*
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
protected function sameAccounts(Validator $validator): void
{

View File

@ -36,7 +36,6 @@ use Illuminate\Support\Collection;
/**
* Interface RecurringRepositoryInterface
*
* @package FireflyIII\Repositories\Recurring
*/
interface RecurringRepositoryInterface
{

View File

@ -41,7 +41,6 @@ use Log;
/**
* Trait RecurringTransactionTrait
*
* @package FireflyIII\Services\Internal\Support
*/
trait RecurringTransactionTrait
{

View File

@ -30,7 +30,6 @@ use Log;
/**
* Trait TransactionTypeTrait
*
* @package FireflyIII\Services\Internal\Support
*/
trait TransactionTypeTrait
{

View File

@ -23,8 +23,12 @@ declare(strict_types=1);
namespace FireflyIII\Support\Binder;
use Carbon\Carbon;
use FireflyIII\Import\Prerequisites\PrerequisitesInterface;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Routing\Route;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Log;
/**
* Class ImportProvider.
@ -40,10 +44,63 @@ class ImportProvider implements BinderInterface
*/
public static function routeBinder(string $value, Route $route): string
{
$providers = array_keys((array)config('import.enabled'));
$providers = array_keys(self::getProviders());
if (\in_array($value, $providers, true)) {
return $value;
}
throw new NotFoundHttpException;
}
/**
* @return array
*/
public static function getProviders(): array
{
$repository = app(UserRepositoryInterface::class);
// get and filter all import routines:
/** @var User $user */
$user = auth()->user();
/** @var array $config */
$providerNames = array_keys(config('import.enabled'));
$providers = [];
$isDemoUser = $repository->hasRole($user, 'demo');
$isDebug = (bool)config('app.debug');
foreach ($providerNames as $providerName) {
//Log::debug(sprintf('Now with provider %s', $providerName));
// only consider enabled providers
$enabled = (bool)config(sprintf('import.enabled.%s', $providerName));
$allowedForDemo = (bool)config(sprintf('import.allowed_for_demo.%s', $providerName));
$allowedForUser = (bool)config(sprintf('import.allowed_for_user.%s', $providerName));
if (false === $enabled) {
//Log::debug('Provider is not enabled. NEXT!');
continue;
}
if (true === $isDemoUser && false === $allowedForDemo) {
//Log::debug('User is demo and this provider is not allowed for demo user. NEXT!');
continue;
}
if (false === $isDemoUser && false === $allowedForUser && false === $isDebug) {
//Log::debug('User is not demo and this provider is not allowed for such users. NEXT!');
continue; // @codeCoverageIgnore
}
$providers[$providerName] = [
'has_prereq' => (bool)config('import.has_prereq.' . $providerName),
];
$class = (string)config(sprintf('import.prerequisites.%s', $providerName));
$result = false;
if ('' !== $class && class_exists($class)) {
//Log::debug('Will not check prerequisites.');
/** @var PrerequisitesInterface $object */
$object = app($class);
$object->setUser($user);
$result = $object->isComplete();
}
$providers[$providerName]['prereq_complete'] = $result;
}
Log::debug(sprintf('Enabled providers: %s', json_encode(array_keys($providers))));
return $providers;
}
}

View File

@ -52,7 +52,7 @@ class ExpandedForm
* @param null $options
*
* @return string
* @throws \Throwable
*/
public function activeAssetAccountList(string $name, $value = null, array $options = []): string
{
@ -93,7 +93,7 @@ class ExpandedForm
*
* @return string
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \Throwable
*/
public function amount(string $name, $value = null, array $options = []): string
{
@ -106,7 +106,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function amountNoCurrency(string $name, $value = null, array $options = []): string
{
@ -145,7 +145,7 @@ class ExpandedForm
* @param null $options
*
* @return string
* @throws \Throwable
*/
public function assetAccountCheckList(string $name, $options = null): string
{
@ -183,7 +183,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function assetAccountList(string $name, $value = null, array $options = []): string
{
@ -225,7 +225,7 @@ class ExpandedForm
*
* @return string
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \Throwable
*/
public function balance(string $name, $value = null, array $options = []): string
{
@ -239,7 +239,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function checkbox(string $name, $value = 1, $checked = null, $options = []): string
{
@ -268,7 +268,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function currencyList(string $name, $value = null, array $options = []): string
{
@ -293,7 +293,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function currencyListEmpty(string $name, $value = null, array $options = []): string
{
@ -320,7 +320,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function date(string $name, $value = null, array $options = []): string
{
@ -339,7 +339,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function file(string $name, array $options = []): string
{
@ -357,7 +357,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function integer(string $name, $value = null, array $options = []): string
{
@ -377,7 +377,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function location(string $name, $value = null, array $options = []): string
{
@ -450,7 +450,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function multiRadio(string $name, array $list = [], $selected = null, array $options = []): string
{
@ -472,7 +472,7 @@ class ExpandedForm
*
* @return string
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \Throwable
*/
public function nonSelectableAmount(string $name, $value = null, array $options = []): string
{
@ -501,7 +501,7 @@ class ExpandedForm
*
* @return string
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \Throwable
*/
public function nonSelectableBalance(string $name, $value = null, array $options = []): string
{
@ -530,7 +530,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function number(string $name, $value = null, array $options = []): string
{
@ -551,7 +551,7 @@ class ExpandedForm
* @param string $name
*
* @return string
* @throws \Throwable
*/
public function optionsList(string $type, string $name): string
{
@ -565,7 +565,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function password(string $name, array $options = null): string
{
@ -584,7 +584,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function piggyBankList(string $name, $value = null, array $options = null): string
{
@ -610,7 +610,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function ruleGroupList(string $name, $value = null, array $options = []): string
{
@ -664,7 +664,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function select(string $name, array $list = [], $selected = null, array $options = []): string
{
@ -684,7 +684,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function staticText(string $name, $value, array $options = []): string
{
@ -702,7 +702,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function tags(string $name, $value = null, array $options = []): string
{
@ -722,7 +722,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function text(string $name, $value = null, array $options = []): string
{
@ -741,7 +741,7 @@ class ExpandedForm
* @param array $options
*
* @return string
* @throws \Throwable
*/
public function textarea(string $name, $value = null, array $options = []): string
{
@ -843,7 +843,7 @@ class ExpandedForm
* @return string
*
* @throws \FireflyIII\Exceptions\FireflyException
* @throws \Throwable
*/
private function currencyField(string $name, string $view, $value = null, array $options = []): string
{

View File

@ -29,7 +29,6 @@ use Log;
/**
* Trait DateCalculation
*
* @package FireflyIII\Support\Http\Controllers
*/
trait DateCalculation
{

View File

@ -0,0 +1,177 @@
<?php
/**
* RuleManagement.php
* Copyright (c) 2018 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Support\Http\Controllers;
use FireflyIII\Repositories\Rule\RuleRepositoryInterface;
use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface;
use Illuminate\Http\Request;
use Log;
use Throwable;
/**
* Trait RuleManagement
*
* @package FireflyIII\Support\Http\Controllers
*/
trait RuleManagement
{
/**
*
*/
protected function createDefaultRule(): void
{
/** @var RuleRepositoryInterface $ruleRepository */
$ruleRepository = app(RuleRepositoryInterface::class);
if (0 === $ruleRepository->count()) {
$data = [
'rule_group_id' => $ruleRepository->getFirstRuleGroup()->id,
'stop-processing' => 0,
'title' => (string)trans('firefly.default_rule_name'),
'description' => (string)trans('firefly.default_rule_description'),
'trigger' => 'store-journal',
'strict' => true,
'rule-triggers' => [
[
'name' => 'description_is',
'value' => (string)trans('firefly.default_rule_trigger_description'),
'stop-processing' => false,
],
[
'name' => 'from_account_is',
'value' => (string)trans('firefly.default_rule_trigger_from_account'),
'stop-processing' => false,
],
],
'rule-actions' => [
[
'name' => 'prepend_description',
'value' => (string)trans('firefly.default_rule_action_prepend'),
'stop-processing' => false,
],
[
'name' => 'set_category',
'value' => (string)trans('firefly.default_rule_action_set_category'),
'stop-processing' => false,
],
],
];
$ruleRepository->store($data);
}
}
/**
* @param Request $request
*
* @return array
*
*/
protected function getPreviousActions(Request $request): array
{
$newIndex = 0;
$actions = [];
/** @var array $oldActions */
$oldActions = \is_array($request->old('rule-action')) ? $request->old('rule-action') : [];
foreach ($oldActions as $index => $entry) {
$count = ($newIndex + 1);
$checked = isset($request->old('rule-action-stop')[$index]) ? true : false;
try {
$actions[] = view(
'rules.partials.action',
[
'oldAction' => $entry,
'oldValue' => $request->old('rule-action-value')[$index],
'oldChecked' => $checked,
'count' => $count,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
++$newIndex;
}
return $actions;
}
/**
* @param Request $request
*
* @return array
*/
protected function getPreviousTriggers(Request $request): array
{
$newIndex = 0;
$triggers = [];
/** @var array $oldTriggers */
$oldTriggers = \is_array($request->old('rule-trigger')) ? $request->old('rule-trigger') : [];
foreach ($oldTriggers as $index => $entry) {
$count = ($newIndex + 1);
$oldChecked = isset($request->old('rule-trigger-stop')[$index]) ? true : false;
try {
$triggers[] = view(
'rules.partials.trigger',
[
'oldTrigger' => $entry,
'oldValue' => $request->old('rule-trigger-value')[$index],
'oldChecked' => $oldChecked,
'count' => $count,
]
)->render();
// @codeCoverageIgnoreStart
} catch (Throwable $e) {
Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()));
Log::error($e->getTraceAsString());
}
// @codeCoverageIgnoreEnd
++$newIndex;
}
return $triggers;
}
/**
*
*/
private function createDefaultRuleGroup(): void
{
/** @var RuleGroupRepositoryInterface $repository */
$repository = app(RuleGroupRepositoryInterface::class);
if (0 === $repository->count()) {
$data = [
'title' => (string)trans('firefly.default_rule_group_name'),
'description' => (string)trans('firefly.default_rule_group_description'),
];
$repository->store($data);
}
}
}

View File

@ -32,7 +32,6 @@ use Log;
/**
* Trait GetSpectreTokenTrait
*
* @package FireflyIII\Support\Import\Information
*/
trait GetSpectreTokenTrait
{

View File

@ -33,7 +33,6 @@ use InvalidArgumentException;
*
* Contains advanced validation rules used in validation of new and existing recurrences.
*
* @package FireflyIII\Validation
*/
trait RecurrenceValidation
{

View File

@ -33,8 +33,6 @@ use Log;
/**
* Trait TransactionValidation
*
* @package FireflyIII\Validation
*/
trait TransactionValidation
{

13
composer.lock generated
View File

@ -5126,12 +5126,12 @@
"source": {
"type": "git",
"url": "https://github.com/Roave/SecurityAdvisories.git",
"reference": "731d60f7fc78a8816dae7049df255cd55e30c313"
"reference": "053766d789f6393e5bc0896635d35abf8d2d362e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/731d60f7fc78a8816dae7049df255cd55e30c313",
"reference": "731d60f7fc78a8816dae7049df255cd55e30c313",
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/053766d789f6393e5bc0896635d35abf8d2d362e",
"reference": "053766d789f6393e5bc0896635d35abf8d2d362e",
"shasum": ""
},
"conflict": {
@ -5180,7 +5180,7 @@
"kreait/firebase-php": ">=3.2,<3.8.1",
"laravel/framework": ">=4,<4.0.99|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15",
"laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10",
"magento/magento1ce": ">=1.5.0.1,<1.9.3.2",
"magento/magento1ce": "<1.9.3.9",
"magento/magento1ee": ">=1.9,<1.14.3.2",
"magento/product-community-edition": ">=2,<2.2.5",
"monolog/monolog": ">=1.8,<1.12",
@ -5238,7 +5238,8 @@
"thelia/thelia": ">=2.1,<2.1.2|>=2.1.0-beta1,<2.1.3",
"titon/framework": ">=0,<9.9.99",
"twig/twig": "<1.20",
"typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.22|>=8,<8.7.5",
"typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.30|>=8,<8.7.17|>=9,<9.3.2",
"typo3/cms-core": ">=8,<8.7.17|>=9,<9.3.2",
"typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5",
"typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4",
"willdurand/js-translation-bundle": "<2.1.1",
@ -5287,7 +5288,7 @@
}
],
"description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it",
"time": "2018-07-09T14:09:25+00:00"
"time": "2018-07-18T13:51:34+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",