diff --git a/.deploy/docker/entrypoint.sh b/.deploy/docker/entrypoint.sh index e88cc8cf85..2a6f7cf013 100755 --- a/.deploy/docker/entrypoint.sh +++ b/.deploy/docker/entrypoint.sh @@ -16,8 +16,8 @@ mkdir -p $FIREFLY_PATH/storage/upload # make sure we own the volumes: -chown -R www-data:www-data -R $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/logs $FIREFLY_PATH/storage/framework/cache -chmod -R 775 $FIREFLY_PATH/storage/export $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/upload $FIREFLY_PATH/storage/logs $FIREFLY_PATH/storage/framework/cache +chown -R www-data:www-data -R $FIREFLY_PATH/storage +chmod -R 775 $FIREFLY_PATH/storage # remove any lingering files that may break upgrades: rm -f $FIREFLY_PATH/storage/logs/laravel.log diff --git a/.dockerignore b/.dockerignore index f42d602ac3..b2ed1beb40 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,4 +1,3 @@ # Ignore composer specific files and vendor folder composer.phar -composer.lock vendor diff --git a/.sandstorm/changelog.md b/.sandstorm/changelog.md index c6415e473d..0019fa8391 100644 --- a/.sandstorm/changelog.md +++ b/.sandstorm/changelog.md @@ -1,3 +1,12 @@ +# 4.7.5.1 +- [Issue 1531](https://github.com/firefly-iii/firefly-iii/issues/1531), the database routine incorrectly reports empty categories. +- [Issue 1532](https://github.com/firefly-iii/firefly-iii/issues/1532), broken dropdown for autosuggest things. +- [Issue 1533](https://github.com/firefly-iii/firefly-iii/issues/1533), fix where the import could not import category names. +- [Issue 1538](https://github.com/firefly-iii/firefly-iii/issues/1538), fix a bug where Spectre would not work when ignoring rules. +- [Issue 1542](https://github.com/firefly-iii/firefly-iii/issues/1542), fix a bug where the importer was incapable of generating new currencies. +- [Issue 1541](https://github.com/firefly-iii/firefly-iii/issues/1541), no longer ignore composer.lock in Docker ignore. +- Bills are stored inactive. + # 4.7.5 - A new feature called "recurring transactions" that will make Firefly III automatically create transactions for you. - New API end points for attachments, available budgets, budgets, budget limits, categories, configuration, currency exchange rates, journal links, link types, piggy banks, preferences, recurring transactions, rules, rule groups and tags. diff --git a/.sandstorm/sandstorm-pkgdef.capnp b/.sandstorm/sandstorm-pkgdef.capnp index 3f86b4e979..211be58c8a 100644 --- a/.sandstorm/sandstorm-pkgdef.capnp +++ b/.sandstorm/sandstorm-pkgdef.capnp @@ -16,7 +16,7 @@ const pkgdef :Spk.PackageDefinition = ( manifest = ( appTitle = (defaultText = "Firefly III"), appVersion = 14, - appMarketingVersion = (defaultText = "4.7.5"), + appMarketingVersion = (defaultText = "4.7.5.1"), actions = [ # Define your "new document" handlers here. diff --git a/app/Api/V1/Controllers/AboutController.php b/app/Api/V1/Controllers/AboutController.php index 2f7795d05c..7c5e034bb3 100644 --- a/app/Api/V1/Controllers/AboutController.php +++ b/app/Api/V1/Controllers/AboutController.php @@ -35,7 +35,7 @@ use League\Fractal\Serializer\JsonApiSerializer; /** * Returns basic information about this installation. * - * Class AboutController + * Class AboutController. */ class AboutController extends Controller { diff --git a/app/Api/V1/Controllers/AccountController.php b/app/Api/V1/Controllers/AccountController.php index f7bd0580f2..9fef764538 100644 --- a/app/Api/V1/Controllers/AccountController.php +++ b/app/Api/V1/Controllers/AccountController.php @@ -1,5 +1,4 @@ [ - AccountType::DEFAULT, - AccountType::CASH, - AccountType::ASSET, - AccountType::EXPENSE, - AccountType::REVENUE, - AccountType::INITIAL_BALANCE, - AccountType::BENEFICIARY, - AccountType::IMPORT, - AccountType::RECONCILIATION, - AccountType::LOAN, - ], - 'asset' => [ - AccountType::DEFAULT, - AccountType::ASSET, - ], - 'cash' => [ - AccountType::CASH, - ], - 'expense' => [ - AccountType::EXPENSE, - AccountType::BENEFICIARY, - ], - 'revenue' => [ - AccountType::REVENUE, - ], - 'special' => [ - AccountType::CASH, - AccountType::INITIAL_BALANCE, - AccountType::IMPORT, - AccountType::RECONCILIATION, - AccountType::LOAN, - ], - 'hidden' => [ - AccountType::INITIAL_BALANCE, - AccountType::IMPORT, - AccountType::RECONCILIATION, - AccountType::LOAN, - ], + $types = [ + 'all' => [AccountType::DEFAULT, AccountType::CASH, AccountType::ASSET, AccountType::EXPENSE, AccountType::REVENUE, + AccountType::INITIAL_BALANCE, AccountType::BENEFICIARY, AccountType::IMPORT, AccountType::RECONCILIATION, + AccountType::LOAN,], + 'asset' => [AccountType::DEFAULT, AccountType::ASSET,], + 'cash' => [AccountType::CASH,], + 'expense' => [AccountType::EXPENSE, AccountType::BENEFICIARY,], + 'revenue' => [AccountType::REVENUE,], + 'special' => [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION, + AccountType::LOAN,], + 'hidden' => [AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION, AccountType::LOAN,], AccountType::DEFAULT => [AccountType::DEFAULT], AccountType::CASH => [AccountType::CASH], AccountType::ASSET => [AccountType::ASSET], @@ -254,10 +232,11 @@ class AccountController extends Controller AccountType::RECONCILIATION => [AccountType::RECONCILIATION], AccountType::LOAN => [AccountType::LOAN], ]; + $return = $types['all']; if (isset($types[$type])) { - return $types[$type]; + $return = $types[$type]; } - return $types['all']; // @codeCoverageIgnore + return $return; // @codeCoverageIgnore } } diff --git a/app/Api/V1/Controllers/AttachmentController.php b/app/Api/V1/Controllers/AttachmentController.php index 8dae717b38..c416e57a7f 100644 --- a/app/Api/V1/Controllers/AttachmentController.php +++ b/app/Api/V1/Controllers/AttachmentController.php @@ -41,11 +41,13 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** - * Class AttachmentController + * Class AttachmentController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class AttachmentController extends Controller { - /** @var AttachmentRepositoryInterface */ + /** @var AttachmentRepositoryInterface The attachment repository */ private $repository; /** @@ -81,6 +83,8 @@ class AttachmentController extends Controller } /** + * Download an attachment. + * * @param Attachment $attachment * * @return LaravelResponse @@ -88,7 +92,7 @@ class AttachmentController extends Controller */ public function download(Attachment $attachment): LaravelResponse { - if ($attachment->uploaded === false) { + if (false === $attachment->uploaded) { throw new FireflyException('No file has been uploaded for this attachment (yet).'); } if ($this->repository->exists($attachment)) { @@ -211,6 +215,8 @@ class AttachmentController extends Controller } /** + * Upload an attachment. + * * @param Request $request * @param Attachment $attachment * diff --git a/app/Api/V1/Controllers/AvailableBudgetController.php b/app/Api/V1/Controllers/AvailableBudgetController.php index ee182bb457..92fbfae79f 100644 --- a/app/Api/V1/Controllers/AvailableBudgetController.php +++ b/app/Api/V1/Controllers/AvailableBudgetController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers; use FireflyIII\Api\V1\Requests\AvailableBudgetRequest; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\AvailableBudget; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; @@ -39,13 +40,15 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** - * Class AvailableBudgetController + * Class AvailableBudgetController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class AvailableBudgetController extends Controller { - /** @var CurrencyRepositoryInterface */ + /** @var CurrencyRepositoryInterface The currency repository */ private $currencyRepository; - /** @var BudgetRepositoryInterface */ + /** @var BudgetRepositoryInterface The budget repository */ private $repository; /** @@ -144,11 +147,15 @@ class AvailableBudgetController extends Controller * @param AvailableBudgetRequest $request * * @return JsonResponse + * @throws FireflyException */ public function store(AvailableBudgetRequest $request): JsonResponse { - $data = $request->getAll(); - $currency = $this->currencyRepository->findNull($data['transaction_currency_id']); + $data = $request->getAll(); + $currency = $this->currencyRepository->findNull($data['transaction_currency_id']); + if (null === $currency) { + throw new FireflyException('Could not find the indicated currency.'); + } $availableBudget = $this->repository->setAvailableBudget($currency, $data['start_date'], $data['end_date'], $data['amount']); $manager = new Manager; $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; diff --git a/app/Api/V1/Controllers/BillController.php b/app/Api/V1/Controllers/BillController.php index c06b060df9..4f438df8b9 100644 --- a/app/Api/V1/Controllers/BillController.php +++ b/app/Api/V1/Controllers/BillController.php @@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Bill; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Transformers\BillTransformer; +use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Collection; @@ -39,11 +40,11 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** - * Class BillController + * Class BillController. */ class BillController extends Controller { - /** @var BillRepositoryInterface */ + /** @var BillRepositoryInterface The bill repository */ private $repository; /** @@ -54,9 +55,12 @@ class BillController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { + /** @var User $admin */ + $admin = auth()->user(); + /** @var BillRepositoryInterface repository */ $this->repository = app(BillRepositoryInterface::class); - $this->repository->setUser(auth()->user()); + $this->repository->setUser($admin); return $next($request); } @@ -103,6 +107,8 @@ class BillController extends Controller /** + * Show the specified bill. + * * @param Request $request * @param Bill $bill * @@ -124,6 +130,8 @@ class BillController extends Controller } /** + * Store a bill. + * * @param BillRequest $request * * @return JsonResponse @@ -147,6 +155,8 @@ class BillController extends Controller /** + * Update a bill. + * * @param BillRequest $request * @param Bill $bill * diff --git a/app/Api/V1/Controllers/BudgetController.php b/app/Api/V1/Controllers/BudgetController.php index d2a2ba2041..38ad437017 100644 --- a/app/Api/V1/Controllers/BudgetController.php +++ b/app/Api/V1/Controllers/BudgetController.php @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Budget; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Transformers\BudgetTransformer; +use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; @@ -38,11 +39,13 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** - * Class BudgetController + * Class BudgetController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class BudgetController extends Controller { - /** @var BudgetRepositoryInterface */ + /** @var BudgetRepositoryInterface The budget repository */ private $repository; /** @@ -53,9 +56,12 @@ class BudgetController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { + /** @var User $admin */ + $admin = auth()->user(); + /** @var BudgetRepositoryInterface repository */ $this->repository = app(BudgetRepositoryInterface::class); - $this->repository->setUser(auth()->user()); + $this->repository->setUser($admin); return $next($request); } @@ -111,6 +117,8 @@ class BudgetController extends Controller /** + * Show a budget. + * * @param Request $request * @param Budget $budget * @@ -132,6 +140,8 @@ class BudgetController extends Controller } /** + * Store a budget. + * * @param BudgetRequest $request * * @return JsonResponse @@ -154,6 +164,8 @@ class BudgetController extends Controller /** + * Update a budget. + * * @param BudgetRequest $request * @param Budget $budget * diff --git a/app/Api/V1/Controllers/BudgetLimitController.php b/app/Api/V1/Controllers/BudgetLimitController.php index fe07060205..80dc9f464e 100644 --- a/app/Api/V1/Controllers/BudgetLimitController.php +++ b/app/Api/V1/Controllers/BudgetLimitController.php @@ -24,8 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers; use Carbon\Carbon; -use Exception; -use FireflyIII\Api\V1\Requests\AvailableBudgetRequest; use FireflyIII\Api\V1\Requests\BudgetLimitRequest; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\BudgetLimit; @@ -43,16 +41,15 @@ use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; use Log; -use Throwable; /** - * Class BudgetLimitController + * Class BudgetLimitController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class BudgetLimitController extends Controller { - ///** @var CurrencyRepositoryInterface */ - //private $currencyRepository; - /** @var BudgetRepositoryInterface */ + /** @var BudgetRepositoryInterface The budget repository */ private $repository; /** @@ -66,7 +63,6 @@ class BudgetLimitController extends Controller /** @var User $user */ $user = auth()->user(); $this->repository = app(BudgetRepositoryInterface::class); - //$this->currencyRepository = app(CurrencyRepositoryInterface::class); $this->repository->setUser($user); return $next($request); @@ -97,40 +93,30 @@ class BudgetLimitController extends Controller */ public function index(Request $request): JsonResponse { - // create some objects: - $manager = new Manager; - $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; - - // read budget from request + $manager = new Manager; + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $start = null; + $end = null; $budgetId = (int)($request->get('budget_id') ?? 0); - $budget = null; - if ($budgetId > 0) { - $budget = $this->repository->findNull($budgetId); - } - // read start date from request - $start = null; + $budget = $this->repository->findNull($budgetId); + $this->parameters->set('budget_id', $budgetId); + try { $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); $this->parameters->set('start', $start->format('Y-m-d')); } catch (InvalidArgumentException $e) { - Log::debug(sprintf('Could not parse start date "%s": %s', $request->get('start'), $e->getMessage())); - + Log::debug(sprintf('Invalid date: %s', $e->getMessage())); } - // read end date from request - $end = null; try { $end = Carbon::createFromFormat('Y-m-d', $request->get('end')); $this->parameters->set('end', $end->format('Y-m-d')); } catch (InvalidArgumentException $e) { - Log::debug(sprintf('Could not parse end date "%s": %s', $request->get('end'), $e->getMessage())); + Log::debug(sprintf('Invalid date: %s', $e->getMessage())); } - $this->parameters->set('budget_id', $budgetId); - // types to get, page size: $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; - // get list of budget limits. Count it and split it. $collection = new Collection; if (null === $budget) { $collection = $this->repository->getAllBudgetLimits($start, $end); @@ -141,12 +127,9 @@ class BudgetLimitController extends Controller $count = $collection->count(); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); - - // make paginator: - $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); + $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); $paginator->setPath(route('api.v1.budget_limits.index') . $this->buildParams()); - // present to user. $manager->setSerializer(new JsonApiSerializer($baseUrl)); $resource = new FractalCollection($budgetLimits, new BudgetLimitTransformer($this->parameters), 'budget_limits'); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); @@ -206,8 +189,8 @@ class BudgetLimitController extends Controller /** * Update the specified resource in storage. * - * @param AvailableBudgetRequest $request - * @param BudgetLimit $budgetLimit + * @param BudgetLimitRequest $request + * @param BudgetLimit $budgetLimit * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/CategoryController.php b/app/Api/V1/Controllers/CategoryController.php index fc33a6fe16..cbc69366ba 100644 --- a/app/Api/V1/Controllers/CategoryController.php +++ b/app/Api/V1/Controllers/CategoryController.php @@ -28,6 +28,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Category; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Transformers\CategoryTransformer; +use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; @@ -38,11 +39,13 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** - * Class CategoryController + * Class CategoryController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CategoryController extends Controller { - /** @var CategoryRepositoryInterface */ + /** @var CategoryRepositoryInterface The category repository */ private $repository; /** @@ -53,9 +56,12 @@ class CategoryController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { + /** @var User $admin */ + $admin = auth()->user(); + /** @var CategoryRepositoryInterface repository */ $this->repository = app(CategoryRepositoryInterface::class); - $this->repository->setUser(auth()->user()); + $this->repository->setUser($admin); return $next($request); } @@ -111,6 +117,8 @@ class CategoryController extends Controller /** + * Show the category. + * * @param Request $request * @param Category $category * @@ -132,6 +140,8 @@ class CategoryController extends Controller } /** + * Store new category. + * * @param CategoryRequest $request * * @return JsonResponse @@ -154,6 +164,8 @@ class CategoryController extends Controller /** + * Update the category. + * * @param CategoryRequest $request * @param Category $category * diff --git a/app/Api/V1/Controllers/ConfigurationController.php b/app/Api/V1/Controllers/ConfigurationController.php index 9bedd0a459..46cadefeaa 100644 --- a/app/Api/V1/Controllers/ConfigurationController.php +++ b/app/Api/V1/Controllers/ConfigurationController.php @@ -25,39 +25,66 @@ namespace FireflyIII\Api\V1\Controllers; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Configuration; +use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; /** - * Class ConfigurationController + * Class ConfigurationController. */ class ConfigurationController extends Controller { + + /** @var UserRepositoryInterface The user repository */ + private $repository; + /** - * @throws FireflyException + * BudgetController constructor. */ - public function index() + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + /** @noinspection UnusedConstructorDependenciesInspection */ + $this->repository = app(UserRepositoryInterface::class); + /** @var User $admin */ + $admin = auth()->user(); + + if (!$this->repository->hasRole($admin, 'owner')) { + throw new FireflyException('No access to method.'); // @codeCoverageIgnore + } + + return $next($request); + } + ); + } + + /** + * Show all configuration. + * + * @return JsonResponse + */ + public function index(): JsonResponse { - if (!auth()->user()->hasRole('owner')) { - throw new FireflyException('No access to method.'); // @codeCoverageIgnore - } $configData = $this->getConfigData(); return response()->json(['data' => $configData], 200)->header('Content-Type', 'application/vnd.api+json'); } /** + * Update the configuration. + * * @param Request $request * * @return JsonResponse * @throws FireflyException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function update(Request $request): JsonResponse { - if (!auth()->user()->hasRole('owner')) { - throw new FireflyException('No access to method.'); // @codeCoverageIgnore - } $name = $request->get('name'); $value = $request->get('value'); $valid = ['is_demo_site', 'permission_update_check', 'single_user_mode']; @@ -68,7 +95,7 @@ class ConfigurationController extends Controller switch ($name) { case 'is_demo_site': case 'single_user_mode': - $configValue = $value === 'true'; + $configValue = 'true' === $value; break; case 'permission_update_check': $configValue = (int)$value >= -1 && (int)$value <= 1 ? (int)$value : -1; @@ -81,7 +108,10 @@ class ConfigurationController extends Controller } /** + * Get all config values. + * * @return array + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ private function getConfigData(): array { diff --git a/app/Api/V1/Controllers/Controller.php b/app/Api/V1/Controllers/Controller.php index 3b5b3d23b0..9a73e7a28a 100644 --- a/app/Api/V1/Controllers/Controller.php +++ b/app/Api/V1/Controllers/Controller.php @@ -37,12 +37,13 @@ use Symfony\Component\HttpFoundation\ParameterBag; * Class Controller. * * @codeCoverageIgnore + * @SuppressWarnings(PHPMD.NumberOfChildren) */ class Controller extends BaseController { use AuthorizesRequests, DispatchesJobs, ValidatesRequests; - /** @var ParameterBag */ + /** @var ParameterBag Parameters from the URI are stored here. */ protected $parameters; /** @@ -56,39 +57,42 @@ class Controller extends BaseController } /** + * Method to help build URI's. + * * @return string + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function buildParams(): string { $return = '?'; $params = []; foreach ($this->parameters as $key => $value) { - if ($key === 'page') { + if ('page' === $key) { continue; } if ($value instanceof Carbon) { $params[$key] = $value->format('Y-m-d'); + continue; } - if (!$value instanceof Carbon) { - $params[$key] = $value; - } + $params[$key] = $value; } $return .= http_build_query($params); - if (\strlen($return) === 1) { - return ''; - } return $return; } /** + * Method to grab all parameters from the URI. + * * @return ParameterBag + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ private function getParameters(): ParameterBag { $bag = new ParameterBag; $page = (int)request()->get('page'); - if ($page === 0) { + if (0 === $page) { $page = 1; } $bag->set('page', $page); diff --git a/app/Api/V1/Controllers/CurrencyController.php b/app/Api/V1/Controllers/CurrencyController.php index 174c4ff261..6bda7e05a7 100644 --- a/app/Api/V1/Controllers/CurrencyController.php +++ b/app/Api/V1/Controllers/CurrencyController.php @@ -30,6 +30,7 @@ use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Transformers\CurrencyTransformer; +use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; @@ -40,29 +41,32 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** - * Class CurrencyController + * Class CurrencyController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class CurrencyController extends Controller { - /** @var CurrencyRepositoryInterface */ + /** @var CurrencyRepositoryInterface The currency repository */ private $repository; - /** @var UserRepositoryInterface */ + /** @var UserRepositoryInterface The user repository */ private $userRepository; /** * CurrencyRepository constructor. - * - * @throws FireflyException */ public function __construct() { parent::__construct(); $this->middleware( function ($request, $next) { + /** @var User $admin */ + $admin = auth()->user(); + /** @var CurrencyRepositoryInterface repository */ $this->repository = app(CurrencyRepositoryInterface::class); $this->userRepository = app(UserRepositoryInterface::class); - $this->repository->setUser(auth()->user()); + $this->repository->setUser($admin); return $next($request); } @@ -79,7 +83,10 @@ class CurrencyController extends Controller */ public function delete(TransactionCurrency $currency): JsonResponse { - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + /** @var User $admin */ + $admin = auth()->user(); + + if (!$this->userRepository->hasRole($admin, 'owner')) { // access denied: throw new FireflyException('No access to method, user is not owner.'); // @codeCoverageIgnore } @@ -123,6 +130,8 @@ class CurrencyController extends Controller /** + * Show a currency. + * * @param Request $request * @param TransactionCurrency $currency * @@ -146,6 +155,8 @@ class CurrencyController extends Controller } /** + * Store new currency. + * * @param CurrencyRequest $request * * @return JsonResponse @@ -155,11 +166,11 @@ class CurrencyController extends Controller { $currency = $this->repository->store($request->getAll()); - if ($request->boolean('default') === true) { - app('preferences')->set('currencyPreference', $currency->code); - app('preferences')->mark(); - } if (null !== $currency) { + if (true === $request->boolean('default')) { + app('preferences')->set('currencyPreference', $currency->code); + app('preferences')->mark(); + } $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); @@ -176,6 +187,8 @@ class CurrencyController extends Controller /** + * Update a currency. + * * @param CurrencyRequest $request * @param TransactionCurrency $currency * @@ -186,7 +199,7 @@ class CurrencyController extends Controller $data = $request->getAll(); $currency = $this->repository->update($currency, $data); - if ($request->boolean('default') === true) { + if (true === $request->boolean('default')) { app('preferences')->set('currencyPreference', $currency->code); app('preferences')->mark(); } diff --git a/app/Api/V1/Controllers/CurrencyExchangeRateController.php b/app/Api/V1/Controllers/CurrencyExchangeRateController.php index 54d8672b0e..f66c3ac89f 100644 --- a/app/Api/V1/Controllers/CurrencyExchangeRateController.php +++ b/app/Api/V1/Controllers/CurrencyExchangeRateController.php @@ -28,20 +28,19 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Services\Currency\ExchangeRateInterface; use FireflyIII\Transformers\CurrencyExchangeRateTransformer; +use FireflyIII\User; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use InvalidArgumentException; use League\Fractal\Manager; use League\Fractal\Resource\Item; -use Log; +use League\Fractal\Serializer\JsonApiSerializer; /** - * * Class CurrencyExchangeRateController */ class CurrencyExchangeRateController extends Controller { - /** @var CurrencyRepositoryInterface */ + /** @var CurrencyRepositoryInterface The currency repository */ private $repository; /** @@ -52,8 +51,11 @@ class CurrencyExchangeRateController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { + /** @var User $admin */ + $admin = auth()->user(); + $this->repository = app(CurrencyRepositoryInterface::class); - $this->repository->setUser(auth()->user()); + $this->repository->setUser($admin); return $next($request); } @@ -62,6 +64,8 @@ class CurrencyExchangeRateController extends Controller } /** + * Show an exchange rate. + * * @param Request $request * * @return JsonResponse @@ -72,8 +76,8 @@ class CurrencyExchangeRateController extends Controller // create some objects: $manager = new Manager; $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // currencies $fromCurrency = $this->repository->findByCodeNull($request->get('from') ?? 'EUR'); $toCurrency = $this->repository->findByCodeNull($request->get('to') ?? 'USD'); @@ -84,27 +88,19 @@ class CurrencyExchangeRateController extends Controller throw new FireflyException('Unknown destination currency.'); } - $dateObj = new Carbon; - try { - $dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d')); - } catch (InvalidArgumentException $e) { - Log::debug($e->getMessage()); - } - - + $dateObj = Carbon::createFromFormat('Y-m-d', $request->get('date') ?? date('Y-m-d')); $this->parameters->set('from', $fromCurrency->code); $this->parameters->set('to', $toCurrency->code); $this->parameters->set('date', $dateObj->format('Y-m-d')); - // get the exchange rate. $rate = $this->repository->getExchangeRate($fromCurrency, $toCurrency, $dateObj); if (null === $rate) { + /** @var User $admin */ + $admin = auth()->user(); // create service: /** @var ExchangeRateInterface $service */ $service = app(ExchangeRateInterface::class); - $service->setUser(auth()->user()); - - // get rate: + $service->setUser($admin); $rate = $service->getRate($fromCurrency, $toCurrency, $dateObj); } diff --git a/app/Api/V1/Controllers/JournalLinkController.php b/app/Api/V1/Controllers/JournalLinkController.php index 0dde9742be..ce6ae8a200 100644 --- a/app/Api/V1/Controllers/JournalLinkController.php +++ b/app/Api/V1/Controllers/JournalLinkController.php @@ -39,13 +39,21 @@ use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; +/** + * Class JournalLinkController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class JournalLinkController extends Controller { - /** @var JournalRepositoryInterface */ + /** @var JournalRepositoryInterface The journal repository */ private $journalRepository; - /** @var LinkTypeRepositoryInterface */ + /** @var LinkTypeRepositoryInterface The link type repository */ private $repository; + /** + * JournalLinkController constructor. + */ public function __construct() { parent::__construct(); @@ -175,6 +183,8 @@ class JournalLinkController extends Controller } /** + * Update object. + * * @param JournalLinkRequest $request * @param TransactionJournalLink $journalLink * diff --git a/app/Api/V1/Controllers/LinkTypeController.php b/app/Api/V1/Controllers/LinkTypeController.php index 31215cd5a3..d1dd2e850c 100644 --- a/app/Api/V1/Controllers/LinkTypeController.php +++ b/app/Api/V1/Controllers/LinkTypeController.php @@ -40,17 +40,21 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** + * Class LinkTypeController. * - * Class LinkTypeController + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class LinkTypeController extends Controller { - /** @var LinkTypeRepositoryInterface */ + /** @var LinkTypeRepositoryInterface The link type repository */ private $repository; - /** @var UserRepositoryInterface */ + /** @var UserRepositoryInterface The user repository */ private $userRepository; + /** + * LinkTypeController constructor. + */ public function __construct() { parent::__construct(); @@ -77,7 +81,7 @@ class LinkTypeController extends Controller */ public function delete(LinkType $linkType): JsonResponse { - if ($linkType->editable === false) { + if (false === $linkType->editable) { throw new FireflyException(sprintf('You cannot delete this link type (#%d, "%s")', $linkType->id, $linkType->name)); } $this->repository->destroy($linkType, null); @@ -151,7 +155,10 @@ class LinkTypeController extends Controller */ public function store(LinkTypeRequest $request): JsonResponse { - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + /** @var User $admin */ + $admin = auth()->user(); + + if (!$this->userRepository->hasRole($admin, 'owner')) { throw new FireflyException('You need the "owner"-role to do this.'); } $data = $request->getAll(); @@ -168,6 +175,8 @@ class LinkTypeController extends Controller } /** + * Update object. + * * @param LinkTypeRequest $request * @param LinkType $linkType * @@ -176,10 +185,14 @@ class LinkTypeController extends Controller */ public function update(LinkTypeRequest $request, LinkType $linkType): JsonResponse { - if ($linkType->editable === false) { + if (false === $linkType->editable) { throw new FireflyException(sprintf('You cannot edit this link type (#%d, "%s")', $linkType->id, $linkType->name)); } - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + + /** @var User $admin */ + $admin = auth()->user(); + + if (!$this->userRepository->hasRole($admin, 'owner')) { throw new FireflyException('You need the "owner"-role to do this.'); } diff --git a/app/Api/V1/Controllers/PiggyBankController.php b/app/Api/V1/Controllers/PiggyBankController.php index 2dd1f0f8a6..0aa3295131 100644 --- a/app/Api/V1/Controllers/PiggyBankController.php +++ b/app/Api/V1/Controllers/PiggyBankController.php @@ -39,24 +39,30 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** - * TODO order up and down. - * Class PiggyBankController + * Class PiggyBankController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class PiggyBankController extends Controller { - /** @var PiggyBankRepositoryInterface */ + /** @var PiggyBankRepositoryInterface The piggy bank repository */ private $repository; + /** + * PiggyBankController constructor. + */ public function __construct() { parent::__construct(); $this->middleware( function ($request, $next) { - /** @var User $user */ - $user = auth()->user(); + /** @var User $admin */ + $admin = auth()->user(); $this->repository = app(PiggyBankRepositoryInterface::class); + $this->repository->setUser($admin); + return $next($request); } @@ -160,6 +166,8 @@ class PiggyBankController extends Controller } /** + * Update piggy bank. + * * @param PiggyBankRequest $request * @param PiggyBank $piggyBank * diff --git a/app/Api/V1/Controllers/PreferenceController.php b/app/Api/V1/Controllers/PreferenceController.php index 3efe8fa35a..e7d40c0091 100644 --- a/app/Api/V1/Controllers/PreferenceController.php +++ b/app/Api/V1/Controllers/PreferenceController.php @@ -42,20 +42,6 @@ use Preferences; */ class PreferenceController extends Controller { - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - /** @var User $user */ - $user = auth()->user(); - - // todo add local repositories. - return $next($request); - } - ); - } - /** * List all of them. * @@ -116,10 +102,13 @@ class PreferenceController extends Controller } /** + * Update a preference. + * * @param PreferenceRequest $request * @param Preference $preference * * @return JsonResponse + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function update(PreferenceRequest $request, Preference $preference): JsonResponse { @@ -138,7 +127,7 @@ class PreferenceController extends Controller break; case 'customFiscalYear': case 'twoFactorAuthEnabled': - $newValue = (int)$data['data'] === 1; + $newValue = 1 === (int)$data['data']; break; } $result = Preferences::set($preference->name, $newValue); diff --git a/app/Api/V1/Controllers/RecurrenceController.php b/app/Api/V1/Controllers/RecurrenceController.php index a5ec34e9c6..10c07b1d02 100644 --- a/app/Api/V1/Controllers/RecurrenceController.php +++ b/app/Api/V1/Controllers/RecurrenceController.php @@ -38,14 +38,16 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; /** - * * Class RecurrenceController */ class RecurrenceController extends Controller { - /** @var RecurringRepositoryInterface */ + /** @var RecurringRepositoryInterface The recurring transaction repository */ private $repository; + /** + * RecurrenceController constructor. + */ public function __construct() { parent::__construct(); @@ -155,6 +157,8 @@ class RecurrenceController extends Controller } /** + * Update single recurrence. + * * @param RecurrenceRequest $request * @param Recurrence $recurrence * @@ -163,9 +167,6 @@ class RecurrenceController extends Controller public function update(RecurrenceRequest $request, Recurrence $recurrence): JsonResponse { $data = $request->getAll(); - - // - $category = $this->repository->update($recurrence, $data); $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; diff --git a/app/Api/V1/Controllers/RuleController.php b/app/Api/V1/Controllers/RuleController.php index bd581dcfb2..d3977bfb2e 100644 --- a/app/Api/V1/Controllers/RuleController.php +++ b/app/Api/V1/Controllers/RuleController.php @@ -42,9 +42,12 @@ use League\Fractal\Serializer\JsonApiSerializer; */ class RuleController extends Controller { - /** @var RuleRepositoryInterface */ + /** @var RuleRepositoryInterface The rule repository */ private $ruleRepository; + /** + * RuleController constructor. + */ public function __construct() { parent::__construct(); @@ -136,7 +139,7 @@ class RuleController extends Controller /** * Store new object. * - * @param Request $request + * @param RuleRequest $request * * @return JsonResponse */ @@ -153,6 +156,8 @@ class RuleController extends Controller } /** + * Update a rule. + * * @param RuleRequest $request * @param Rule $rule * @@ -160,9 +165,9 @@ class RuleController extends Controller */ public function update(RuleRequest $request, Rule $rule): JsonResponse { - $rule = $this->ruleRepository->update($rule, $request->getAll()); - $manager = new Manager(); - $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $rule = $this->ruleRepository->update($rule, $request->getAll()); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); $resource = new Item($rule, new RuleTransformer($this->parameters), 'rules'); diff --git a/app/Api/V1/Controllers/RuleGroupController.php b/app/Api/V1/Controllers/RuleGroupController.php index 9085594c69..c97fecb22e 100644 --- a/app/Api/V1/Controllers/RuleGroupController.php +++ b/app/Api/V1/Controllers/RuleGroupController.php @@ -38,11 +38,17 @@ use League\Fractal\Resource\Item; use League\Fractal\Serializer\JsonApiSerializer; +/** + * Class RuleGroupController + */ class RuleGroupController extends Controller { - /** @var RuleGroupRepositoryInterface */ + /** @var RuleGroupRepositoryInterface The rule group repository */ private $ruleGroupRepository; + /** + * RuleGroupController constructor. + */ public function __construct() { parent::__construct(); @@ -62,7 +68,7 @@ class RuleGroupController extends Controller /** * Delete the resource. * - * @param string $object + * @param RuleGroup $ruleGroup * * @return JsonResponse */ @@ -151,8 +157,10 @@ class RuleGroupController extends Controller } /** - * @param Request $request - * @param string $object + * Update a rule group. + * + * @param RuleGroupRequest $request + * @param RuleGroup $ruleGroup * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/TransactionController.php b/app/Api/V1/Controllers/TransactionController.php index a03b594f42..91210a8525 100644 --- a/app/Api/V1/Controllers/TransactionController.php +++ b/app/Api/V1/Controllers/TransactionController.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers; use FireflyIII\Api\V1\Requests\TransactionRequest; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Helpers\Filter\InternalTransferFilter; use FireflyIII\Helpers\Filter\NegativeAmountFilter; @@ -33,36 +34,39 @@ use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Transformers\TransactionTransformer; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Collection; use League\Fractal\Manager; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Serializer\JsonApiSerializer; -use Log; /** * Class TransactionController + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class TransactionController extends Controller { - /** @var JournalRepositoryInterface */ + /** @var JournalRepositoryInterface The journal repository */ private $repository; /** * TransactionController constructor. - * - * @throws \FireflyIII\Exceptions\FireflyException */ public function __construct() { parent::__construct(); $this->middleware( function ($request, $next) { + /** @var User $admin */ + $admin = auth()->user(); + /** @var JournalRepositoryInterface repository */ $this->repository = app(JournalRepositoryInterface::class); - $this->repository->setUser(auth()->user()); + $this->repository->setUser($admin); return $next($request); } @@ -74,9 +78,9 @@ class TransactionController extends Controller * * @param \FireflyIII\Models\Transaction $transaction * - * @return \Illuminate\Http\Response + * @return JsonResponse */ - public function delete(Transaction $transaction) + public function delete(Transaction $transaction): JsonResponse { $journal = $transaction->transactionJournal; $this->repository->destroy($journal); @@ -85,33 +89,32 @@ class TransactionController extends Controller } /** + * Show all transactions. + * * @param Request $request * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function index(Request $request) + public function index(Request $request): JsonResponse { $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; - - // read type from URI - $type = $request->get('type') ?? 'default'; + $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); - // types to get, page size: - $types = $this->mapTypes($this->parameters->get('type')); - + $types = $this->mapTypes($this->parameters->get('type')); $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); - // collect transactions using the journal collector + /** @var User $admin */ + $admin = auth()->user(); + /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); - $collector->setUser(auth()->user()); + $collector->setUser($admin); $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); $collector->setAllAssetAccounts(); - // remove internal transfer filter: - if (\in_array(TransactionType::TRANSFER, $types)) { + if (\in_array(TransactionType::TRANSFER, $types, true)) { $collector->removeFilter(InternalTransferFilter::class); } @@ -124,7 +127,6 @@ class TransactionController extends Controller $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); $transactions = $paginator->getCollection(); - $resource = new FractalCollection($transactions, new TransactionTransformer($this->parameters), 'transactions'); $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); @@ -133,13 +135,15 @@ class TransactionController extends Controller /** + * Show a single transaction. + * * @param Request $request * @param Transaction $transaction * @param string $include * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function show(Request $request, Transaction $transaction, string $include = null) + public function show(Request $request, Transaction $transaction, string $include = null): JsonResponse { $manager = new Manager(); $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; @@ -173,13 +177,16 @@ class TransactionController extends Controller } /** + * Store a new transaction. + * * @param TransactionRequest $request * * @param JournalRepositoryInterface $repository * - * @return \Illuminate\Http\JsonResponse + * @throws FireflyException + * @return JsonResponse */ - public function store(TransactionRequest $request, JournalRepositoryInterface $repository) + public function store(TransactionRequest $request, JournalRepositoryInterface $repository): JsonResponse { $data = $request->getAll(); $data['user'] = auth()->user()->id; @@ -217,23 +224,21 @@ class TransactionController extends Controller /** + * Update a transaction. + * * @param TransactionRequest $request * @param JournalRepositoryInterface $repository * @param Transaction $transaction * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction) + public function update(TransactionRequest $request, JournalRepositoryInterface $repository, Transaction $transaction): JsonResponse { $data = $request->getAll(); $data['user'] = auth()->user()->id; - - Log::debug('Inside transaction update'); - - $journal = $repository->update($transaction->transactionJournal, $data); - - $manager = new Manager(); - $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; + $journal = $repository->update($transaction->transactionJournal, $data); + $manager = new Manager(); + $baseUrl = $request->getSchemeAndHttpHost() . '/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); // add include parameter: @@ -265,72 +270,38 @@ class TransactionController extends Controller } /** + * All the types you can request. + * * @param string $type * * @return array */ private function mapTypes(string $type): array { - $types = [ - 'all' => [ - TransactionType::WITHDRAWAL, - TransactionType::DEPOSIT, - TransactionType::TRANSFER, - TransactionType::OPENING_BALANCE, - TransactionType::RECONCILIATION, - ], - 'withdrawal' => [ - TransactionType::WITHDRAWAL, - ], - 'withdrawals' => [ - TransactionType::WITHDRAWAL, - ], - 'expense' => [ - TransactionType::WITHDRAWAL, - ], - 'income' => [ - TransactionType::DEPOSIT, - ], - 'deposit' => [ - TransactionType::DEPOSIT, - ], - 'deposits' => [ - TransactionType::DEPOSIT, - ], - 'transfer' => [ - TransactionType::TRANSFER, - ], - 'transfers' => [ - TransactionType::TRANSFER, - ], - 'opening_balance' => [ - TransactionType::OPENING_BALANCE, - ], - 'reconciliation' => [ - TransactionType::RECONCILIATION, - ], - 'reconciliations' => [ - TransactionType::RECONCILIATION, - ], - 'special' => [ - TransactionType::OPENING_BALANCE, - TransactionType::RECONCILIATION, - ], - 'specials' => [ - TransactionType::OPENING_BALANCE, - TransactionType::RECONCILIATION, - ], - 'default' => [ - TransactionType::WITHDRAWAL, - TransactionType::DEPOSIT, - TransactionType::TRANSFER, - ], + $types = [ + 'all' => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE, + TransactionType::RECONCILIATION,], + 'withdrawal' => [TransactionType::WITHDRAWAL,], + 'withdrawals' => [TransactionType::WITHDRAWAL,], + 'expense' => [TransactionType::WITHDRAWAL,], + 'income' => [TransactionType::DEPOSIT,], + 'deposit' => [TransactionType::DEPOSIT,], + 'deposits' => [TransactionType::DEPOSIT,], + 'transfer' => [TransactionType::TRANSFER,], + 'transfers' => [TransactionType::TRANSFER,], + 'opening_balance' => [TransactionType::OPENING_BALANCE,], + 'reconciliation' => [TransactionType::RECONCILIATION,], + 'reconciliations' => [TransactionType::RECONCILIATION,], + 'special' => [TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,], + 'specials' => [TransactionType::OPENING_BALANCE, TransactionType::RECONCILIATION,], + 'default' => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER,], ]; + $return = $types['default']; if (isset($types[$type])) { - return $types[$type]; + $return = $types[$type]; } - return $types['default']; // @codeCoverageIgnore + return $return; } } diff --git a/app/Api/V1/Controllers/UserController.php b/app/Api/V1/Controllers/UserController.php index e8466818f9..f582513ca0 100644 --- a/app/Api/V1/Controllers/UserController.php +++ b/app/Api/V1/Controllers/UserController.php @@ -29,6 +29,7 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Transformers\UserTransformer; use FireflyIII\User; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; use League\Fractal\Manager; @@ -39,18 +40,18 @@ use League\Fractal\Serializer\JsonApiSerializer; /** - * Class UserController + * Class UserController. + * + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class UserController extends Controller { - /** @var UserRepositoryInterface */ + /** @var UserRepositoryInterface The user repository */ private $repository; /** * UserController constructor. - * - * @throws \FireflyIII\Exceptions\FireflyException */ public function __construct() { @@ -70,12 +71,14 @@ class UserController extends Controller * * @param \FireflyIII\User $user * - * @return \Illuminate\Http\Response + * @return JsonResponse * @throws FireflyException */ - public function delete(User $user) + public function delete(User $user): JsonResponse { - if (auth()->user()->hasRole('owner')) { + /** @var User $admin */ + $admin = auth()->user(); + if ($this->repository->hasRole($admin, 'owner')) { $this->repository->destroy($user); return response()->json([], 204); @@ -88,9 +91,9 @@ class UserController extends Controller * * @param Request $request * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function index(Request $request) + public function index(Request $request): JsonResponse { // user preferences $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; @@ -117,12 +120,14 @@ class UserController extends Controller } /** + * Show a single user. + * * @param Request $request * @param User $user * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function show(Request $request, User $user) + public function show(Request $request, User $user): JsonResponse { // make manager $manager = new Manager(); @@ -140,11 +145,13 @@ class UserController extends Controller } /** + * Store a new user. + * * @param UserRequest $request * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function store(UserRequest $request) + public function store(UserRequest $request): JsonResponse { $data = $request->getAll(); $user = $this->repository->store($data); @@ -165,12 +172,14 @@ class UserController extends Controller } /** + * Update a user. + * * @param UserRequest $request * @param User $user * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function update(UserRequest $request, User $user) + public function update(UserRequest $request, User $user): JsonResponse { $data = $request->getAll(); $user = $this->repository->update($user, $data); diff --git a/app/Api/V1/Requests/AccountRequest.php b/app/Api/V1/Requests/AccountRequest.php index 5a287b85ed..db0feadf7e 100644 --- a/app/Api/V1/Requests/AccountRequest.php +++ b/app/Api/V1/Requests/AccountRequest.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests; - /** * Class AccountRequest */ @@ -31,6 +30,8 @@ class AccountRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -40,6 +41,8 @@ class AccountRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -67,6 +70,8 @@ class AccountRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/AttachmentRequest.php b/app/Api/V1/Requests/AttachmentRequest.php index 30da4d2683..c0cb193e70 100644 --- a/app/Api/V1/Requests/AttachmentRequest.php +++ b/app/Api/V1/Requests/AttachmentRequest.php @@ -26,7 +26,6 @@ namespace FireflyIII\Api\V1\Requests; use FireflyIII\Models\Bill; use FireflyIII\Models\ImportJob; use FireflyIII\Models\TransactionJournal; -use FireflyIII\Rules\IsBase64; use FireflyIII\Rules\IsValidAttachmentModel; /** @@ -35,6 +34,8 @@ use FireflyIII\Rules\IsValidAttachmentModel; class AttachmentRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -44,6 +45,8 @@ class AttachmentRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -58,6 +61,8 @@ class AttachmentRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/AvailableBudgetRequest.php b/app/Api/V1/Requests/AvailableBudgetRequest.php index 5631f5acc1..31c673e10d 100644 --- a/app/Api/V1/Requests/AvailableBudgetRequest.php +++ b/app/Api/V1/Requests/AvailableBudgetRequest.php @@ -29,6 +29,8 @@ namespace FireflyIII\Api\V1\Requests; class AvailableBudgetRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -38,6 +40,8 @@ class AvailableBudgetRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -51,6 +55,9 @@ class AvailableBudgetRequest extends Request } /** + * TODO must also accept currency code. + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/BillRequest.php b/app/Api/V1/Requests/BillRequest.php index f58c977737..cdb6801365 100644 --- a/app/Api/V1/Requests/BillRequest.php +++ b/app/Api/V1/Requests/BillRequest.php @@ -33,6 +33,8 @@ class BillRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -42,6 +44,8 @@ class BillRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -64,6 +68,8 @@ class BillRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/BudgetLimitRequest.php b/app/Api/V1/Requests/BudgetLimitRequest.php index 8ede47cfce..a12ac2ffdc 100644 --- a/app/Api/V1/Requests/BudgetLimitRequest.php +++ b/app/Api/V1/Requests/BudgetLimitRequest.php @@ -30,6 +30,8 @@ namespace FireflyIII\Api\V1\Requests; class BudgetLimitRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -39,6 +41,8 @@ class BudgetLimitRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -52,6 +56,8 @@ class BudgetLimitRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/BudgetRequest.php b/app/Api/V1/Requests/BudgetRequest.php index e90866d505..707c7b11c2 100644 --- a/app/Api/V1/Requests/BudgetRequest.php +++ b/app/Api/V1/Requests/BudgetRequest.php @@ -31,6 +31,8 @@ use FireflyIII\Models\Budget; class BudgetRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -40,6 +42,8 @@ class BudgetRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -52,6 +56,8 @@ class BudgetRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/CategoryRequest.php b/app/Api/V1/Requests/CategoryRequest.php index b910674e54..922892103a 100644 --- a/app/Api/V1/Requests/CategoryRequest.php +++ b/app/Api/V1/Requests/CategoryRequest.php @@ -31,6 +31,8 @@ use FireflyIII\Models\Category; class CategoryRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -40,6 +42,8 @@ class CategoryRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -51,6 +55,8 @@ class CategoryRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/CurrencyRequest.php b/app/Api/V1/Requests/CurrencyRequest.php index 6c63c83ddc..a535b8d006 100644 --- a/app/Api/V1/Requests/CurrencyRequest.php +++ b/app/Api/V1/Requests/CurrencyRequest.php @@ -30,6 +30,8 @@ namespace FireflyIII\Api\V1\Requests; class CurrencyRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -39,6 +41,8 @@ class CurrencyRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -53,6 +57,8 @@ class CurrencyRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array @@ -62,7 +68,7 @@ class CurrencyRequest extends Request 'code' => 'required|between:3,3|unique:transaction_currencies,code', 'symbol' => 'required|between:1,5|unique:transaction_currencies,symbol', 'decimal_places' => 'required|between:0,20|numeric|min:0|max:20', - 'default' => 'in:true,false', + 'default' => 'boolean', ]; switch ($this->method()) { diff --git a/app/Api/V1/Requests/JournalLinkRequest.php b/app/Api/V1/Requests/JournalLinkRequest.php index e52d5b7484..fd06410b08 100644 --- a/app/Api/V1/Requests/JournalLinkRequest.php +++ b/app/Api/V1/Requests/JournalLinkRequest.php @@ -31,6 +31,8 @@ namespace FireflyIII\Api\V1\Requests; class JournalLinkRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -40,6 +42,8 @@ class JournalLinkRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -53,6 +57,11 @@ class JournalLinkRequest extends Request } /** + * TODO include link-type name as optional parameter. + * TODO be consistent and remove notes from this object. + * + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/LinkTypeRequest.php b/app/Api/V1/Requests/LinkTypeRequest.php index c44dbcb145..3692bc5ea6 100644 --- a/app/Api/V1/Requests/LinkTypeRequest.php +++ b/app/Api/V1/Requests/LinkTypeRequest.php @@ -33,6 +33,8 @@ use Illuminate\Validation\Rule; class LinkTypeRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -42,6 +44,8 @@ class LinkTypeRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -56,6 +60,8 @@ class LinkTypeRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/PiggyBankRequest.php b/app/Api/V1/Requests/PiggyBankRequest.php index 15a41bda01..5106a93f45 100644 --- a/app/Api/V1/Requests/PiggyBankRequest.php +++ b/app/Api/V1/Requests/PiggyBankRequest.php @@ -33,6 +33,8 @@ use FireflyIII\Rules\IsAssetAccountId; class PiggyBankRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -42,6 +44,8 @@ class PiggyBankRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -58,6 +62,8 @@ class PiggyBankRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/PreferenceRequest.php b/app/Api/V1/Requests/PreferenceRequest.php index 38c3a39e11..f3439ccfef 100644 --- a/app/Api/V1/Requests/PreferenceRequest.php +++ b/app/Api/V1/Requests/PreferenceRequest.php @@ -32,6 +32,8 @@ class PreferenceRequest extends Request /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -40,6 +42,11 @@ class PreferenceRequest extends Request return auth()->check(); } + /** + * Get all data from the request. + * + * @return array + */ public function getAll(): array { return [ @@ -47,6 +54,11 @@ class PreferenceRequest extends Request ]; } + /** + * The rules that the incoming request must be matched against. + * + * @return array + */ public function rules(): array { return [ diff --git a/app/Api/V1/Requests/RecurrenceRequest.php b/app/Api/V1/Requests/RecurrenceRequest.php index 3aa948722a..34494a0cce 100644 --- a/app/Api/V1/Requests/RecurrenceRequest.php +++ b/app/Api/V1/Requests/RecurrenceRequest.php @@ -24,20 +24,21 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests; use Carbon\Carbon; -use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Rules\BelongsUser; +use FireflyIII\Validation\RecurrenceValidation; +use FireflyIII\Validation\TransactionValidation; use Illuminate\Validation\Validator; -use InvalidArgumentException; -use Log; /** * Class RecurrenceRequest */ class RecurrenceRequest extends Request { + use RecurrenceValidation, TransactionValidation; + /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -47,6 +48,8 @@ class RecurrenceRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -67,55 +70,16 @@ class RecurrenceRequest extends Request 'piggy_bank_name' => $this->string('piggy_bank_name'), 'tags' => explode(',', $this->string('tags')), ], - 'transactions' => [], - 'repetitions' => [], + 'transactions' => $this->getTransactionData(), + 'repetitions' => $this->getRepetitionData(), ]; - // repetition data: - /** @var array $repetitions */ - $repetitions = $this->get('repetitions'); - /** @var array $repetition */ - foreach ($repetitions as $repetition) { - $return['repetitions'][] = [ - 'type' => $repetition['type'], - 'moment' => $repetition['moment'], - 'skip' => (int)$repetition['skip'], - 'weekend' => (int)$repetition['weekend'], - ]; - } - // transaction data: - /** @var array $transactions */ - $transactions = $this->get('transactions'); - /** @var array $transaction */ - foreach ($transactions as $transaction) { - $return['transactions'][] = [ - 'amount' => $transaction['amount'], - - 'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, - 'currency_code' => $transaction['currency_code'] ?? null, - - 'foreign_amount' => $transaction['foreign_amount'] ?? null, - 'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, - 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, - - 'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, - 'budget_name' => $transaction['budget_name'] ?? null, - 'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, - 'category_name' => $transaction['category_name'] ?? null, - - 'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, - 'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, - 'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, - 'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, - - 'description' => $transaction['description'], - ]; - } - return $return; } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array @@ -132,18 +96,12 @@ class RecurrenceRequest extends Request 'nr_of_repetitions' => 'numeric|between:1,31', 'apply_rules' => 'required|boolean', 'active' => 'required|boolean', - - // rules for meta values: 'tags' => 'between:1,64000', 'piggy_bank_id' => 'numeric', - - // rules for repetitions. 'repetitions.*.type' => 'required|in:daily,weekly,ndom,monthly,yearly', 'repetitions.*.moment' => 'between:0,10', 'repetitions.*.skip' => 'required|numeric|between:0,31', 'repetitions.*.weekend' => 'required|numeric|min:1|max:4', - - // rules for transactions. 'transactions.*.currency_id' => 'numeric|exists:transaction_currencies,id|required_without:transactions.*.currency_code', 'transactions.*.currency_code' => 'min:3|max:3|exists:transaction_currencies,code|required_without:transactions.*.currency_id', 'transactions.*.foreign_amount' => 'numeric|more:0', @@ -171,312 +129,76 @@ class RecurrenceRequest extends Request { $validator->after( function (Validator $validator) { - $this->atLeastOneTransaction($validator); - $this->atLeastOneRepetition($validator); - $this->validRepeatsUntil($validator); - $this->validRepetitionMoment($validator); - $this->foreignCurrencyInformation($validator); + $this->validateOneTransaction($validator); + $this->validateOneRepetition($validator); + $this->validateRecurrenceRepetition($validator); + $this->validateRepetitionMoment($validator); + $this->validateForeignCurrencyInformation($validator); $this->validateAccountInformation($validator); } ); } + /** - * Throws an error when this asset account is invalid. + * Returns the repetition data as it is found in the submitted data. * - * @noinspection MoreThanThreeArgumentsInspection - * - * @param Validator $validator - * @param int|null $accountId - * @param null|string $accountName - * @param string $idField - * @param string $nameField - * - * @return null|Account + * @return array */ - protected function assetAccountExists(Validator $validator, ?int $accountId, ?string $accountName, string $idField, string $nameField): ?Account + private function getRepetitionData(): array { - $accountId = (int)$accountId; - $accountName = (string)$accountName; - // both empty? hard exit. - if ($accountId < 1 && '' === $accountName) { - $validator->errors()->add($idField, trans('validation.filled', ['attribute' => $idField])); - - return null; - } - // ID belongs to user and is asset account: - /** @var AccountRepositoryInterface $repository */ - $repository = app(AccountRepositoryInterface::class); - $repository->setUser(auth()->user()); - $set = $repository->getAccountsById([$accountId]); - Log::debug(sprintf('Count of accounts found by ID %d is: %d', $accountId, $set->count())); - if ($set->count() === 1) { - /** @var Account $first */ - $first = $set->first(); - if ($first->accountType->type !== AccountType::ASSET) { - $validator->errors()->add($idField, trans('validation.belongs_user')); - - return null; - } - - // we ignore the account name at this point. - return $first; + $return = []; + // repetition data: + /** @var array $repetitions */ + $repetitions = $this->get('repetitions'); + /** @var array $repetition */ + foreach ($repetitions as $repetition) { + $return[] = [ + 'type' => $repetition['type'], + 'moment' => $repetition['moment'], + 'skip' => (int)$repetition['skip'], + 'weekend' => (int)$repetition['weekend'], + ]; } - $account = $repository->findByName($accountName, [AccountType::ASSET]); - if (null === $account) { - $validator->errors()->add($nameField, trans('validation.belongs_user')); - - return null; - } - - return $account; + return $return; } /** - * Adds an error to the validator when there are no repetitions in the array of data. + * Returns the transaction data as it is found in the submitted data. It's a complex method according to code + * standards but it just has a lot of ??-statements because of the fields that may or may not exist. * - * @param Validator $validator + * @return array + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ - protected function atLeastOneRepetition(Validator $validator): void + private function getTransactionData(): array { - $data = $validator->getData(); - $repetitions = $data['repetitions'] ?? []; - // need at least one transaction - if (\count($repetitions) === 0) { - $validator->errors()->add('description', trans('validation.at_least_one_repetition')); - } - } - - /** - * Adds an error to the validator when there are no transactions in the array of data. - * - * @param Validator $validator - */ - protected function atLeastOneTransaction(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - // need at least one transaction - if (\count($transactions) === 0) { - $validator->errors()->add('description', trans('validation.at_least_one_transaction')); - } - } - - /** - * TODO can be made a rule? - * If the transactions contain foreign amounts, there must also be foreign currency information. - * - * @param Validator $validator - */ - protected function foreignCurrencyInformation(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - foreach ($transactions as $index => $transaction) { - // must have currency info. - if (isset($transaction['foreign_amount']) - && !(isset($transaction['foreign_currency_id']) - || isset($transaction['foreign_currency_code']))) { - $validator->errors()->add( - 'transactions.' . $index . '.foreign_amount', - trans('validation.require_currency_info') - ); - } - } - } - - /** - * Throws an error when the given opposing account (of type $type) is invalid. - * Empty data is allowed, system will default to cash. - * - * @noinspection MoreThanThreeArgumentsInspection - * - * @param Validator $validator - * @param string $type - * @param int|null $accountId - * @param null|string $accountName - * @param string $idField - * - * @return null|Account - */ - protected function opposingAccountExists(Validator $validator, string $type, ?int $accountId, ?string $accountName, string $idField): ?Account - { - $accountId = (int)$accountId; - $accountName = (string)$accountName; - // both empty? done! - if ($accountId < 1 && \strlen($accountName) === 0) { - return null; - } - if ($accountId !== 0) { - // ID belongs to user and is $type account: - /** @var AccountRepositoryInterface $repository */ - $repository = app(AccountRepositoryInterface::class); - $repository->setUser(auth()->user()); - $set = $repository->getAccountsById([$accountId]); - if ($set->count() === 1) { - /** @var Account $first */ - $first = $set->first(); - if ($first->accountType->type !== $type) { - $validator->errors()->add($idField, trans('validation.belongs_user')); - - return null; - } - - // we ignore the account name at this point. - return $first; - } + $return = []; + // transaction data: + /** @var array $transactions */ + $transactions = $this->get('transactions'); + /** @var array $transaction */ + foreach ($transactions as $transaction) { + $return[] = [ + 'amount' => $transaction['amount'], + 'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, + 'currency_code' => $transaction['currency_code'] ?? null, + 'foreign_amount' => $transaction['foreign_amount'] ?? null, + 'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, + 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, + 'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, + 'budget_name' => $transaction['budget_name'] ?? null, + 'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, + 'category_name' => $transaction['category_name'] ?? null, + 'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, + 'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, + 'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, + 'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, + 'description' => $transaction['description'], + ]; } - // not having an opposing account by this name is NOT a problem. - return null; - } - - /** - * TODO can be a rule? - * - * Validates the given account information. Switches on given transaction type. - * - * @param Validator $validator - */ - protected function validateAccountInformation(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - $idField = 'description'; - $transactionType = $data['type'] ?? 'false'; - foreach ($transactions as $index => $transaction) { - $sourceId = isset($transaction['source_id']) ? (int)$transaction['source_id'] : null; - $sourceName = $transaction['source_name'] ?? null; - $destinationId = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null; - $destinationName = $transaction['destination_name'] ?? null; - $sourceAccount = null; - $destinationAccount = null; - switch ($transactionType) { - case 'withdrawal': - $idField = 'transactions.' . $index . '.source_id'; - $nameField = 'transactions.' . $index . '.source_name'; - $sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField); - $idField = 'transactions.' . $index . '.destination_id'; - $destinationAccount = $this->opposingAccountExists($validator, AccountType::EXPENSE, $destinationId, $destinationName, $idField); - break; - case 'deposit': - $idField = 'transactions.' . $index . '.source_id'; - $sourceAccount = $this->opposingAccountExists($validator, AccountType::REVENUE, $sourceId, $sourceName, $idField); - - $idField = 'transactions.' . $index . '.destination_id'; - $nameField = 'transactions.' . $index . '.destination_name'; - $destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField); - break; - case 'transfer': - $idField = 'transactions.' . $index . '.source_id'; - $nameField = 'transactions.' . $index . '.source_name'; - $sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField); - - $idField = 'transactions.' . $index . '.destination_id'; - $nameField = 'transactions.' . $index . '.destination_name'; - $destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField); - break; - default: - $validator->errors()->add($idField, trans('validation.invalid_account_info')); - - return; - - } - // add some errors in case of same account submitted: - if (null !== $sourceAccount && null !== $destinationAccount && $sourceAccount->id === $destinationAccount->id) { - $validator->errors()->add($idField, trans('validation.source_equals_destination')); - } - } - } - - /** - * @param Validator $validator - */ - private function validRepeatsUntil(Validator $validator): void - { - $data = $validator->getData(); - $repetitions = $data['nr_of_repetitions'] ?? null; - $repeatUntil = $data['repeat_until'] ?? null; - if (null !== $repetitions && null !== $repeatUntil) { - // expect a date OR count: - $validator->errors()->add('repeat_until', trans('validation.require_repeat_until')); - $validator->errors()->add('nr_of_repetitions', trans('validation.require_repeat_until')); - - return; - } - } - - /** - * TODO merge this in a rule somehow. - * - * @param Validator $validator - */ - private function validRepetitionMoment(Validator $validator): void - { - $data = $validator->getData(); - $repetitions = $data['repetitions'] ?? []; - /** - * @var int $index - * @var array $repetition - */ - foreach ($repetitions as $index => $repetition) { - switch ($repetition['type']) { - default: - $validator->errors()->add(sprintf('repetitions.%d.type', $index), trans('validation.valid_recurrence_rep_type')); - - return; - case 'daily': - if ('' !== (string)$repetition['moment']) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); - } - - return; - case 'monthly': - $dayOfMonth = (int)$repetition['moment']; - if ($dayOfMonth < 1 || $dayOfMonth > 31) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); - } - - return; - case 'ndom': - $parameters = explode(',', $repetition['moment']); - if (\count($parameters) !== 2) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); - - return; - } - $nthDay = (int)($parameters[0] ?? 0.0); - $dayOfWeek = (int)($parameters[1] ?? 0.0); - if ($nthDay < 1 || $nthDay > 5) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); - - return; - } - if ($dayOfWeek < 1 || $dayOfWeek > 7) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); - - return; - } - - return; - case 'weekly': - $dayOfWeek = (int)$repetition['moment']; - if ($dayOfWeek < 1 || $dayOfWeek > 7) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); - - return; - } - break; - case 'yearly': - try { - Carbon::createFromFormat('Y-m-d', $repetition['moment']); - } catch (InvalidArgumentException $e) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); - - return; - } - } - } + return $return; } } \ No newline at end of file diff --git a/app/Api/V1/Requests/Request.php b/app/Api/V1/Requests/Request.php index e2016dba34..416818471c 100644 --- a/app/Api/V1/Requests/Request.php +++ b/app/Api/V1/Requests/Request.php @@ -28,6 +28,10 @@ use FireflyIII\Http\Requests\Request as FireflyIIIRequest; /** * Class Request. + * + * Technically speaking this class does not have to be extended like this but who knows what the future brings. + * + * @SuppressWarnings(PHPMD.NumberOfChildren) */ class Request extends FireflyIIIRequest { diff --git a/app/Api/V1/Requests/RuleGroupRequest.php b/app/Api/V1/Requests/RuleGroupRequest.php index a8b88601e4..5c56cda869 100644 --- a/app/Api/V1/Requests/RuleGroupRequest.php +++ b/app/Api/V1/Requests/RuleGroupRequest.php @@ -33,6 +33,8 @@ use FireflyIII\Models\RuleGroup; class RuleGroupRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -42,6 +44,8 @@ class RuleGroupRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -54,6 +58,8 @@ class RuleGroupRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Api/V1/Requests/RuleRequest.php b/app/Api/V1/Requests/RuleRequest.php index 84f6afb52b..7bc6b2b1be 100644 --- a/app/Api/V1/Requests/RuleRequest.php +++ b/app/Api/V1/Requests/RuleRequest.php @@ -32,6 +32,8 @@ use Illuminate\Validation\Validator; class RuleRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -41,6 +43,8 @@ class RuleRequest extends Request } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -62,14 +66,14 @@ class RuleRequest extends Request $data['rule-triggers'][] = [ 'name' => $trigger['name'], 'value' => $trigger['value'], - 'stop-processing' => (int)($trigger['stop-processing'] ?? 0) === 1, + 'stop-processing' => 1 === (int)($trigger['stop-processing'] ?? 0), ]; } foreach ($this->get('rule-actions') as $action) { $data['rule-actions'][] = [ 'name' => $action['name'], 'value' => $action['value'], - 'stop-processing' => (int)($action['stop-processing'] ?? 0) === 1, + 'stop-processing' => 1 === (int)($action['stop-processing'] ?? 0), ]; } @@ -77,6 +81,8 @@ class RuleRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array @@ -134,7 +140,7 @@ class RuleRequest extends Request $data = $validator->getData(); $repetitions = $data['rule-actions'] ?? []; // need at least one transaction - if (\count($repetitions) === 0) { + if (0 === \count($repetitions)) { $validator->errors()->add('title', trans('validation.at_least_one_action')); } } @@ -149,7 +155,7 @@ class RuleRequest extends Request $data = $validator->getData(); $repetitions = $data['rule-triggers'] ?? []; // need at least one transaction - if (\count($repetitions) === 0) { + if (0 === \count($repetitions)) { $validator->errors()->add('title', trans('validation.at_least_one_trigger')); } } diff --git a/app/Api/V1/Requests/TransactionRequest.php b/app/Api/V1/Requests/TransactionRequest.php index ce0c27e1be..cbb2f74e71 100644 --- a/app/Api/V1/Requests/TransactionRequest.php +++ b/app/Api/V1/Requests/TransactionRequest.php @@ -24,12 +24,8 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; -use FireflyIII\Models\Transaction; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Rules\BelongsUser; +use FireflyIII\Validation\TransactionValidation; use Illuminate\Validation\Validator; @@ -38,7 +34,11 @@ use Illuminate\Validation\Validator; */ class TransactionRequest extends Request { + use TransactionValidation; + /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool @@ -48,12 +48,15 @@ class TransactionRequest extends Request } /** + * Get all data. Is pretty complex because of all the ??-statements. + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) * @return array */ public function getAll(): array { $data = [ - // basic fields for journal: 'type' => $this->string('type'), 'date' => $this->date('date'), 'description' => $this->string('description'), @@ -62,8 +65,6 @@ class TransactionRequest extends Request 'bill_id' => $this->integer('bill_id'), 'bill_name' => $this->string('bill_name'), 'tags' => explode(',', $this->string('tags')), - - // then, custom fields for journal 'interest_date' => $this->date('interest_date'), 'book_date' => $this->date('book_date'), 'process_date' => $this->date('process_date'), @@ -72,39 +73,17 @@ class TransactionRequest extends Request 'invoice_date' => $this->date('invoice_date'), 'internal_reference' => $this->string('internal_reference'), 'notes' => $this->string('notes'), - - // then, transactions (see below). - 'transactions' => [], - + 'transactions' => $this->getTransactionData(), ]; - foreach ($this->get('transactions') as $index => $transaction) { - $array = [ - 'description' => $transaction['description'] ?? null, - 'amount' => $transaction['amount'], - 'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, - 'currency_code' => $transaction['currency_code'] ?? null, - 'foreign_amount' => $transaction['foreign_amount'] ?? null, - 'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, - 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, - 'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, - 'budget_name' => $transaction['budget_name'] ?? null, - 'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, - 'category_name' => $transaction['category_name'] ?? null, - 'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, - 'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, - 'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, - 'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, - 'reconciled' => $transaction['reconciled'] ?? false, - 'identifier' => $index, - ]; - $data['transactions'][] = $array; - } return $data; } /** + * The rules that the incoming request must be matched against. + * * @return array + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function rules(): array { @@ -149,13 +128,8 @@ class TransactionRequest extends Request 'transactions.*.destination_name' => 'between:1,255|nullable', ]; - switch ($this->method()) { - default: - break; - case 'PUT': - case 'PATCH': - unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']); - break; + if ('PUT' === $this->method()) { + unset($rules['type'], $rules['piggy_bank_id'], $rules['piggy_bank_name']); } return $rules; @@ -174,11 +148,11 @@ class TransactionRequest extends Request { $validator->after( function (Validator $validator) { - $this->atLeastOneTransaction($validator); - $this->checkValidDescriptions($validator); - $this->equalToJournalDescription($validator); - $this->emptySplitDescriptions($validator); - $this->foreignCurrencyInformation($validator); + $this->validateOneTransaction($validator); + $this->validateDescriptions($validator); + $this->validateJournalDescription($validator); + $this->validateSplitDescriptions($validator); + $this->validateForeignCurrencyInformation($validator); $this->validateAccountInformation($validator); $this->validateSplitAccounts($validator); } @@ -186,335 +160,37 @@ class TransactionRequest extends Request } /** - * Throws an error when this asset account is invalid. + * Get transaction data. * - * @noinspection MoreThanThreeArgumentsInspection - * - * @param Validator $validator - * @param int|null $accountId - * @param null|string $accountName - * @param string $idField - * @param string $nameField - * - * @return null|Account + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @return array */ - protected function assetAccountExists(Validator $validator, ?int $accountId, ?string $accountName, string $idField, string $nameField): ?Account + private function getTransactionData(): array { - - $accountId = (int)$accountId; - $accountName = (string)$accountName; - // both empty? hard exit. - if ($accountId < 1 && \strlen($accountName) === 0) { - $validator->errors()->add($idField, trans('validation.filled', ['attribute' => $idField])); - - return null; - } - // ID belongs to user and is asset account: - /** @var AccountRepositoryInterface $repository */ - $repository = app(AccountRepositoryInterface::class); - $repository->setUser(auth()->user()); - $set = $repository->getAccountsById([$accountId]); - if ($set->count() === 1) { - /** @var Account $first */ - $first = $set->first(); - if ($first->accountType->type !== AccountType::ASSET) { - $validator->errors()->add($idField, trans('validation.belongs_user')); - - return null; - } - - // we ignore the account name at this point. - return $first; + $return = []; + foreach ($this->get('transactions') as $index => $transaction) { + $return[] = [ + 'description' => $transaction['description'] ?? null, + 'amount' => $transaction['amount'], + 'currency_id' => isset($transaction['currency_id']) ? (int)$transaction['currency_id'] : null, + 'currency_code' => $transaction['currency_code'] ?? null, + 'foreign_amount' => $transaction['foreign_amount'] ?? null, + 'foreign_currency_id' => isset($transaction['foreign_currency_id']) ? (int)$transaction['foreign_currency_id'] : null, + 'foreign_currency_code' => $transaction['foreign_currency_code'] ?? null, + 'budget_id' => isset($transaction['budget_id']) ? (int)$transaction['budget_id'] : null, + 'budget_name' => $transaction['budget_name'] ?? null, + 'category_id' => isset($transaction['category_id']) ? (int)$transaction['category_id'] : null, + 'category_name' => $transaction['category_name'] ?? null, + 'source_id' => isset($transaction['source_id']) ? (int)$transaction['source_id'] : null, + 'source_name' => isset($transaction['source_name']) ? (string)$transaction['source_name'] : null, + 'destination_id' => isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null, + 'destination_name' => isset($transaction['destination_name']) ? (string)$transaction['destination_name'] : null, + 'reconciled' => $transaction['reconciled'] ?? false, + 'identifier' => $index, + ]; } - $account = $repository->findByName($accountName, [AccountType::ASSET]); - if (null === $account) { - $validator->errors()->add($nameField, trans('validation.belongs_user')); - - return null; - } - - return $account; + return $return; } - - /** - * Adds an error to the validator when there are no transactions in the array of data. - * - * @param Validator $validator - */ - protected function atLeastOneTransaction(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - // need at least one transaction - if (\count($transactions) === 0) { - $validator->errors()->add('description', trans('validation.at_least_one_transaction')); - } - } - - /** - * Adds an error to the "description" field when the user has submitted no descriptions and no - * journal description. - * - * @param Validator $validator - */ - protected function checkValidDescriptions(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - $journalDescription = (string)($data['description'] ?? ''); - $validDescriptions = 0; - foreach ($transactions as $index => $transaction) { - if (\strlen((string)($transaction['description'] ?? '')) > 0) { - $validDescriptions++; - } - } - - // no valid descriptions and empty journal description? error. - if ($validDescriptions === 0 && \strlen($journalDescription) === 0) { - $validator->errors()->add('description', trans('validation.filled', ['attribute' => trans('validation.attributes.description')])); - } - - } - - /** - * Adds an error to the validator when the user submits a split transaction (more than 1 transactions) - * but does not give them a description. - * - * @param Validator $validator - */ - protected function emptySplitDescriptions(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - foreach ($transactions as $index => $transaction) { - $description = (string)($transaction['description'] ?? ''); - // filled description is mandatory for split transactions. - if (\count($transactions) > 1 && \strlen($description) === 0) { - $validator->errors()->add( - 'transactions.' . $index . '.description', - trans('validation.filled', ['attribute' => trans('validation.attributes.transaction_description')]) - ); - } - } - } - - /** - * Adds an error to the validator when any transaction descriptions are equal to the journal description. - * - * @param Validator $validator - */ - protected function equalToJournalDescription(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - $journalDescription = (string)($data['description'] ?? ''); - foreach ($transactions as $index => $transaction) { - $description = (string)($transaction['description'] ?? ''); - // description cannot be equal to journal description. - if ($description === $journalDescription) { - $validator->errors()->add('transactions.' . $index . '.description', trans('validation.equal_description')); - } - } - } - - /** - * TODO can be made a rule? - * - * If the transactions contain foreign amounts, there must also be foreign currency information. - * - * @param Validator $validator - */ - protected function foreignCurrencyInformation(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - foreach ($transactions as $index => $transaction) { - // must have currency info. - if (isset($transaction['foreign_amount']) - && !(isset($transaction['foreign_currency_id']) - || isset($transaction['foreign_currency_code']))) { - $validator->errors()->add( - 'transactions.' . $index . '.foreign_amount', - trans('validation.require_currency_info') - ); - } - } - } - - /** - * Throws an error when the given opposing account (of type $type) is invalid. - * Empty data is allowed, system will default to cash. - * - * @noinspection MoreThanThreeArgumentsInspection - * - * @param Validator $validator - * @param string $type - * @param int|null $accountId - * @param null|string $accountName - * @param string $idField - * - * @return null|Account - */ - protected function opposingAccountExists(Validator $validator, string $type, ?int $accountId, ?string $accountName, string $idField): ?Account - { - $accountId = (int)$accountId; - $accountName = (string)$accountName; - // both empty? done! - if ($accountId < 1 && \strlen($accountName) === 0) { - return null; - } - if ($accountId !== 0) { - // ID belongs to user and is $type account: - /** @var AccountRepositoryInterface $repository */ - $repository = app(AccountRepositoryInterface::class); - $repository->setUser(auth()->user()); - $set = $repository->getAccountsById([$accountId]); - if ($set->count() === 1) { - /** @var Account $first */ - $first = $set->first(); - if ($first->accountType->type !== $type) { - $validator->errors()->add($idField, trans('validation.belongs_user')); - - return null; - } - - // we ignore the account name at this point. - return $first; - } - } - - // not having an opposing account by this name is NOT a problem. - return null; - } - - /** - * Validates the given account information. Switches on given transaction type. - * - * @param Validator $validator - * - * @throws FireflyException - */ - protected function validateAccountInformation(Validator $validator): void - { - $data = $validator->getData(); - $transactions = $data['transactions'] ?? []; - if (!isset($data['type'])) { - // the journal may exist in the request: - /** @var Transaction $transaction */ - $transaction = $this->route()->parameter('transaction'); - if (null === $transaction) { - return; // @codeCoverageIgnore - } - $data['type'] = strtolower($transaction->transactionJournal->transactionType->type); - } - foreach ($transactions as $index => $transaction) { - $sourceId = isset($transaction['source_id']) ? (int)$transaction['source_id'] : null; - $sourceName = $transaction['source_name'] ?? null; - $destinationId = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null; - $destinationName = $transaction['destination_name'] ?? null; - $sourceAccount = null; - $destinationAccount = null; - switch ($data['type']) { - case 'withdrawal': - $idField = 'transactions.' . $index . '.source_id'; - $nameField = 'transactions.' . $index . '.source_name'; - $sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField); - $idField = 'transactions.' . $index . '.destination_id'; - $destinationAccount = $this->opposingAccountExists($validator, AccountType::EXPENSE, $destinationId, $destinationName, $idField); - break; - case 'deposit': - $idField = 'transactions.' . $index . '.source_id'; - $sourceAccount = $this->opposingAccountExists($validator, AccountType::REVENUE, $sourceId, $sourceName, $idField); - - $idField = 'transactions.' . $index . '.destination_id'; - $nameField = 'transactions.' . $index . '.destination_name'; - $destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField); - break; - case 'transfer': - $idField = 'transactions.' . $index . '.source_id'; - $nameField = 'transactions.' . $index . '.source_name'; - $sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField); - - $idField = 'transactions.' . $index . '.destination_id'; - $nameField = 'transactions.' . $index . '.destination_name'; - $destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField); - break; - default: - // @codeCoverageIgnoreStart - throw new FireflyException( - sprintf('The validator cannot handle transaction type "%s" in validateAccountInformation().', $data['type']) - ); - // @codeCoverageIgnoreEnd - - } - // add some errors in case of same account submitted: - if (null !== $sourceAccount && null !== $destinationAccount && $sourceAccount->id === $destinationAccount->id) { - $validator->errors()->add($idField, trans('validation.source_equals_destination')); - } - } - } - - /** - * @param Validator $validator - * - * @throws FireflyException - */ - protected function validateSplitAccounts(Validator $validator): void - { - $data = $validator->getData(); - $count = isset($data['transactions']) ? \count($data['transactions']) : 0; - if ($count < 2) { - return; - } - // this is pretty much impossible: - // @codeCoverageIgnoreStart - if (!isset($data['type'])) { - // the journal may exist in the request: - /** @var Transaction $transaction */ - $transaction = $this->route()->parameter('transaction'); - if (null === $transaction) { - return; - } - $data['type'] = strtolower($transaction->transactionJournal->transactionType->type); - } - // @codeCoverageIgnoreEnd - - // collect all source ID's and destination ID's, if present: - $sources = []; - $destinations = []; - - foreach ($data['transactions'] as $transaction) { - $sources[] = isset($transaction['source_id']) ? (int)$transaction['source_id'] : 0; - $destinations[] = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : 0; - } - $destinations = array_unique($destinations); - $sources = array_unique($sources); - // switch on type: - switch ($data['type']) { - case 'withdrawal': - if (\count($sources) > 1) { - $validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal')); - } - break; - case 'deposit': - if (\count($destinations) > 1) { - $validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal')); - } - break; - case 'transfer': - if (\count($sources) > 1 || \count($destinations) > 1) { - $validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal')); - $validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal')); - } - break; - default: - // @codeCoverageIgnoreStart - throw new FireflyException( - sprintf('The validator cannot handle transaction type "%s" in validateSplitAccounts().', $data['type']) - ); - // @codeCoverageIgnoreEnd - } - } - } diff --git a/app/Api/V1/Requests/UserRequest.php b/app/Api/V1/Requests/UserRequest.php index ba9bf54904..31cd81f1e2 100644 --- a/app/Api/V1/Requests/UserRequest.php +++ b/app/Api/V1/Requests/UserRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests; +use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; @@ -33,24 +34,32 @@ use FireflyIII\User; class UserRequest extends Request { /** + * Authorize logged in users. + * * @return bool */ public function authorize(): bool { + $result = false; // Only allow authenticated users - if (!auth()->check()) { - return false; // @codeCoverageIgnore - } - /** @var User $user */ - $user = auth()->user(); - if (!$user->hasRole('owner')) { - return false; // @codeCoverageIgnore + if (auth()->check()) { + /** @var User $user */ + $user = auth()->user(); + + /** @var UserRepositoryInterface $repository */ + $repository = app(UserRepositoryInterface::class); + + if ($repository->hasRole($user, 'owner')) { + $result = true; // @codeCoverageIgnore + } } - return true; + return $result; } /** + * Get all data from the request. + * * @return array */ public function getAll(): array @@ -65,6 +74,8 @@ class UserRequest extends Request } /** + * The rules that the incoming request must be matched against. + * * @return array */ public function rules(): array diff --git a/app/Console/Commands/CreateExport.php b/app/Console/Commands/CreateExport.php index 336c5718ff..6896b409cf 100644 --- a/app/Console/Commands/CreateExport.php +++ b/app/Console/Commands/CreateExport.php @@ -1,5 +1,4 @@ . */ +/** @noinspection MultipleReturnStatementsInspection */ + declare(strict_types=1); namespace FireflyIII\Console\Commands; @@ -42,6 +43,7 @@ use Storage; class CreateExport extends Command { use VerifiesAccessToken; + /** * The console command description. * @@ -64,9 +66,11 @@ class CreateExport extends Command /** * Execute the console command. * - * @return mixed + * @return int + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function handle() + public function handle(): int { if (!$this->verifyAccessToken()) { $this->error('Invalid access token.'); @@ -86,6 +90,9 @@ class CreateExport extends Command // set user $user = $userRepository->findNull((int)$this->option('user')); + if (null === $user) { + return 1; + } $jobRepository->setUser($user); $journalRepository->setUser($user); $accountRepository->setUser($user); diff --git a/app/Console/Commands/CreateImport.php b/app/Console/Commands/CreateImport.php index 8c23105c0a..f9a8fb8633 100644 --- a/app/Console/Commands/CreateImport.php +++ b/app/Console/Commands/CreateImport.php @@ -1,5 +1,4 @@ . */ +/** @noinspection MultipleReturnStatementsInspection */ + declare(strict_types=1); namespace FireflyIII\Console\Commands; @@ -81,10 +82,15 @@ class CreateImport extends Command $configuration = (string)$this->argument('configuration'); $user = $userRepository->findNull((int)$this->option('user')); $cwd = getcwd(); - $type = strtolower((string)$this->option('type')); $provider = strtolower((string)$this->option('provider')); $configurationData = []; + if (null === $user) { + $this->errorLine('User is NULL.'); + + return 1; + } + if (!$this->validArguments()) { $this->errorLine('Invalid arguments.'); @@ -182,7 +188,7 @@ class CreateImport extends Command } $count++; } - if ($importJob->status === 'provider_finished') { + if ('provider_finished' === $importJob->status) { $this->infoLine('Import has finished. Please wait for storage of data.'); // set job to be storing data: $jobRepository->setStatus($importJob, 'storing_data'); @@ -274,19 +280,19 @@ class CreateImport extends Command return false; } - if ($provider === 'file' && !\in_array($type, $validTypes, true)) { + if ('file' === $provider && !\in_array($type, $validTypes, true)) { $this->errorLine(sprintf('Cannot import file of type "%s"', $type)); return false; } - if ($provider === 'file' && !file_exists($file)) { + if ('file' === $provider && !file_exists($file)) { $this->errorLine(sprintf('Firefly III cannot find file "%s" (working directory: "%s").', $file, $cwd)); return false; } - if ($provider === 'file' && !file_exists($configuration)) { + if ('file' === $provider && !file_exists($configuration)) { $this->errorLine(sprintf('Firefly III cannot find configuration file "%s" (working directory: "%s").', $configuration, $cwd)); return false; diff --git a/app/Console/Commands/DecryptAttachment.php b/app/Console/Commands/DecryptAttachment.php index dca003e8b9..056a638872 100644 --- a/app/Console/Commands/DecryptAttachment.php +++ b/app/Console/Commands/DecryptAttachment.php @@ -1,5 +1,4 @@ . */ +/** @noinspection MultipleReturnStatementsInspection */ + declare(strict_types=1); namespace FireflyIII\Console\Commands; @@ -51,11 +52,12 @@ class DecryptAttachment extends Command /** * Execute the console command. - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's five its fine. + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * + * @return int */ - public function handle() + public function handle(): int { /** @var AttachmentRepositoryInterface $repository */ $repository = app(AttachmentRepositoryInterface::class); @@ -67,28 +69,28 @@ class DecryptAttachment extends Command $this->error(sprintf('No attachment with id #%d', $attachmentId)); Log::error(sprintf('DecryptAttachment: No attachment with id #%d', $attachmentId)); - return; + return 1; } if ($attachmentName !== $attachment->filename) { $this->error('File name does not match.'); Log::error('DecryptAttachment: File name does not match.'); - return; + return 1; } if (!is_dir($storagePath)) { $this->error(sprintf('Path "%s" is not a directory.', $storagePath)); Log::error(sprintf('DecryptAttachment: Path "%s" is not a directory.', $storagePath)); - return; + return 1; } if (!is_writable($storagePath)) { $this->error(sprintf('Path "%s" is not writable.', $storagePath)); Log::error(sprintf('DecryptAttachment: Path "%s" is not writable.', $storagePath)); - return; + return 1; } $fullPath = $storagePath . DIRECTORY_SEPARATOR . $attachment->filename; @@ -98,9 +100,10 @@ class DecryptAttachment extends Command if (false === $result) { $this->error('Could not write to file.'); - return; + return 1; } $this->info(sprintf('%d bytes written. Exiting now..', $result)); + return 0; } } diff --git a/app/Console/Commands/EncryptFile.php b/app/Console/Commands/EncryptFile.php index d074897c23..64b19820a5 100644 --- a/app/Console/Commands/EncryptFile.php +++ b/app/Console/Commands/EncryptFile.php @@ -1,5 +1,4 @@ . */ +/** @noinspection MultipleReturnStatementsInspection */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ + declare(strict_types=1); namespace FireflyIII\Console\Commands; @@ -27,8 +29,8 @@ namespace FireflyIII\Console\Commands; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Import\Routine\RoutineInterface; use FireflyIII\Models\ImportJob; +use FireflyIII\Models\Tag; use Illuminate\Console\Command; -use Illuminate\Support\MessageBag; use Log; /** @@ -52,10 +54,12 @@ class Import extends Command /** * Run the import routine. + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * * @throws FireflyException */ - public function handle() + public function handle(): void { Log::debug('Start start-import command'); $jobKey = $this->argument('key'); @@ -83,21 +87,30 @@ class Import extends Command /** @var RoutineInterface $routine */ $routine = app($className); - $routine->setJob($job); + $routine->setImportJob($job); $routine->run(); - /** @var MessageBag $error */ - foreach ($routine->getErrors() as $index => $error) { + /** + * @var int $index + * @var string $error + */ + foreach ($job->errors as $index => $error) { $this->errorLine(sprintf('Error importing line #%d: %s', $index, $error)); } - $this->infoLine( - sprintf('The import has finished. %d transactions have been imported out of %d records.', $routine->getJournals()->count(), $routine->getLines()) - ); + /** @var Tag $tag */ + $tag = $job->tag()->first(); + $count = 0; + if (null === $tag) { + $count = $tag->transactionJournals()->count(); + } + $this->infoLine(sprintf('The import has finished. %d transactions have been imported.', $count)); } /** + * Displays an error. + * * @param string $message * @param array|null $data */ @@ -109,6 +122,8 @@ class Import extends Command } /** + * Displays an informational message. + * * @param string $message * @param array $data */ diff --git a/app/Console/Commands/ScanAttachments.php b/app/Console/Commands/ScanAttachments.php index b23f82b1ce..ac10dec27f 100644 --- a/app/Console/Commands/ScanAttachments.php +++ b/app/Console/Commands/ScanAttachments.php @@ -1,5 +1,4 @@ . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ + declare(strict_types=1); namespace FireflyIII\Console\Commands; @@ -53,7 +54,7 @@ class ScanAttachments extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $attachments = Attachment::get(); $disk = Storage::disk('upload'); @@ -63,13 +64,13 @@ class ScanAttachments extends Command try { $content = $disk->get($fileName); } catch (FileNotFoundException $e) { - $this->error(sprintf('Could not find data for attachment #%d', $attachment->id)); + $this->error(sprintf('Could not find data for attachment #%d: %s', $attachment->id, $e->getMessage())); continue; } try { $decrypted = Crypt::decrypt($content); } catch (DecryptException $e) { - $this->error(sprintf('Could not decrypt data of attachment #%d', $attachment->id)); + $this->error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage())); continue; } $tmpfname = tempnam(sys_get_temp_dir(), 'FireflyIII'); diff --git a/app/Console/Commands/UpgradeDatabase.php b/app/Console/Commands/UpgradeDatabase.php index a533aedf2f..37f72b8db4 100644 --- a/app/Console/Commands/UpgradeDatabase.php +++ b/app/Console/Commands/UpgradeDatabase.php @@ -20,6 +20,10 @@ * along with Firefly III. If not, see . */ +/** @noinspection MultipleReturnStatementsInspection */ +/** @noinspection PhpStaticAsDynamicMethodCallInspection */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ + declare(strict_types=1); namespace FireflyIII\Console\Commands; @@ -42,7 +46,9 @@ use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionJournalMeta; use FireflyIII\Models\TransactionType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\User; use Illuminate\Console\Command; use Illuminate\Database\QueryException; @@ -50,14 +56,14 @@ use Illuminate\Support\Collection; use Log; use Preferences; use Schema; +use UnexpectedValueException; /** * Class UpgradeDatabase. * * Upgrade user database. - * - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) // it just touches a lot of things. + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class UpgradeDatabase extends Command { @@ -77,7 +83,7 @@ class UpgradeDatabase extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { $this->setTransactionIdentifier(); $this->updateAccountCurrencies(); @@ -93,7 +99,14 @@ class UpgradeDatabase extends Command $this->info('Firefly III database is up to date.'); } - public function migrateBillsToRules() + /** + * Since it is one routine these warnings make sense and should be supressed. + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @SuppressWarnings(PHPMD.NPathComplexity) + */ + public function migrateBillsToRules(): void { foreach (User::get() as $user) { /** @var Preference $lang */ @@ -101,12 +114,20 @@ class UpgradeDatabase extends Command $groupName = (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data); $ruleGroup = $user->ruleGroups()->where('title', $groupName)->first(); $currencyPreference = Preferences::getForUser($user, 'currencyPreference', config('firefly.default_currency', 'EUR')); - $currency = TransactionCurrency::where('code', $currencyPreference->data)->first(); + + if (null === $currencyPreference) { + $this->error('User has no currency preference. Impossible.'); + + return; + } + + $currency = TransactionCurrency::where('code', $currencyPreference->data)->first(); if (null === $currency) { + $this->line('Fall back to default currency in migrateBillsToRules().'); $currency = app('amount')->getDefaultCurrency(); } - if ($ruleGroup === null) { + if (null === $ruleGroup) { $array = RuleGroup::get(['order'])->pluck('order')->toArray(); $order = \count($array) > 0 ? max($array) + 1 : 1; $ruleGroup = RuleGroup::create( @@ -126,7 +147,7 @@ class UpgradeDatabase extends Command $collection = $user->bills()->get(); /** @var Bill $bill */ foreach ($collection as $bill) { - if ($bill->match !== 'MIGRATED_TO_RULES') { + if ('MIGRATED_TO_RULES' !== $bill->match) { $rule = Rule::create( [ 'user_id' => $user->id, @@ -260,23 +281,29 @@ class UpgradeDatabase extends Command /** * Each (asset) account must have a reference to a preferred currency. If the account does not have one, it's forced upon the account. * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's seven but it can't really be helped. + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function updateAccountCurrencies(): void { $accounts = Account::leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') ->whereIn('account_types.type', [AccountType::DEFAULT, AccountType::ASSET])->get(['accounts.*']); - + /** @var AccountRepositoryInterface $repository */ + $repository = app(AccountRepositoryInterface::class); $accounts->each( - function (Account $account) { + function (Account $account) use ($repository) { + $repository->setUser($account->user); // get users preference, fall back to system pref. $defaultCurrencyCode = Preferences::getForUser($account->user, 'currencyPreference', config('firefly.default_currency', 'EUR'))->data; $defaultCurrency = TransactionCurrency::where('code', $defaultCurrencyCode)->first(); - $accountCurrency = (int)$account->getMeta('currency_id'); + $accountCurrency = (int)$repository->getMetaValue($account, 'currency_id'); $openingBalance = $account->getOpeningBalance(); $obCurrency = (int)$openingBalance->transaction_currency_id; + if (null === $defaultCurrency) { + throw new UnexpectedValueException('The default currency is NULL, and this is more or less impossible.'); + } + // both 0? set to default currency: if (0 === $accountCurrency && 0 === $obCurrency) { AccountMeta::where('account_id', $account->id)->where('name', 'currency_id')->forceDelete(); @@ -317,19 +344,22 @@ class UpgradeDatabase extends Command * Both source and destination must match the respective currency preference of the related asset account. * So FF3 must verify all transactions. * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function updateOtherCurrencies(): void { /** @var CurrencyRepositoryInterface $repository */ $repository = app(CurrencyRepositoryInterface::class); - $set = TransactionJournal + /** @var AccountRepositoryInterface $accountRepos */ + $accountRepos = app(AccountRepositoryInterface::class); + $set = TransactionJournal ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') ->whereIn('transaction_types.type', [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::OPENING_BALANCE]) ->get(['transaction_journals.*']); $set->each( - function (TransactionJournal $journal) use ($repository) { + function (TransactionJournal $journal) use ($repository, $accountRepos) { // get the transaction with the asset account in it: /** @var Transaction $transaction */ $transaction = $journal->transactions() @@ -339,9 +369,13 @@ class UpgradeDatabase extends Command if (null === $transaction) { return; } + $accountRepos->setUser($journal->user); /** @var Account $account */ - $account = $transaction->account; - $currency = $repository->find((int)$account->getMeta('currency_id')); + $account = $transaction->account; + $currency = $repository->findNull((int)$accountRepos->getMetaValue($account, 'currency_id')); + if (null === $currency) { + return; + } $transactions = $journal->transactions()->get(); $transactions->each( function (Transaction $transaction) use ($currency) { @@ -377,7 +411,7 @@ class UpgradeDatabase extends Command * Both source and destination must match the respective currency preference. So FF3 must verify ALL * transactions. */ - public function updateTransferCurrencies() + public function updateTransferCurrencies(): void { $set = TransactionJournal ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') @@ -449,6 +483,7 @@ class UpgradeDatabase extends Command */ private function migrateNotes(): void { + /** @noinspection PhpUndefinedMethodInspection */ $set = TransactionJournalMeta::whereName('notes')->get(); /** @var TransactionJournalMeta $meta */ foreach ($set as $meta) { @@ -479,8 +514,15 @@ class UpgradeDatabase extends Command { /** @var CurrencyRepositoryInterface $repository */ $repository = app(CurrencyRepositoryInterface::class); - $currency = $repository->find((int)$transaction->account->getMeta('currency_id')); - $journal = $transaction->transactionJournal; + /** @var AccountRepositoryInterface $accountRepos */ + $accountRepos = app(AccountRepositoryInterface::class); + $accountRepos->setUser($transaction->account->user); + $currency = $repository->findNull((int)$accountRepos->getMetaValue($transaction->account, 'currency_id')); + $journal = $transaction->transactionJournal; + + if (null === $currency) { + return; + } if (!((int)$currency->id === (int)$journal->transaction_currency_id)) { $this->line( @@ -549,11 +591,11 @@ class UpgradeDatabase extends Command * * The transaction that is sent to this function MUST be the source transaction (amount negative). * - * Method is long and complex bit I'm taking it for granted. + * Method is long and complex but I'll allow it. https://imgur.com/gallery/dVDJiez * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) * * @param Transaction $transaction */ @@ -561,7 +603,14 @@ class UpgradeDatabase extends Command { /** @var CurrencyRepositoryInterface $repository */ $repository = app(CurrencyRepositoryInterface::class); - $currency = $repository->findNull((int)$transaction->account->getMeta('currency_id')); + /** @var AccountRepositoryInterface $accountRepos */ + $accountRepos = app(AccountRepositoryInterface::class); + /** @var JournalRepositoryInterface $journalRepos */ + $journalRepos = app(JournalRepositoryInterface::class); + + $accountRepos->setUser($transaction->account->user); + $journalRepos->setUser($transaction->account->user); + $currency = $repository->findNull((int)$accountRepos->getMetaValue($transaction->account, 'currency_id')); if (null === $currency) { Log::error(sprintf('Account #%d ("%s") must have currency preference but has none.', $transaction->account->id, $transaction->account->name)); @@ -597,7 +646,7 @@ class UpgradeDatabase extends Command $journal = $transaction->transactionJournal; /** @var Transaction $opposing */ $opposing = $journal->transactions()->where('amount', '>', 0)->where('identifier', $transaction->identifier)->first(); - $opposingCurrency = $repository->findNull((int)$opposing->account->getMeta('currency_id')); + $opposingCurrency = $repository->findNull((int)$accountRepos->getMetaValue($opposing->account, 'currency_id')); if (null === $opposingCurrency) { Log::error(sprintf('Account #%d ("%s") must have currency preference but has none.', $opposing->account->id, $opposing->account->name)); @@ -653,7 +702,7 @@ class UpgradeDatabase extends Command // when both are zero, try to grab it from journal: if (null === $opposing->foreign_amount && null === $transaction->foreign_amount) { - $foreignAmount = $journal->getMeta('foreign_amount'); + $foreignAmount = $journalRepos->getMetaField($journal, 'foreign_amount'); if (null === $foreignAmount) { Log::debug(sprintf('Journal #%d has missing foreign currency data, forced to do 1:1 conversion :(.', $transaction->transaction_journal_id)); $transaction->foreign_amount = bcmul((string)$transaction->amount, '-1'); diff --git a/app/Console/Commands/UpgradeFireflyInstructions.php b/app/Console/Commands/UpgradeFireflyInstructions.php index 7924e609a0..eae3998a22 100644 --- a/app/Console/Commands/UpgradeFireflyInstructions.php +++ b/app/Console/Commands/UpgradeFireflyInstructions.php @@ -1,5 +1,4 @@ argument('task')) { $this->updateInstructions(); @@ -62,7 +61,7 @@ class UpgradeFireflyInstructions extends Command * * @param string $text */ - private function boxed(string $text) + private function boxed(string $text): void { $parts = explode("\n", wordwrap($text)); foreach ($parts as $string) { @@ -75,7 +74,7 @@ class UpgradeFireflyInstructions extends Command * * @param string $text */ - private function boxedInfo(string $text) + private function boxedInfo(string $text): void { $parts = explode("\n", wordwrap($text)); foreach ($parts as $string) { @@ -86,7 +85,7 @@ class UpgradeFireflyInstructions extends Command /** * Render instructions. */ - private function installInstructions() + private function installInstructions(): void { /** @var string $version */ $version = config('firefly.version'); @@ -94,8 +93,7 @@ class UpgradeFireflyInstructions extends Command $text = ''; foreach (array_keys($config) as $compare) { // if string starts with: - $len = \strlen($compare); - if (substr($version, 0, $len) === $compare) { + if (0 === strpos($version, $compare)) { $text = $config[$compare]; } } @@ -120,7 +118,7 @@ class UpgradeFireflyInstructions extends Command /** * Show a line. */ - private function showLine() + private function showLine(): void { $line = '+'; for ($i = 0; $i < 78; ++$i) { @@ -133,7 +131,7 @@ class UpgradeFireflyInstructions extends Command /** * Render upgrade instructions. */ - private function updateInstructions() + private function updateInstructions(): void { /** @var string $version */ $version = config('firefly.version'); @@ -141,8 +139,7 @@ class UpgradeFireflyInstructions extends Command $text = ''; foreach (array_keys($config) as $compare) { // if string starts with: - $len = \strlen($compare); - if (substr($version, 0, $len) === $compare) { + if (0 === strpos($version, $compare)) { $text = $config[$compare]; } } diff --git a/app/Console/Commands/UseEncryption.php b/app/Console/Commands/UseEncryption.php index e89aff9281..df38fff556 100644 --- a/app/Console/Commands/UseEncryption.php +++ b/app/Console/Commands/UseEncryption.php @@ -1,5 +1,4 @@ info('Firefly III configuration calls for encrypted data.'); } - if (config('firefly.encryption') === false) { + if (false === config('firefly.encryption')) { $this->info('Firefly III configuration calls for unencrypted data.'); } $this->handleObjects('Account', 'name', 'encrypted'); @@ -72,18 +71,21 @@ class UseEncryption extends Command * @param string $field * @param string $indicator */ - public function handleObjects(string $class, string $field, string $indicator) + public function handleObjects(string $class, string $field, string $indicator): void { $fqn = sprintf('FireflyIII\Models\%s', $class); - $encrypt = config('firefly.encryption') === true ? 0 : 1; - $set = $fqn::where($indicator, $encrypt)->get(); + $encrypt = true === config('firefly.encryption') ? 0 : 1; + /** @noinspection PhpUndefinedMethodInspection */ + $set = $fqn::where($indicator, $encrypt)->get(); foreach ($set as $entry) { $newName = $entry->$field; $entry->$field = $newName; + /** @noinspection PhpUndefinedMethodInspection */ $entry->save(); } + /** @noinspection PhpUndefinedMethodInspection */ $this->line(sprintf('Updated %d %s.', $set->count(), strtolower(Str::plural($class)))); } } diff --git a/app/Console/Commands/VerifiesAccessToken.php b/app/Console/Commands/VerifiesAccessToken.php index c03d456b53..b82beee8ab 100644 --- a/app/Console/Commands/VerifiesAccessToken.php +++ b/app/Console/Commands/VerifiesAccessToken.php @@ -1,5 +1,4 @@ . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ + declare(strict_types=1); namespace FireflyIII\Console\Commands; @@ -29,6 +30,7 @@ use DB; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Budget; +use FireflyIII\Models\Category; use FireflyIII\Models\LinkType; use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\Transaction; @@ -39,6 +41,7 @@ use FireflyIII\User; use Illuminate\Console\Command; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Database\Eloquent\Builder; +use Log; use Preferences; use Schema; use stdClass; @@ -46,6 +49,7 @@ use stdClass; /** * Class VerifyDatabase. * + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class VerifyDatabase extends Command @@ -66,15 +70,15 @@ class VerifyDatabase extends Command /** * Execute the console command. */ - public function handle() + public function handle(): void { // if table does not exist, return false if (!Schema::hasTable('users')) { return; } - $this->reportObject('budget'); - $this->reportObject('category'); + $this->reportEmptyBudgets(); + $this->reportEmptyCategories(); $this->reportObject('tag'); $this->reportAccounts(); $this->reportBudgetLimits(); @@ -145,9 +149,10 @@ class VerifyDatabase extends Command } /** - * Fix the situation where the matching transactions - * of a journal somehow have non-matching categories - * or budgets + * Fix the situation where the matching transactions of a journal somehow have non-matching categories or budgets. + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ private function fixBadMeta(): void { @@ -208,6 +213,12 @@ class VerifyDatabase extends Command } } + /** + * Makes sure amounts are stored correctly. + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ private function fixDoubleAmounts(): void { $count = 0; @@ -257,7 +268,7 @@ class VerifyDatabase extends Command } /** - * + * Removes bills from journals that should not have bills. */ private function removeBills(): void { @@ -305,7 +316,7 @@ class VerifyDatabase extends Command /** * Reports on accounts with no transactions. */ - private function reportAccounts() + private function reportAccounts(): void { $set = Account::leftJoin('transactions', 'transactions.account_id', '=', 'accounts.id') ->leftJoin('users', 'accounts.user_id', '=', 'users.id') @@ -378,6 +389,82 @@ class VerifyDatabase extends Command } } + /** + * Report on budgets with no transactions or journals. + */ + private function reportEmptyBudgets(): void + { + $set = Budget::leftJoin('budget_transaction_journal', 'budgets.id', '=', 'budget_transaction_journal.budget_id') + ->leftJoin('users', 'budgets.user_id', '=', 'users.id') + ->distinct() + ->whereNull('budget_transaction_journal.budget_id') + ->whereNull('budgets.deleted_at') + ->get(['budgets.id', 'budgets.name', 'budgets.user_id', 'users.email']); + + /** @var stdClass $entry */ + foreach ($set as $entry) { + $objName = $entry->name; + try { + $objName = Crypt::decrypt($objName); + } catch (DecryptException $e) { + // it probably was not encrypted. + Log::debug(sprintf('Not a problem: %s', $e->getMessage())); + } + + // also count the transactions: + $countTransactions = DB::table('budget_transaction')->where('budget_id', $entry->id)->count(); + + if (0 === $countTransactions) { + $line = sprintf( + 'User #%d (%s) has budget #%d ("%s") which has no transactions.', + $entry->user_id, + $entry->email, + $entry->id, + $objName + ); + $this->line($line); + } + } + } + + /** + * Report on categories with no transactions or journals. + */ + private function reportEmptyCategories(): void + { + $set = Category::leftJoin('category_transaction_journal', 'categories.id', '=', 'category_transaction_journal.category_id') + ->leftJoin('users', 'categories.user_id', '=', 'users.id') + ->distinct() + ->whereNull('category_transaction_journal.category_id') + ->whereNull('categories.deleted_at') + ->get(['categories.id', 'categories.name', 'categories.user_id', 'users.email']); + + /** @var stdClass $entry */ + foreach ($set as $entry) { + $objName = $entry->name; + try { + $objName = Crypt::decrypt($objName); + } catch (DecryptException $e) { + // it probably was not encrypted. + Log::debug(sprintf('Not a problem: %s', $e->getMessage())); + } + + // also count the transactions: + $countTransactions = DB::table('category_transaction')->where('category_id', $entry->id)->count(); + + if (0 === $countTransactions) { + $line = sprintf( + 'User #%d (%s) has category #%d ("%s") which has no transactions.', + $entry->user_id, + $entry->email, + $entry->id, + $objName + ); + $this->line($line); + } + } + } + /** * Report on journals with bad account types linked to them. */ @@ -483,12 +570,13 @@ class VerifyDatabase extends Command $plural = str_plural($name); $class = sprintf('FireflyIII\Models\%s', ucfirst($name)); $field = 'tag' === $name ? 'tag' : 'name'; - $set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id') - ->leftJoin('users', $plural . '.user_id', '=', 'users.id') - ->distinct() - ->whereNull($name . '_transaction_journal.' . $name . '_id') - ->whereNull($plural . '.deleted_at') - ->get([$plural . '.id', $plural . '.' . $field . ' as name', $plural . '.user_id', 'users.email']); + /** @noinspection PhpUndefinedMethodInspection */ + $set = $class::leftJoin($name . '_transaction_journal', $plural . '.id', '=', $name . '_transaction_journal.' . $name . '_id') + ->leftJoin('users', $plural . '.user_id', '=', 'users.id') + ->distinct() + ->whereNull($name . '_transaction_journal.' . $name . '_id') + ->whereNull($plural . '.deleted_at') + ->get([$plural . '.id', $plural . '.' . $field . ' as name', $plural . '.user_id', 'users.email']); /** @var stdClass $entry */ foreach ($set as $entry) { @@ -497,6 +585,7 @@ class VerifyDatabase extends Command $objName = Crypt::decrypt($objName); } catch (DecryptException $e) { // it probably was not encrypted. + Log::debug(sprintf('Not a problem: %s', $e->getMessage())); } $line = sprintf( @@ -524,7 +613,8 @@ class VerifyDatabase extends Command $sum = (string)$user->transactions()->sum('amount'); if (0 !== bccomp($sum, '0')) { $this->error('Error: Transactions for user #' . $user->id . ' (' . $user->email . ') are off by ' . $sum . '!'); - } else { + } + if (0 === bccomp($sum, '0')) { $this->info(sprintf('Amount integrity OK for user #%d', $user->id)); } } @@ -554,7 +644,7 @@ class VerifyDatabase extends Command /** * Report on transfers that have budgets. */ - private function reportTransfersBudgets() + private function reportTransfersBudgets(): void { $set = TransactionJournal::distinct() ->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index bda9202d93..3c1fe481de 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -34,15 +34,6 @@ use Illuminate\Foundation\Console\Kernel as ConsoleKernel; */ class Kernel extends ConsoleKernel { - /** - * The Artisan commands provided by your application. - * - * @var array - */ - protected $commands - = [ - ]; - /** * Register the commands for the application. */ @@ -50,6 +41,7 @@ class Kernel extends ConsoleKernel { $this->load(__DIR__ . '/Commands'); + /** @noinspection PhpIncludeInspection */ require base_path('routes/console.php'); } diff --git a/app/Events/AdminRequestedTestMessage.php b/app/Events/AdminRequestedTestMessage.php index 7198811a0c..800ffb909f 100644 --- a/app/Events/AdminRequestedTestMessage.php +++ b/app/Events/AdminRequestedTestMessage.php @@ -35,13 +35,9 @@ class AdminRequestedTestMessage extends Event { use SerializesModels; - /** - * @var string - */ + /** @var string The users IP address */ public $ipAddress; - /** - * @var User - */ + /** @var User The user */ public $user; /** diff --git a/app/Events/RegisteredUser.php b/app/Events/RegisteredUser.php index 053d0b24c5..1bbb4b25dd 100644 --- a/app/Events/RegisteredUser.php +++ b/app/Events/RegisteredUser.php @@ -34,13 +34,9 @@ class RegisteredUser extends Event { use SerializesModels; - /** - * @var string - */ + /** @var string The users IP address */ public $ipAddress; - /** - * @var User - */ + /** @var User The user */ public $user; /** diff --git a/app/Events/RequestedNewPassword.php b/app/Events/RequestedNewPassword.php index 422cc19872..4452a8dfeb 100644 --- a/app/Events/RequestedNewPassword.php +++ b/app/Events/RequestedNewPassword.php @@ -34,18 +34,12 @@ class RequestedNewPassword extends Event { use SerializesModels; - /** - * @var string - */ + /** @var string The users IP address */ public $ipAddress; - /** - * @var string - */ - public $token; - /** - * @var User - */ + /** @var User The user */ public $user; + /** @var string The token */ + public $token; /** * Create a new event instance. This event is triggered when a users tries to reset his or her password. diff --git a/app/Events/RequestedReportOnJournals.php b/app/Events/RequestedReportOnJournals.php index d4bdf0dbb7..632ebe6570 100644 --- a/app/Events/RequestedReportOnJournals.php +++ b/app/Events/RequestedReportOnJournals.php @@ -1,4 +1,23 @@ . + */ namespace FireflyIII\Events; @@ -16,9 +35,9 @@ class RequestedReportOnJournals { use Dispatchable, InteractsWithSockets, SerializesModels; - /** @var Collection */ + /** @var Collection The journals to report on. */ public $journals; - /** @var int */ + /** @var int The ID of the user. */ public $userId; /** diff --git a/app/Events/RequestedVersionCheckStatus.php b/app/Events/RequestedVersionCheckStatus.php index 6173b031af..dabe9ca7b8 100644 --- a/app/Events/RequestedVersionCheckStatus.php +++ b/app/Events/RequestedVersionCheckStatus.php @@ -35,9 +35,7 @@ class RequestedVersionCheckStatus extends Event { use SerializesModels; - /** - * @var User - */ + /** @var User The user */ public $user; /** diff --git a/app/Events/StoredTransactionJournal.php b/app/Events/StoredTransactionJournal.php index 4db12b1b35..3e1348eb69 100644 --- a/app/Events/StoredTransactionJournal.php +++ b/app/Events/StoredTransactionJournal.php @@ -28,16 +28,17 @@ use FireflyIII\Models\TransactionJournal; use Illuminate\Queue\SerializesModels; /** - * @codeCoverageIgnore * Class StoredTransactionJournal. + * + * @codeCoverageIgnore */ class StoredTransactionJournal extends Event { use SerializesModels; - /** @var TransactionJournal */ + /** @var TransactionJournal The journal that was stored. */ public $journal; - /** @var int */ + /** @var int The piggy bank ID. */ public $piggyBankId; /** diff --git a/app/Events/UpdatedTransactionJournal.php b/app/Events/UpdatedTransactionJournal.php index 5c9c7f7a9b..3d3ef2fff6 100644 --- a/app/Events/UpdatedTransactionJournal.php +++ b/app/Events/UpdatedTransactionJournal.php @@ -37,7 +37,7 @@ class UpdatedTransactionJournal extends Event { use SerializesModels; - /** @var TransactionJournal */ + /** @var TransactionJournal The journal. */ public $journal; /** diff --git a/app/Events/UserChangedEmail.php b/app/Events/UserChangedEmail.php index 2c2d9d8580..917eef90ae 100644 --- a/app/Events/UserChangedEmail.php +++ b/app/Events/UserChangedEmail.php @@ -34,13 +34,13 @@ class UserChangedEmail extends Event { use SerializesModels; - /** @var string */ + /** @var string The user's IP address */ public $ipAddress; - /** @var string */ + /** @var string The user's new email address */ public $newEmail; - /** @var string */ + /** @var string The user's old email address */ public $oldEmail; - /** @var User */ + /** @var User The user itself */ public $user; /** diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 6a72b8ab29..46aec0c792 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -20,6 +20,8 @@ * along with Firefly III. If not, see . */ +/** @noinspection MultipleReturnStatementsInspection */ + declare(strict_types=1); namespace FireflyIII\Exceptions; @@ -39,32 +41,16 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; */ class Handler extends ExceptionHandler { - /** - * A list of the inputs that are never flashed for validation exceptions. - * - * @var array - */ - protected $dontFlash - = [ - 'password', - 'password_confirmation', - ]; - /** - * A list of the exception types that are not reported. - * - * @var array - */ - protected $dontReport - = [ - ]; - /** * Render an exception into an HTTP response. * - * @param \Illuminate\Http\Request $request - * @param \Exception $exception + * @param Request $request + * @param Exception $exception + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * - * @return \Illuminate\Http\Response + * @return mixed */ public function render($request, Exception $exception) { @@ -130,18 +116,10 @@ class Handler extends ExceptionHandler { $doMailError = env('SEND_ERROR_MESSAGE', true); - if ( - // if the user wants us to mail: - $doMailError === true - && ( - // and if is one of these error instances - $exception instanceof FireflyException - || $exception instanceof ErrorException - || $exception instanceof OAuthServerException - - ) - ) { - // then, send email + // if the user wants us to mail: + if (true === $doMailError + // and if is one of these error instances + && ($exception instanceof FireflyException || $exception instanceof ErrorException || $exception instanceof OAuthServerException)) { $userData = [ 'id' => 0, 'email' => 'unknown@example.com', diff --git a/app/Export/Collector/AttachmentCollector.php b/app/Export/Collector/AttachmentCollector.php index 0db72ed3a2..9eecde245b 100644 --- a/app/Export/Collector/AttachmentCollector.php +++ b/app/Export/Collector/AttachmentCollector.php @@ -1,5 +1,4 @@ end = $end; } + /** @noinspection MultipleReturnStatementsInspection */ /** + * Export attachments. + * * @param Attachment $attachment * * @return bool @@ -101,13 +108,13 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface if ($this->uploadDisk->exists($file)) { try { $decrypted = Crypt::decrypt($this->uploadDisk->get($file)); - } catch (DecryptException $e) { + } catch (FileNotFoundException|DecryptException $e) { Log::error('Catchable error: could not decrypt attachment #' . $attachment->id . ' because: ' . $e->getMessage()); return false; } } - if ($decrypted === false) { + if (false === $decrypted) { return false; } $exportFile = $this->exportFileName($attachment); @@ -130,6 +137,8 @@ class AttachmentCollector extends BasicCollector implements CollectorInterface } /** + * Get the attachments. + * * @return Collection */ private function getAttachments(): Collection diff --git a/app/Export/Collector/BasicCollector.php b/app/Export/Collector/BasicCollector.php index bc19f1f541..10215d6c58 100644 --- a/app/Export/Collector/BasicCollector.php +++ b/app/Export/Collector/BasicCollector.php @@ -33,11 +33,11 @@ use Illuminate\Support\Collection; */ class BasicCollector { - /** @var ExportJob */ + /** @var ExportJob The job to export. */ protected $job; - /** @var User */ + /** @var User The user */ protected $user; - /** @var Collection */ + /** @var Collection All the entries. */ private $entries; /** @@ -49,6 +49,8 @@ class BasicCollector } /** + * Get all entries. + * * @return Collection */ public function getEntries(): Collection @@ -57,26 +59,32 @@ class BasicCollector } /** + * Set entries. + * * @param Collection $entries */ - public function setEntries(Collection $entries) + public function setEntries(Collection $entries): void { $this->entries = $entries; } /** + * Set export job. + * * @param ExportJob $job */ - public function setJob(ExportJob $job) + public function setJob(ExportJob $job): void { $this->job = $job; $this->user = $job->user; } /** + * Set user. + * * @param User $user */ - public function setUser(User $user) + public function setUser(User $user): void { $this->user = $user; } diff --git a/app/Export/Collector/CollectorInterface.php b/app/Export/Collector/CollectorInterface.php index bd40c82f29..b93dc1617b 100644 --- a/app/Export/Collector/CollectorInterface.php +++ b/app/Export/Collector/CollectorInterface.php @@ -33,21 +33,29 @@ use Illuminate\Support\Collection; interface CollectorInterface { /** + * Get entries. + * * @return Collection */ public function getEntries(): Collection; /** + * Run the collector. + * * @return bool */ public function run(): bool; /** + * Set entries. + * * @param Collection $entries */ public function setEntries(Collection $entries); /** + * Set export job. + * * @param ExportJob $job * * @return mixed diff --git a/app/Export/Collector/UploadCollector.php b/app/Export/Collector/UploadCollector.php index dd8c71e769..5e1e6df02b 100644 --- a/app/Export/Collector/UploadCollector.php +++ b/app/Export/Collector/UploadCollector.php @@ -1,5 +1,4 @@ . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ + declare(strict_types=1); namespace FireflyIII\Export; @@ -50,23 +51,23 @@ use ZipArchive; */ class ExpandedProcessor implements ProcessorInterface { - /** @var Collection */ + /** @var Collection All accounts */ public $accounts; - /** @var string */ + /** @var string The export format*/ public $exportFormat; - /** @var bool */ + /** @var bool Should include attachments */ public $includeAttachments; - /** @var bool */ + /** @var bool Should include old uploads */ public $includeOldUploads; - /** @var ExportJob */ + /** @var ExportJob The export job itself */ public $job; - /** @var array */ + /** @var array The settings*/ public $settings; - /** @var Collection */ + /** @var Collection The entries to export. */ private $exportEntries; - /** @var Collection */ + /** @var Collection The files to export */ private $files; - /** @var Collection */ + /** @var Collection The journals. */ private $journals; /** @@ -80,6 +81,8 @@ class ExpandedProcessor implements ProcessorInterface } /** + * Collect all attachments + * * @return bool */ public function collectAttachments(): bool @@ -143,6 +146,8 @@ class ExpandedProcessor implements ProcessorInterface } /** + * Get old oploads. + * * @return bool */ public function collectOldUploads(): bool @@ -158,6 +163,8 @@ class ExpandedProcessor implements ProcessorInterface } /** + * Convert journals to export objects. + * * @return bool */ public function convertJournals(): bool @@ -173,6 +180,8 @@ class ExpandedProcessor implements ProcessorInterface } /** + * Create a ZIP file. + * * @return bool * * @throws FireflyException @@ -204,6 +213,8 @@ class ExpandedProcessor implements ProcessorInterface } /** + * Export the journals. + * * @return bool */ public function exportJournals(): bool @@ -219,6 +230,8 @@ class ExpandedProcessor implements ProcessorInterface } /** + * Get files. + * * @return Collection */ public function getFiles(): Collection @@ -231,7 +244,7 @@ class ExpandedProcessor implements ProcessorInterface * * @param array $settings */ - public function setSettings(array $settings) + public function setSettings(array $settings): void { // save settings $this->settings = $settings; @@ -243,9 +256,9 @@ class ExpandedProcessor implements ProcessorInterface } /** - * + * Delete files. */ - private function deleteFiles() + private function deleteFiles():void { $disk = Storage::disk('export'); foreach ($this->getFiles() as $file) { @@ -254,6 +267,8 @@ class ExpandedProcessor implements ProcessorInterface } /** + * Get currencies. + * * @param array $array * * @return array diff --git a/app/Export/Exporter/BasicExporter.php b/app/Export/Exporter/BasicExporter.php index 02826171c2..fd1003ddfa 100644 --- a/app/Export/Exporter/BasicExporter.php +++ b/app/Export/Exporter/BasicExporter.php @@ -32,9 +32,9 @@ use Illuminate\Support\Collection; */ class BasicExporter { - /** @var ExportJob */ + /** @var ExportJob The export job */ protected $job; - /** @var Collection */ + /** @var Collection The entries */ private $entries; /** @@ -46,6 +46,8 @@ class BasicExporter } /** + * Get all entries. + * * @return Collection */ public function getEntries(): Collection @@ -54,17 +56,21 @@ class BasicExporter } /** + * Set all entries. + * * @param Collection $entries */ - public function setEntries(Collection $entries) + public function setEntries(Collection $entries): void { $this->entries = $entries; } /** + * Set the job. + * * @param ExportJob $job */ - public function setJob(ExportJob $job) + public function setJob(ExportJob $job): void { $this->job = $job; } diff --git a/app/Export/Exporter/CsvExporter.php b/app/Export/Exporter/CsvExporter.php index e323b94bf9..bbc66b8345 100644 --- a/app/Export/Exporter/CsvExporter.php +++ b/app/Export/Exporter/CsvExporter.php @@ -33,10 +33,12 @@ use Storage; */ class CsvExporter extends BasicExporter implements ExporterInterface { - /** @var string */ + /** @var string Filename */ private $fileName; /** + * Get file name. + * * @return string */ public function getFileName(): string @@ -45,6 +47,8 @@ class CsvExporter extends BasicExporter implements ExporterInterface } /** + * Run collector. + * * @return bool * */ @@ -83,6 +87,9 @@ class CsvExporter extends BasicExporter implements ExporterInterface return true; } + /** + * Make a temp file. + */ private function tempFile() { $this->fileName = $this->job->key . '-records.csv'; diff --git a/app/Export/Exporter/ExporterInterface.php b/app/Export/Exporter/ExporterInterface.php index f10e763dab..cc44b69c08 100644 --- a/app/Export/Exporter/ExporterInterface.php +++ b/app/Export/Exporter/ExporterInterface.php @@ -33,26 +33,36 @@ use Illuminate\Support\Collection; interface ExporterInterface { /** + * Get entries. + * * @return Collection */ public function getEntries(): Collection; /** + * Get file name. + * * @return string */ public function getFileName(): string; /** + * Run exporter. + * * @return bool */ public function run(): bool; /** + * Set entries. + * * @param Collection $entries */ public function setEntries(Collection $entries); /** + * Set job. + * * @param ExportJob $job */ public function setJob(ExportJob $job); diff --git a/app/Export/ProcessorInterface.php b/app/Export/ProcessorInterface.php index ad8745cc7c..641e26eaeb 100644 --- a/app/Export/ProcessorInterface.php +++ b/app/Export/ProcessorInterface.php @@ -37,41 +37,57 @@ interface ProcessorInterface public function __construct(); /** + * Collect all attachments. + * * @return bool */ public function collectAttachments(): bool; /** + * Collect all journals. + * * @return bool */ public function collectJournals(): bool; /** + * Collect old uploads. + * * @return bool */ public function collectOldUploads(): bool; /** + * Convert all journals. + * * @return bool */ public function convertJournals(): bool; /** + * Create a zip file. + * * @return bool */ public function createZipFile(): bool; /** + * Export journals. + * * @return bool */ public function exportJournals(): bool; /** + * Get all files. + * * @return Collection */ public function getFiles(): Collection; /** + * Set the settings. + * * @param array $settings */ public function setSettings(array $settings); diff --git a/app/Factory/AccountFactory.php b/app/Factory/AccountFactory.php index 81383d4143..a3e7f3d4a3 100644 --- a/app/Factory/AccountFactory.php +++ b/app/Factory/AccountFactory.php @@ -20,10 +20,14 @@ * along with Firefly III. If not, see . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ +/** @noinspection PhpUndefinedMethodInspection */ + declare(strict_types=1); namespace FireflyIII\Factory; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Services\Internal\Support\AccountServiceTrait; @@ -44,56 +48,63 @@ class AccountFactory * @param array $data * * @return Account + * @throws FireflyException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function create(array $data): Account { - $type = $this->getAccountType($data['account_type_id'], $data['accountType']); + $type = $this->getAccountType($data['account_type_id'], $data['accountType']); + + if (null === $type) { + throw new FireflyException( + sprintf('AccountFactory::create() was unable to find account type #%d ("%s").', $data['account_type_id'], $data['accountType']) + ); + } + $data['iban'] = $this->filterIban($data['iban']); - // account may exist already: - $existingAccount = $this->find($data['name'], $type->type); - if (null !== $existingAccount) { - return $existingAccount; + $return = $this->find($data['name'], $type->type); + + + if (null === $return) { + // create it: + $databaseData + = [ + 'user_id' => $this->user->id, + 'account_type_id' => $type->id, + 'name' => $data['name'], + 'virtual_balance' => $data['virtualBalance'] ?? '0', + 'active' => true === $data['active'], + 'iban' => $data['iban'], + ]; + + // remove virtual balance when not an asset account: + if ($type->type !== AccountType::ASSET) { + $databaseData['virtual_balance'] = '0'; + } + + // fix virtual balance when it's empty + if ('' === $databaseData['virtual_balance']) { + $databaseData['virtual_balance'] = '0'; + } + + $return = Account::create($databaseData); + $this->updateMetaData($return, $data); + + if ($type->type === AccountType::ASSET) { + if ($this->validIBData($data)) { + $this->updateIB($return, $data); + } + if (!$this->validIBData($data)) { + $this->deleteIB($return); + } + } + $this->updateNote($return, $data['notes'] ?? ''); } - - // create it: - $databaseData - = [ - 'user_id' => $this->user->id, - 'account_type_id' => $type->id, - 'name' => $data['name'], - 'virtual_balance' => $data['virtualBalance'] ?? '0', - 'active' => true === $data['active'], - 'iban' => $data['iban'], - ]; - - // remove virtual balance when not an asset account: - if ($type->type !== AccountType::ASSET) { - $databaseData['virtual_balance'] = '0'; - } - - // fix virtual balance when it's empty - if ($databaseData['virtual_balance'] === '') { - $databaseData['virtual_balance'] = '0'; - } - - $newAccount = Account::create($databaseData); - $this->updateMetaData($newAccount, $data); - - if ($this->validIBData($data) && $type->type === AccountType::ASSET) { - $this->updateIB($newAccount, $data); - } - if (!$this->validIBData($data) && $type->type === AccountType::ASSET) { - $this->deleteIB($newAccount); - } - // update note: - if (isset($data['notes'])) { - $this->updateNote($newAccount, $data['notes']); - } - - return $newAccount; + return $return; } /** @@ -106,15 +117,16 @@ class AccountFactory { $type = AccountType::whereType($accountType)->first(); $accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']); - + $return = null; /** @var Account $object */ foreach ($accounts as $object) { if ($object->name === $accountName) { - return $object; + $return = $object; + break; } } - return null; + return $return; } /** @@ -122,30 +134,35 @@ class AccountFactory * @param string $accountType * * @return Account + * @throws FireflyException */ public function findOrCreate(string $accountName, string $accountType): Account { $type = AccountType::whereType($accountType)->first(); $accounts = $this->user->accounts()->where('account_type_id', $type->id)->get(['accounts.*']); - + $return = null; /** @var Account $object */ foreach ($accounts as $object) { if ($object->name === $accountName) { - return $object; + $return = $object; + break; } } + if (null === $return) { + $return = $this->create( + [ + 'user_id' => $this->user->id, + 'name' => $accountName, + 'account_type_id' => $type->id, + 'accountType' => null, + 'virtualBalance' => '0', + 'iban' => null, + 'active' => true, + ] + ); + } - return $this->create( - [ - 'user_id' => $this->user->id, - 'name' => $accountName, - 'account_type_id' => $type->id, - 'accountType' => null, - 'virtualBalance' => '0', - 'iban' => null, - 'active' => true, - ] - ); + return $return; } /** @@ -161,18 +178,23 @@ class AccountFactory * @param null|string $accountType * * @return AccountType|null + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ protected function getAccountType(?int $accountTypeId, ?string $accountType): ?AccountType { $accountTypeId = (int)$accountTypeId; + $result = null; if ($accountTypeId > 0) { - return AccountType::find($accountTypeId); + $result = AccountType::find($accountTypeId); } - $type = config('firefly.accountTypeByIdentifier.' . (string)$accountType); - $result = AccountType::whereType($type)->first(); - if (null === $result && null !== $accountType) { - // try as full name: - $result = AccountType::whereType($accountType)->first(); + if (null === $result) { + /** @var string $type */ + $type = (string)config('firefly.accountTypeByIdentifier.' . (string)$accountType); + $result = AccountType::whereType($type)->first(); + if (null === $result && null !== $accountType) { + // try as full name: + $result = AccountType::whereType($accountType)->first(); + } } return $result; diff --git a/app/Factory/BillFactory.php b/app/Factory/BillFactory.php index 101d225452..a3de276298 100644 --- a/app/Factory/BillFactory.php +++ b/app/Factory/BillFactory.php @@ -81,25 +81,19 @@ class BillFactory { $billId = (int)$billId; $billName = (string)$billName; - + $bill = null; // first find by ID: if ($billId > 0) { /** @var Bill $bill */ $bill = $this->user->bills()->find($billId); - if (null !== $bill) { - return $bill; - } } // then find by name: - if (\strlen($billName) > 0) { + if (null === $bill && \strlen($billName) > 0) { $bill = $this->findByName($billName); - if (null !== $bill) { - return $bill; - } } - return null; + return $bill; } @@ -112,22 +106,24 @@ class BillFactory { /** @var Collection $collection */ $collection = $this->user->bills()->get(); + $return = null; /** @var Bill $bill */ foreach ($collection as $bill) { Log::debug(sprintf('"%s" vs. "%s"', $bill->name, $name)); if ($bill->name === $name) { - return $bill; + $return = $bill; + break; } } - Log::debug(sprintf('Bill::Find by name returns NULL based on "%s"', $name)); + Log::debug(sprintf('Bill::find("%s") by name returns null? %s', $name, var_export($return, true))); - return null; + return $return; } /** * @param User $user */ - public function setUser(User $user) + public function setUser(User $user): void { $this->user = $user; } diff --git a/app/Factory/BudgetFactory.php b/app/Factory/BudgetFactory.php index ba9315f4ec..49ec300f00 100644 --- a/app/Factory/BudgetFactory.php +++ b/app/Factory/BudgetFactory.php @@ -1,5 +1,4 @@ . */ - +/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); @@ -30,7 +29,7 @@ use FireflyIII\User; use Illuminate\Support\Collection; /** - * Class BudgetFactory + * Class BudgetFactory. */ class BudgetFactory { @@ -43,13 +42,14 @@ class BudgetFactory * @param null|string $budgetName * * @return Budget|null + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function find(?int $budgetId, ?string $budgetName): ?Budget { $budgetId = (int)$budgetId; $budgetName = (string)$budgetName; - if (\strlen($budgetName) === 0 && $budgetId === 0) { + if (0 === $budgetId && '' === $budgetName) { return null; } @@ -62,7 +62,7 @@ class BudgetFactory } } - if (\strlen($budgetName) > 0) { + if ('' !== $budgetName) { $budget = $this->findByName($budgetName); if (null !== $budget) { return $budget; @@ -94,7 +94,7 @@ class BudgetFactory /** * @param User $user */ - public function setUser(User $user) + public function setUser(User $user): void { $this->user = $user; } diff --git a/app/Factory/CategoryFactory.php b/app/Factory/CategoryFactory.php index 245d8e9eb6..f68fe7c732 100644 --- a/app/Factory/CategoryFactory.php +++ b/app/Factory/CategoryFactory.php @@ -1,5 +1,4 @@ . */ - +/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; @@ -64,6 +63,7 @@ class CategoryFactory * @param null|string $categoryName * * @return Category|null + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function findOrCreate(?int $categoryId, ?string $categoryName): ?Category { @@ -72,7 +72,7 @@ class CategoryFactory Log::debug(sprintf('Going to find category with ID %d and name "%s"', $categoryId, $categoryName)); - if ('' === $categoryName && $categoryId === 0) { + if ('' === $categoryName && 0 === $categoryId) { return null; } // first by ID: @@ -104,7 +104,7 @@ class CategoryFactory /** * @param User $user */ - public function setUser(User $user) + public function setUser(User $user): void { $this->user = $user; } diff --git a/app/Factory/PiggyBankEventFactory.php b/app/Factory/PiggyBankEventFactory.php index d4a586ba03..8117ddddcb 100644 --- a/app/Factory/PiggyBankEventFactory.php +++ b/app/Factory/PiggyBankEventFactory.php @@ -1,5 +1,4 @@ . */ - +/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; @@ -43,6 +42,7 @@ class PiggyBankEventFactory * @param PiggyBank|null $piggyBank * * @return PiggyBankEvent|null + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function create(TransactionJournal $journal, ?PiggyBank $piggyBank): ?PiggyBankEvent { @@ -51,7 +51,6 @@ class PiggyBankEventFactory return null; } - // is a transfer? if (!(TransactionType::TRANSFER === $journal->transactionType->type)) { Log::info(sprintf('Will not connect %s #%d to a piggy bank.', $journal->transactionType->type, $journal->id)); @@ -62,7 +61,6 @@ class PiggyBankEventFactory $piggyRepos = app(PiggyBankRepositoryInterface::class); $piggyRepos->setUser($journal->user); - // repetition exists? $repetition = $piggyRepos->getRepetition($piggyBank); if (null === $repetition) { Log::error(sprintf('No piggy bank repetition on %s!', $journal->date->format('Y-m-d'))); @@ -70,7 +68,6 @@ class PiggyBankEventFactory return null; } - // get the amount $amount = $piggyRepos->getExactAmount($piggyBank, $repetition, $journal); if (0 === bccomp($amount, '0')) { Log::debug('Amount is zero, will not create event.'); @@ -78,10 +75,8 @@ class PiggyBankEventFactory return null; } - // update amount $piggyRepos->addAmountToRepetition($repetition, $amount); $event = $piggyRepos->createEventWithJournal($piggyBank, $amount, $journal); - Log::debug(sprintf('Created piggy bank event #%d', $event->id)); return $event; diff --git a/app/Factory/PiggyBankFactory.php b/app/Factory/PiggyBankFactory.php index ce398c3697..a81a421bf9 100644 --- a/app/Factory/PiggyBankFactory.php +++ b/app/Factory/PiggyBankFactory.php @@ -1,5 +1,4 @@ . */ - +/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; @@ -41,12 +40,13 @@ class PiggyBankFactory * @param null|string $piggyBankName * * @return PiggyBank|null + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank { $piggyBankId = (int)$piggyBankId; $piggyBankName = (string)$piggyBankName; - if (\strlen($piggyBankName) === 0 && $piggyBankId === 0) { + if ('' === $piggyBankName && 0 === $piggyBankId) { return null; } // first find by ID: @@ -92,7 +92,7 @@ class PiggyBankFactory /** * @param User $user */ - public function setUser(User $user) + public function setUser(User $user): void { $this->user = $user; diff --git a/app/Factory/RecurrenceFactory.php b/app/Factory/RecurrenceFactory.php index f144022ed7..f21c760df1 100644 --- a/app/Factory/RecurrenceFactory.php +++ b/app/Factory/RecurrenceFactory.php @@ -18,12 +18,14 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; +use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Recurrence; use FireflyIII\Services\Internal\Support\RecurringTransactionTrait; @@ -56,6 +58,9 @@ class RecurrenceFactory return null; } + /** @var Carbon $firstDate */ + $firstDate = $data['recurrence']['first_date']; + $repetitions = (int)$data['recurrence']['repetitions']; $recurrence = new Recurrence( [ @@ -63,7 +68,7 @@ class RecurrenceFactory 'transaction_type_id' => $type->id, 'title' => $data['recurrence']['title'], 'description' => $data['recurrence']['description'], - 'first_date' => $data['recurrence']['first_date']->format('Y-m-d'), + 'first_date' => $firstDate->format('Y-m-d'), 'repeat_until' => $repetitions > 0 ? null : $data['recurrence']['repeat_until'], 'latest_date' => null, 'repetitions' => $data['recurrence']['repetitions'], diff --git a/app/Factory/TagFactory.php b/app/Factory/TagFactory.php index 1fdd0e74a8..d3399d04a2 100644 --- a/app/Factory/TagFactory.php +++ b/app/Factory/TagFactory.php @@ -1,5 +1,4 @@ . */ +/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); diff --git a/app/Factory/TransactionCurrencyFactory.php b/app/Factory/TransactionCurrencyFactory.php index e57e1f81d1..b2d75737c2 100644 --- a/app/Factory/TransactionCurrencyFactory.php +++ b/app/Factory/TransactionCurrencyFactory.php @@ -1,5 +1,4 @@ . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ +/** @noinspection PhpUndefinedMethodInspection */ +/** @noinspection MultipleReturnStatementsInspection */ + declare(strict_types=1); namespace FireflyIII\Factory; @@ -63,13 +66,14 @@ class TransactionCurrencyFactory * @param null|string $currencyCode * * @return TransactionCurrency|null + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function find(?int $currencyId, ?string $currencyCode): ?TransactionCurrency { $currencyCode = (string)$currencyCode; $currencyId = (int)$currencyId; - if ('' === $currencyCode && $currencyId === 0) { + if ('' === $currencyCode && 0 === $currencyId) { Log::warning('Cannot find anything on empty currency code and empty currency ID!'); return null; diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php index bb7bdc2550..35a435faa7 100644 --- a/app/Factory/TransactionFactory.php +++ b/app/Factory/TransactionFactory.php @@ -50,6 +50,7 @@ class TransactionFactory * * @return Transaction * @throws FireflyException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function create(array $data): ?Transaction { @@ -89,37 +90,41 @@ class TransactionFactory * * @return Collection * @throws FireflyException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function createPair(TransactionJournal $journal, array $data): Collection { - Log::debug('Start of TransactionFactory::createPair()'); + Log::debug('Start of TransactionFactory::createPair()', $data); // all this data is the same for both transactions: $currency = $this->findCurrency($data['currency_id'], $data['currency_code']); $description = $journal->description === $data['description'] ? null : $data['description']; - // type of source account depends on journal type: - $sourceType = $this->accountType($journal, 'source'); - Log::debug(sprintf('Expect source account to be of type %s', $sourceType)); - $sourceAccount = $this->findAccount($sourceType, $data['source_id'], $data['source_name']); - - // same for destination account: + // type of source account and destination account depends on journal type: + $sourceType = $this->accountType($journal, 'source'); $destinationType = $this->accountType($journal, 'destination'); - Log::debug(sprintf('Expect source destination to be of type %s', $destinationType)); + + Log::debug(sprintf('Expect source account to be of type "%s"', $sourceType)); + Log::debug(sprintf('Expect source destination to be of type "%s"', $destinationType)); + + // find source and destination account: + $sourceAccount = $this->findAccount($sourceType, $data['source_id'], $data['source_name']); $destinationAccount = $this->findAccount($destinationType, $data['destination_id'], $data['destination_name']); + if (null === $sourceAccount || null === $destinationAccount) { + throw new FireflyException('Could not determine source or destination account.'); + } + Log::debug(sprintf('Source type is "%s", destination type is "%s"', $sourceAccount->accountType->type, $destinationAccount->accountType->type)); - // throw big fat error when source type === dest type - if ($sourceAccount->accountType->type === $destinationAccount->accountType->type - && ($journal->transactionType->type !== TransactionType::TRANSFER - && $journal->transactionType->type !== TransactionType::RECONCILIATION) - ) { + // throw big fat error when source type === dest type and it's not a transfer or reconciliation. + if ($sourceAccount->accountType->type === $destinationAccount->accountType->type && $journal->transactionType->type !== TransactionType::TRANSFER) { throw new FireflyException(sprintf('Source and destination account cannot be both of the type "%s"', $destinationAccount->accountType->type)); } if ($sourceAccount->accountType->type !== AccountType::ASSET && $destinationAccount->accountType->type !== AccountType::ASSET) { throw new FireflyException('At least one of the accounts must be an asset account.'); } - // first make a "negative" (source) transaction based on the data in the array. $source = $this->create( [ 'description' => $description, @@ -132,8 +137,7 @@ class TransactionFactory 'identifier' => $data['identifier'], ] ); - // then make a "positive" transaction based on the data in the array. - $dest = $this->create( + $dest = $this->create( [ 'description' => $description, 'amount' => app('steam')->positive((string)$data['amount']), @@ -145,6 +149,9 @@ class TransactionFactory 'identifier' => $data['identifier'], ] ); + if (null === $source || null === $dest) { + throw new FireflyException('Could not create transactions.'); + } // set foreign currency $foreign = $this->findCurrency($data['foreign_currency_id'], $data['foreign_currency_code']); @@ -178,7 +185,7 @@ class TransactionFactory /** * @param User $user */ - public function setUser(User $user) + public function setUser(User $user): void { $this->user = $user; } diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php index e81c50c087..42061110f8 100644 --- a/app/Factory/TransactionJournalFactory.php +++ b/app/Factory/TransactionJournalFactory.php @@ -37,14 +37,18 @@ use Log; class TransactionJournalFactory { use JournalServiceTrait, TransactionTypeTrait; - /** @var User */ + /** @var User The user */ private $user; /** + * Store a new transaction journal. + * * @param array $data * * @return TransactionJournal * @throws FireflyException + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function create(array $data): TransactionJournal { @@ -124,6 +128,8 @@ class TransactionJournalFactory } /** + * Link a piggy bank to this journal. + * * @param TransactionJournal $journal * @param array $data */ diff --git a/app/Factory/TransactionJournalMetaFactory.php b/app/Factory/TransactionJournalMetaFactory.php index 2af8397c0a..7ffc1db139 100644 --- a/app/Factory/TransactionJournalMetaFactory.php +++ b/app/Factory/TransactionJournalMetaFactory.php @@ -1,5 +1,4 @@ . */ +/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); @@ -38,6 +38,8 @@ class TransactionJournalMetaFactory * @param array $data * * @return TransactionJournalMeta|null + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function updateOrCreate(array $data): ?TransactionJournalMeta { @@ -57,7 +59,7 @@ class TransactionJournalMetaFactory if ($data['data'] instanceof Carbon) { $value = $data['data']->toW3cString(); } - if ((string)$value === '') { + if ('' === (string)$value) { // don't store blank strings. if (null !== $entry) { try { diff --git a/app/Factory/TransactionTypeFactory.php b/app/Factory/TransactionTypeFactory.php index 03db2cbd13..05f0fdf67d 100644 --- a/app/Factory/TransactionTypeFactory.php +++ b/app/Factory/TransactionTypeFactory.php @@ -19,6 +19,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpUndefinedMethodInspection */ declare(strict_types=1); diff --git a/app/Generator/Chart/Basic/ChartJsGenerator.php b/app/Generator/Chart/Basic/ChartJsGenerator.php index ef66a2b7cf..c21522586e 100644 --- a/app/Generator/Chart/Basic/ChartJsGenerator.php +++ b/app/Generator/Chart/Basic/ChartJsGenerator.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Generator\Chart\Basic; use FireflyIII\Support\ChartColour; -use Steam; /** * Class ChartJsGenerator. @@ -90,7 +89,7 @@ class ChartJsGenerator implements GeneratorInterface if (isset($set['currency_symbol'])) { $currentSet['currency_symbol'] = $set['currency_symbol']; } - if(isset($set['backgroundColor'])) { + if (isset($set['backgroundColor'])) { $currentSet['backgroundColor'] = $set['backgroundColor']; } $chartData['datasets'][] = $currentSet; @@ -130,7 +129,7 @@ class ChartJsGenerator implements GeneratorInterface $index = 0; foreach ($data as $key => $value) { // make larger than 0 - $chartData['datasets'][0]['data'][] = (float)Steam::positive($value); + $chartData['datasets'][0]['data'][] = (float)app('steam')->positive($value); $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); $chartData['labels'][] = $key; ++$index; diff --git a/app/Generator/Report/Account/MonthReportGenerator.php b/app/Generator/Report/Account/MonthReportGenerator.php index d3dc1e659d..49f0cbfbd7 100644 --- a/app/Generator/Report/Account/MonthReportGenerator.php +++ b/app/Generator/Report/Account/MonthReportGenerator.php @@ -31,17 +31,20 @@ use Illuminate\Support\Collection; */ class MonthReportGenerator implements ReportGeneratorInterface { - /** @var Collection */ + /** @var Collection The accounts involved in the report. */ private $accounts; - /** @var Carbon */ + /** @var Carbon The end date */ private $end; - /** @var Collection */ + /** @var Collection The expense accounts. */ private $expense; - /** @var Carbon */ + /** @var Carbon The start date. */ private $start; /** + * Generate the report. + * * @return string + * @throws \Throwable */ public function generate(): string { @@ -57,6 +60,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set accounts. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -69,6 +74,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set budgets. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -79,6 +86,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set categories. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -89,6 +98,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set end date. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -101,6 +112,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set expense collection. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -113,6 +126,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set start date. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -125,6 +140,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set collection of tags. + * * @param Collection $tags * * @return ReportGeneratorInterface @@ -135,6 +152,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Return the preferred period. + * * @return string */ protected function preferredPeriod(): string diff --git a/app/Generator/Report/Account/MultiYearReportGenerator.php b/app/Generator/Report/Account/MultiYearReportGenerator.php index 690891b8e1..a4d17d0d83 100644 --- a/app/Generator/Report/Account/MultiYearReportGenerator.php +++ b/app/Generator/Report/Account/MultiYearReportGenerator.php @@ -27,9 +27,9 @@ namespace FireflyIII\Generator\Report\Account; */ class MultiYearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. - /** + * Returns the preferred period. + * * @return string */ protected function preferredPeriod(): string diff --git a/app/Generator/Report/Account/YearReportGenerator.php b/app/Generator/Report/Account/YearReportGenerator.php index f5031da9e2..c1e890ba19 100644 --- a/app/Generator/Report/Account/YearReportGenerator.php +++ b/app/Generator/Report/Account/YearReportGenerator.php @@ -27,9 +27,9 @@ namespace FireflyIII\Generator\Report\Account; */ class YearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. - /** + * Returns the preferred period. + * * @return string */ protected function preferredPeriod(): string diff --git a/app/Generator/Report/Audit/MonthReportGenerator.php b/app/Generator/Report/Audit/MonthReportGenerator.php index a4acdfcb24..278190c1cb 100644 --- a/app/Generator/Report/Audit/MonthReportGenerator.php +++ b/app/Generator/Report/Audit/MonthReportGenerator.php @@ -18,33 +18,40 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ + +/** @noinspection PhpUndefinedMethodInspection */ + declare(strict_types=1); namespace FireflyIII\Generator\Report\Audit; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Models\Account; use FireflyIII\Models\Transaction; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use Illuminate\Support\Collection; -use Steam; /** * Class MonthReportGenerator. */ class MonthReportGenerator implements ReportGeneratorInterface { - /** @var Collection */ + /** @var Collection The accounts used. */ private $accounts; - /** @var Carbon */ + /** @var Carbon End date of the report. */ private $end; - /** @var Carbon */ + /** @var Carbon Start date of the report. */ private $start; /** + * Generates the report. + * * @return string + * @throws \Throwable */ public function generate(): string { @@ -77,6 +84,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Account collection setter. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -89,6 +98,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Budget collection setter. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -99,6 +110,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Category collection setter. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -109,6 +122,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * End date setter. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -121,6 +136,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Expenses collection setter. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -131,6 +148,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Start date collection setter. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -143,6 +162,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Tags collection setter. + * * @param Collection $tags * * @return ReportGeneratorInterface @@ -153,26 +174,37 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Get the audit report. + * * @param Account $account * @param Carbon $date * * @return array * * @SuppressWarnings(PHPMD.ExcessiveMethodLength) // not that long + * @throws FireflyException */ private function getAuditReport(Account $account, Carbon $date): array { /** @var CurrencyRepositoryInterface $currencyRepos */ $currencyRepos = app(CurrencyRepositoryInterface::class); + /** @var AccountRepositoryInterface $accountRepository */ + $accountRepository = app(AccountRepositoryInterface::class); + $accountRepository->setUser($account->user); + /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAccounts(new Collection([$account]))->setRange($this->start, $this->end); $journals = $collector->getJournals(); $journals = $journals->reverse(); - $dayBeforeBalance = Steam::balance($account, $date); + $dayBeforeBalance = app('steam')->balance($account, $date); $startBalance = $dayBeforeBalance; - $currency = $currencyRepos->find((int)$account->getMeta('currency_id')); + $currency = $currencyRepos->findNull((int)$accountRepository->getMetaValue($account, 'currency_id')); + + if (null === $currency) { + throw new FireflyException('Unexpected NULL value in account currency preference.'); + } /** @var Transaction $transaction */ foreach ($journals as $transaction) { @@ -183,17 +215,16 @@ class MonthReportGenerator implements ReportGeneratorInterface $transactionAmount = $transaction->transaction_foreign_amount; } - $newBalance = bcadd($startBalance, $transactionAmount); - $transaction->after = $newBalance; - $startBalance = $newBalance; - $transaction->currency = $currency; + $newBalance = bcadd($startBalance, $transactionAmount); + $transaction->after = $newBalance; + $startBalance = $newBalance; } $return = [ 'journals' => $journals->reverse(), 'exists' => $journals->count() > 0, 'end' => $this->end->formatLocalized((string)trans('config.month_and_day')), - 'endBalance' => Steam::balance($account, $this->end), + 'endBalance' => app('steam')->balance($account, $this->end), 'dayBefore' => $date->formatLocalized((string)trans('config.month_and_day')), 'dayBeforeBalance' => $dayBeforeBalance, ]; diff --git a/app/Generator/Report/Audit/MultiYearReportGenerator.php b/app/Generator/Report/Audit/MultiYearReportGenerator.php index 00df62d2db..0bd3b5697f 100644 --- a/app/Generator/Report/Audit/MultiYearReportGenerator.php +++ b/app/Generator/Report/Audit/MultiYearReportGenerator.php @@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Audit; */ class MultiYearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. } diff --git a/app/Generator/Report/Audit/YearReportGenerator.php b/app/Generator/Report/Audit/YearReportGenerator.php index 4855e6aeee..e341718728 100644 --- a/app/Generator/Report/Audit/YearReportGenerator.php +++ b/app/Generator/Report/Audit/YearReportGenerator.php @@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Audit; */ class YearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. } diff --git a/app/Generator/Report/Budget/MonthReportGenerator.php b/app/Generator/Report/Budget/MonthReportGenerator.php index d5e0a8a9a0..ff4229ab26 100644 --- a/app/Generator/Report/Budget/MonthReportGenerator.php +++ b/app/Generator/Report/Budget/MonthReportGenerator.php @@ -18,6 +18,8 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection MultipleReturnStatementsInspection */ +/** @noinspection PhpUndefinedMethodInspection */ declare(strict_types=1); namespace FireflyIII\Generator\Report\Budget; @@ -39,17 +41,15 @@ use Log; */ class MonthReportGenerator extends Support implements ReportGeneratorInterface { - /** @var Collection */ + /** @var Collection The accounts in the report. */ private $accounts; - /** @var Collection */ + /** @var Collection The budgets in the report. */ private $budgets; - /** @var Carbon */ + /** @var Carbon The end date. */ private $end; - /** @var Collection */ + /** @var Collection The expenses in the report. */ private $expenses; - /** @var Collection */ - private $income; - /** @var Carbon */ + /** @var Carbon The start date. */ private $start; /** @@ -57,12 +57,14 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface */ public function __construct() { - $this->income = new Collection; $this->expenses = new Collection; } /** + * Generates the report. + * * @return string + * @throws \Throwable */ public function generate(): string { @@ -83,6 +85,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the involved accounts. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -95,6 +99,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the involved budgets. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -107,6 +113,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Unused category setter. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -117,6 +125,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the end date of the report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -129,6 +139,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Unused expense setter. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -139,6 +151,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the start date of the report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -151,6 +165,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Unused tags setter. + * * @param Collection $tags * * @return ReportGeneratorInterface @@ -161,6 +177,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Get the expenses. + * * @return Collection */ protected function getExpenses(): Collection @@ -188,6 +206,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Summarize a collection by its budget. + * * @param Collection $collection * * @return array diff --git a/app/Generator/Report/Budget/MultiYearReportGenerator.php b/app/Generator/Report/Budget/MultiYearReportGenerator.php index 13e4fc81b0..1e32b8d8ce 100644 --- a/app/Generator/Report/Budget/MultiYearReportGenerator.php +++ b/app/Generator/Report/Budget/MultiYearReportGenerator.php @@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Budget; */ class MultiYearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. } diff --git a/app/Generator/Report/Budget/YearReportGenerator.php b/app/Generator/Report/Budget/YearReportGenerator.php index 44ff2349b1..a025513451 100644 --- a/app/Generator/Report/Budget/YearReportGenerator.php +++ b/app/Generator/Report/Budget/YearReportGenerator.php @@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Budget; */ class YearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. } diff --git a/app/Generator/Report/Category/MonthReportGenerator.php b/app/Generator/Report/Category/MonthReportGenerator.php index 31ca187d53..ef187a575b 100644 --- a/app/Generator/Report/Category/MonthReportGenerator.php +++ b/app/Generator/Report/Category/MonthReportGenerator.php @@ -18,6 +18,8 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection MultipleReturnStatementsInspection */ +/** @noinspection PhpUndefinedMethodInspection */ declare(strict_types=1); namespace FireflyIII\Generator\Report\Category; @@ -40,17 +42,17 @@ use Log; */ class MonthReportGenerator extends Support implements ReportGeneratorInterface { - /** @var Collection */ + /** @var Collection The included accounts */ private $accounts; - /** @var Collection */ + /** @var Collection The included categories */ private $categories; - /** @var Carbon */ + /** @var Carbon The end date */ private $end; - /** @var Collection */ + /** @var Collection The expenses */ private $expenses; - /** @var Collection */ + /** @var Collection The income in the report. */ private $income; - /** @var Carbon */ + /** @var Carbon The start date. */ private $start; /** @@ -63,7 +65,10 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Generates the report. + * * @return string + * @throws \Throwable */ public function generate(): string { @@ -101,6 +106,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the involved accounts. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -113,6 +120,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Empty budget setter. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -123,6 +132,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the categories involved in this report. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -135,6 +146,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the end date for this report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -147,6 +160,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the expenses involved in this report. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -157,6 +172,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the start date for this report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -169,6 +186,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Unused tag setter. + * * @param Collection $tags * * @return ReportGeneratorInterface @@ -179,6 +198,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Get the expenses for this report. + * * @return Collection */ protected function getExpenses(): Collection @@ -206,6 +227,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Get the income for this report. + * * @return Collection */ protected function getIncome(): Collection @@ -230,6 +253,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Summarize the category. + * * @param Collection $collection * * @return array diff --git a/app/Generator/Report/Category/MultiYearReportGenerator.php b/app/Generator/Report/Category/MultiYearReportGenerator.php index 1ce99f992f..2fe96eb9cd 100644 --- a/app/Generator/Report/Category/MultiYearReportGenerator.php +++ b/app/Generator/Report/Category/MultiYearReportGenerator.php @@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Category; */ class MultiYearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. } diff --git a/app/Generator/Report/Category/YearReportGenerator.php b/app/Generator/Report/Category/YearReportGenerator.php index d769979990..920ea366e7 100644 --- a/app/Generator/Report/Category/YearReportGenerator.php +++ b/app/Generator/Report/Category/YearReportGenerator.php @@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Category; */ class YearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. } diff --git a/app/Generator/Report/ReportGeneratorFactory.php b/app/Generator/Report/ReportGeneratorFactory.php index e06cb5b3ac..6e06480a33 100644 --- a/app/Generator/Report/ReportGeneratorFactory.php +++ b/app/Generator/Report/ReportGeneratorFactory.php @@ -31,6 +31,8 @@ use FireflyIII\Exceptions\FireflyException; class ReportGeneratorFactory { /** + * Static report generator class. + * * @param string $type * @param Carbon $start * @param Carbon $end diff --git a/app/Generator/Report/ReportGeneratorInterface.php b/app/Generator/Report/ReportGeneratorInterface.php index 42d1d158b2..db0369ce17 100644 --- a/app/Generator/Report/ReportGeneratorInterface.php +++ b/app/Generator/Report/ReportGeneratorInterface.php @@ -31,11 +31,15 @@ use Illuminate\Support\Collection; interface ReportGeneratorInterface { /** + * Generate the report. + * * @return string */ public function generate(): string; /** + * Set the involved accounts. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -43,6 +47,8 @@ interface ReportGeneratorInterface public function setAccounts(Collection $accounts): ReportGeneratorInterface; /** + * Set the involved budgets. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -50,6 +56,8 @@ interface ReportGeneratorInterface public function setBudgets(Collection $budgets): ReportGeneratorInterface; /** + * Set the involved categories. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -57,6 +65,8 @@ interface ReportGeneratorInterface public function setCategories(Collection $categories): ReportGeneratorInterface; /** + * Set the end date. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -64,6 +74,8 @@ interface ReportGeneratorInterface public function setEndDate(Carbon $date): ReportGeneratorInterface; /** + * Set the expense accounts. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -71,6 +83,8 @@ interface ReportGeneratorInterface public function setExpense(Collection $expense): ReportGeneratorInterface; /** + * Set the start date. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -78,6 +92,8 @@ interface ReportGeneratorInterface public function setStartDate(Carbon $date): ReportGeneratorInterface; /** + * Set the tags. + * * @param Collection $tags * * @return ReportGeneratorInterface diff --git a/app/Generator/Report/Standard/MonthReportGenerator.php b/app/Generator/Report/Standard/MonthReportGenerator.php index 348efb6975..e27f4d79ed 100644 --- a/app/Generator/Report/Standard/MonthReportGenerator.php +++ b/app/Generator/Report/Standard/MonthReportGenerator.php @@ -32,15 +32,18 @@ use Illuminate\Support\Collection; */ class MonthReportGenerator implements ReportGeneratorInterface { - /** @var Collection */ + /** @var Collection The accounts involved in the report. */ private $accounts; - /** @var Carbon */ + /** @var Carbon The end date. */ private $end; - /** @var Carbon */ + /** @var Carbon The start date. */ private $start; /** + * Generates the report. + * * @return string + * @throws \Throwable */ public function generate(): string { @@ -58,6 +61,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Sets the accounts involved in the report. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -70,6 +75,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Unused budget setter. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -80,6 +87,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Unused category setter. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -90,6 +99,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set the end date of the report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -102,6 +113,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set the expenses used in this report. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -112,6 +125,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set the start date of this report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -124,6 +139,8 @@ class MonthReportGenerator implements ReportGeneratorInterface } /** + * Set the tags used in this report. + * * @param Collection $tags * * @return ReportGeneratorInterface diff --git a/app/Generator/Report/Standard/MultiYearReportGenerator.php b/app/Generator/Report/Standard/MultiYearReportGenerator.php index d03465386e..ec507b9386 100644 --- a/app/Generator/Report/Standard/MultiYearReportGenerator.php +++ b/app/Generator/Report/Standard/MultiYearReportGenerator.php @@ -31,15 +31,18 @@ use Illuminate\Support\Collection; */ class MultiYearReportGenerator implements ReportGeneratorInterface { - /** @var Collection */ + /** @var Collection The accounts involved. */ private $accounts; - /** @var Carbon */ + /** @var Carbon The end date. */ private $end; - /** @var Carbon */ + /** @var Carbon The start date. */ private $start; /** + * Generates the report. + * * @return string + * @throws \Throwable */ public function generate(): string { @@ -55,6 +58,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface } /** + * Sets the accounts used in the report. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -67,6 +72,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface } /** + * Sets the budgets used in the report. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -77,6 +84,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface } /** + * Sets the categories used in the report. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -87,6 +96,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface } /** + * Sets the end date used in the report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -99,6 +110,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface } /** + * Unused setter for expenses. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -109,6 +122,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface } /** + * Set the start date of the report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -121,6 +136,8 @@ class MultiYearReportGenerator implements ReportGeneratorInterface } /** + * Set the tags for the report. + * * @param Collection $tags * * @return ReportGeneratorInterface diff --git a/app/Generator/Report/Standard/YearReportGenerator.php b/app/Generator/Report/Standard/YearReportGenerator.php index 900758a1ca..47f92f47ad 100644 --- a/app/Generator/Report/Standard/YearReportGenerator.php +++ b/app/Generator/Report/Standard/YearReportGenerator.php @@ -31,15 +31,18 @@ use Illuminate\Support\Collection; */ class YearReportGenerator implements ReportGeneratorInterface { - /** @var Collection */ + /** @var Collection The accounts involved. */ private $accounts; - /** @var Carbon */ + /** @var Carbon The end date. */ private $end; - /** @var Carbon */ + /** @var Carbon The start date. */ private $start; /** + * Generates the report. + * * @return string + * @throws \Throwable */ public function generate(): string { @@ -55,6 +58,8 @@ class YearReportGenerator implements ReportGeneratorInterface } /** + * Set the accounts. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -67,6 +72,8 @@ class YearReportGenerator implements ReportGeneratorInterface } /** + * Unused budget setter. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -77,6 +84,8 @@ class YearReportGenerator implements ReportGeneratorInterface } /** + * Unused categories setter. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -87,6 +96,8 @@ class YearReportGenerator implements ReportGeneratorInterface } /** + * Set the end date. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -99,6 +110,8 @@ class YearReportGenerator implements ReportGeneratorInterface } /** + * Set the expenses used. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -109,6 +122,8 @@ class YearReportGenerator implements ReportGeneratorInterface } /** + * Set the start date. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -121,6 +136,8 @@ class YearReportGenerator implements ReportGeneratorInterface } /** + * Unused tags setter. + * * @param Collection $tags * * @return ReportGeneratorInterface diff --git a/app/Generator/Report/Support.php b/app/Generator/Report/Support.php index f739509769..f3d757e63d 100644 --- a/app/Generator/Report/Support.php +++ b/app/Generator/Report/Support.php @@ -18,6 +18,8 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpUndefinedMethodInspection */ +/** @noinspection PhpUndefinedMethodInspection */ declare(strict_types=1); namespace FireflyIII\Generator\Report; @@ -31,6 +33,8 @@ use Illuminate\Support\Collection; class Support { /** + * Get the top expenses. + * * @return Collection */ public function getTopExpenses(): Collection @@ -39,6 +43,8 @@ class Support } /** + * Get the top income. + * * @return Collection */ public function getTopIncome(): Collection @@ -47,6 +53,8 @@ class Support } /** + * Get averages from a collection. + * * @param Collection $collection * @param int $sortFlag * @@ -89,6 +97,8 @@ class Support } /** + * Summarize collection by earned and spent data. + * * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five. * * @param array $spent @@ -117,7 +127,6 @@ class Support $return[$objectId]['spent'] = $entry; $return['sum']['spent'] = bcadd($return['sum']['spent'], $entry); } - unset($entry); /** * @var int @@ -136,6 +145,8 @@ class Support } /** + * Summarize the data by account. + * * @param Collection $collection * * @return array diff --git a/app/Generator/Report/Tag/MonthReportGenerator.php b/app/Generator/Report/Tag/MonthReportGenerator.php index 678339cc12..1c5affa011 100644 --- a/app/Generator/Report/Tag/MonthReportGenerator.php +++ b/app/Generator/Report/Tag/MonthReportGenerator.php @@ -18,6 +18,9 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ + +/** @noinspection MultipleReturnStatementsInspection */ +/** @noinspection PhpUndefinedMethodInspection */ declare(strict_types=1); namespace FireflyIII\Generator\Report\Tag; @@ -41,17 +44,17 @@ use Log; */ class MonthReportGenerator extends Support implements ReportGeneratorInterface { - /** @var Collection */ + /** @var Collection The accounts involved */ private $accounts; - /** @var Carbon */ + /** @var Carbon The end date */ private $end; - /** @var Collection */ + /** @var Collection The expenses involved */ private $expenses; - /** @var Collection */ + /** @var Collection The income involved */ private $income; - /** @var Carbon */ + /** @var Carbon The start date */ private $start; - /** @var Collection */ + /** @var Collection The tags involved. */ private $tags; /** @@ -64,7 +67,11 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Generate the report. + * * @return string + * @throws \Throwable + * @throws \Throwable */ public function generate(): string { @@ -98,6 +105,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the accounts. + * * @param Collection $accounts * * @return ReportGeneratorInterface @@ -110,6 +119,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Unused budget setter. + * * @param Collection $budgets * * @return ReportGeneratorInterface @@ -120,6 +131,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Unused category setter. + * * @param Collection $categories * * @return ReportGeneratorInterface @@ -130,6 +143,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the end date of the report. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -142,6 +157,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the expenses in this report. + * * @param Collection $expense * * @return ReportGeneratorInterface @@ -152,6 +169,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the start date. + * * @param Carbon $date * * @return ReportGeneratorInterface @@ -164,6 +183,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Set the tags used in this report. + * * @param Collection $tags * * @return ReportGeneratorInterface @@ -176,6 +197,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Get expense collection for report. + * * @return Collection */ protected function getExpenses(): Collection @@ -204,6 +227,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Get the income for this report. + * * @return Collection */ protected function getIncome(): Collection @@ -228,6 +253,8 @@ class MonthReportGenerator extends Support implements ReportGeneratorInterface } /** + * Summarize by tag. + * * @param Collection $collection * * @return array diff --git a/app/Generator/Report/Tag/MultiYearReportGenerator.php b/app/Generator/Report/Tag/MultiYearReportGenerator.php index 1b5aa1993f..0d6380416b 100644 --- a/app/Generator/Report/Tag/MultiYearReportGenerator.php +++ b/app/Generator/Report/Tag/MultiYearReportGenerator.php @@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Tag; */ class MultiYearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. } diff --git a/app/Generator/Report/Tag/YearReportGenerator.php b/app/Generator/Report/Tag/YearReportGenerator.php index abb8dc9efc..0cb3f216a0 100644 --- a/app/Generator/Report/Tag/YearReportGenerator.php +++ b/app/Generator/Report/Tag/YearReportGenerator.php @@ -27,5 +27,4 @@ namespace FireflyIII\Generator\Report\Tag; */ class YearReportGenerator extends MonthReportGenerator { - // Doesn't do anything different. } diff --git a/app/Handlers/Events/APIEventHandler.php b/app/Handlers/Events/APIEventHandler.php index e73b151e86..5be569d2a2 100644 --- a/app/Handlers/Events/APIEventHandler.php +++ b/app/Handlers/Events/APIEventHandler.php @@ -39,6 +39,8 @@ use Session; class APIEventHandler { /** + * Respond to the creation of an access token. + * * @param AccessTokenCreated $event * * @return bool @@ -48,28 +50,24 @@ class APIEventHandler /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); $user = $repository->findNull((int)$event->userId); - if (null === $user) { - Log::error('Access Token generated but no user associated.'); + if (null !== $user) { + $email = $user->email; + $ipAddress = Request::ip(); - return true; + Log::debug(sprintf('Now in APIEventHandler::accessTokenCreated. Email is %s, IP is %s', $email, $ipAddress)); + try { + Log::debug('Trying to send message...'); + Mail::to($email)->send(new AccessTokenCreatedMail($email, $ipAddress)); + // @codeCoverageIgnoreStart + } catch (Exception $e) { + Log::debug('Send message failed! :('); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); + Session::flash('error', 'Possible email error: ' . $e->getMessage()); + } + Log::debug('If no error above this line, message was sent.'); } - $email = $user->email; - $ipAddress = Request::ip(); - - Log::debug(sprintf('Now in APIEventHandler::accessTokenCreated. Email is %s, IP is %s', $email, $ipAddress)); - try { - Log::debug('Trying to send message...'); - Mail::to($email)->send(new AccessTokenCreatedMail($email, $ipAddress)); - // @codeCoverageIgnoreStart - } catch (Exception $e) { - Log::debug('Send message failed! :('); - Log::error($e->getMessage()); - Log::error($e->getTraceAsString()); - Session::flash('error', 'Possible email error: ' . $e->getMessage()); - } - Log::debug('If no error above this line, message was sent.'); - // @codeCoverageIgnoreEnd return true; diff --git a/app/Handlers/Events/AdminEventHandler.php b/app/Handlers/Events/AdminEventHandler.php index 83225c7e53..1bc55af2ba 100644 --- a/app/Handlers/Events/AdminEventHandler.php +++ b/app/Handlers/Events/AdminEventHandler.php @@ -48,27 +48,24 @@ class AdminEventHandler $repository = app(UserRepositoryInterface::class); // is user even admin? - if (!$repository->hasRole($event->user, 'owner')) { - return true; + if ($repository->hasRole($event->user, 'owner')) { + $email = $event->user->email; + $ipAddress = $event->ipAddress; + + Log::debug(sprintf('Now in sendTestMessage event handler. Email is %s, IP is %s', $email, $ipAddress)); + try { + Log::debug('Trying to send message...'); + Mail::to($email)->send(new AdminTestMail($email, $ipAddress)); + // @codeCoverageIgnoreStart + } catch (Exception $e) { + Log::debug('Send message failed! :('); + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); + Session::flash('error', 'Possible email error: ' . $e->getMessage()); + } + Log::debug('If no error above this line, message was sent.'); } - - $email = $event->user->email; - $ipAddress = $event->ipAddress; - - Log::debug(sprintf('Now in sendTestMessage event handler. Email is %s, IP is %s', $email, $ipAddress)); - try { - Log::debug('Trying to send message...'); - Mail::to($email)->send(new AdminTestMail($email, $ipAddress)); - // @codeCoverageIgnoreStart - } catch (Exception $e) { - Log::debug('Send message failed! :('); - Log::error($e->getMessage()); - Log::error($e->getTraceAsString()); - Session::flash('error', 'Possible email error: ' . $e->getMessage()); - } - Log::debug('If no error above this line, message was sent.'); - // @codeCoverageIgnoreEnd return true; } diff --git a/app/Handlers/Events/AutomationHandler.php b/app/Handlers/Events/AutomationHandler.php index 3585e0ccf2..bc694b4108 100644 --- a/app/Handlers/Events/AutomationHandler.php +++ b/app/Handlers/Events/AutomationHandler.php @@ -37,6 +37,8 @@ class AutomationHandler { /** + * Respond to the creation of X journals. + * * @param RequestedReportOnJournals $event * * @return bool @@ -47,25 +49,16 @@ class AutomationHandler /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); $user = $repository->findNull($event->userId); - if (null === $user) { - Log::debug('User is NULL'); - - return true; + if (null !== $user && 0 !== $event->journals->count()) { + try { + Log::debug('Trying to mail...'); + Mail::to($user->email)->send(new ReportNewJournalsMail($user->email, '127.0.0.1', $event->journals)); + // @codeCoverageIgnoreStart + } catch (Exception $e) { + Log::error($e->getMessage()); + } + Log::debug('Done!'); } - if ($event->journals->count() === 0) { - Log::debug('No journals.'); - - return true; - } - - try { - Log::debug('Trying to mail...'); - Mail::to($user->email)->send(new ReportNewJournalsMail($user->email, '127.0.0.1', $event->journals)); - // @codeCoverageIgnoreStart - } catch (Exception $e) { - Log::error($e->getMessage()); - } - Log::debug('Done!'); // @codeCoverageIgnoreEnd return true; diff --git a/app/Handlers/Events/StoredJournalEventHandler.php b/app/Handlers/Events/StoredJournalEventHandler.php index 43ca29745b..db3fcb41f2 100644 --- a/app/Handlers/Events/StoredJournalEventHandler.php +++ b/app/Handlers/Events/StoredJournalEventHandler.php @@ -25,35 +25,33 @@ namespace FireflyIII\Handlers\Events; use FireflyIII\Events\StoredTransactionJournal; use FireflyIII\Models\Rule; use FireflyIII\Models\RuleGroup; -use FireflyIII\Repositories\Journal\JournalRepositoryInterface as JRI; -use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface as PRI; -use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface as RGRI; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; +use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\TransactionRules\Processor; /** - * @codeCoverageIgnore - * * Class StoredJournalEventHandler */ class StoredJournalEventHandler { - /** @var JRI */ + /** @var JournalRepositoryInterface The journal repository. */ public $journalRepository; - /** @var PRI */ + /** @var PiggyBankRepositoryInterface The Piggy bank repository */ public $repository; - - /** @var RGRI */ + /** @var RuleGroupRepositoryInterface The rule group repository */ public $ruleGroupRepository; /** * StoredJournalEventHandler constructor. * - * @param PRI $repository - * @param JRI $journalRepository - * @param RGRI $ruleGroupRepository + * @param PiggyBankRepositoryInterface $repository + * @param JournalRepositoryInterface $journalRepository + * @param RuleGroupRepositoryInterface $ruleGroupRepository */ - public function __construct(PRI $repository, JRI $journalRepository, RGRI $ruleGroupRepository) - { + public function __construct( + PiggyBankRepositoryInterface $repository, JournalRepositoryInterface $journalRepository, RuleGroupRepositoryInterface $ruleGroupRepository + ) { $this->repository = $repository; $this->journalRepository = $journalRepository; $this->ruleGroupRepository = $ruleGroupRepository; diff --git a/app/Handlers/Events/UpdatedJournalEventHandler.php b/app/Handlers/Events/UpdatedJournalEventHandler.php index ac06e95908..f6308e08e3 100644 --- a/app/Handlers/Events/UpdatedJournalEventHandler.php +++ b/app/Handlers/Events/UpdatedJournalEventHandler.php @@ -29,13 +29,11 @@ use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\TransactionRules\Processor; /** - * @codeCoverageIgnore - * * Class UpdatedJournalEventHandler */ class UpdatedJournalEventHandler { - /** @var RuleGroupRepositoryInterface */ + /** @var RuleGroupRepositoryInterface The rule group repository */ public $repository; /** diff --git a/app/Handlers/Events/UserEventHandler.php b/app/Handlers/Events/UserEventHandler.php index 64ef4a83fc..530562ab60 100644 --- a/app/Handlers/Events/UserEventHandler.php +++ b/app/Handlers/Events/UserEventHandler.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection NullPointerExceptionInspection */ declare(strict_types=1); namespace FireflyIII\Handlers\Events; @@ -26,7 +27,6 @@ use Exception; use FireflyIII\Events\RegisteredUser; use FireflyIII\Events\RequestedNewPassword; use FireflyIII\Events\UserChangedEmail; -use FireflyIII\Factories\RoleFactory; use FireflyIII\Mail\ConfirmEmailChangeMail; use FireflyIII\Mail\RegisteredUser as RegisteredUserMail; use FireflyIII\Mail\RequestedNewPassword as RequestedNewPasswordMail; @@ -44,6 +44,7 @@ use Preferences; * This class responds to any events that have anything to do with the User object. * * The method name reflects what is being done. This is in the present tense. + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class UserEventHandler { @@ -68,6 +69,8 @@ class UserEventHandler } /** + * Fires to see if a user is admin. + * * @param Login $event * * @return bool @@ -81,34 +84,27 @@ class UserEventHandler $user = $event->user; $count = $repository->count(); - if ($count > 1) { - // if more than one user, do nothing. - Log::debug(sprintf('System has %d users, will not change users roles.', $count)); + // only act when there is 1 user in the system and he has no admin rights. + if (1 === $count && !$repository->hasRole($user, 'owner')) { + // user is the only user but does not have role "owner". + $role = $repository->getRole('owner'); + if (null === $role) { + // create role, does not exist. Very strange situation so let's raise a big fuss about it. + $role = $repository->createRole('owner', 'Site Owner', 'User runs this instance of FF3'); + Log::error('Could not find role "owner". This is weird.'); + } - return true; + Log::info(sprintf('Gave user #%d role #%d ("%s")', $user->id, $role->id, $role->name)); + // give user the role + $repository->attachRole($user, 'owner'); } - // user is only user but has admin role - if (1 === $count && $user->hasRole('owner')) { - Log::debug(sprintf('User #%d is only user but has role owner so all is well.', $user->id)); - - return true; - } - // user is the only user but does not have role "owner". - $role = $repository->getRole('owner'); - if (null === $role) { - // create role, does not exist. Very strange situation so let's raise a big fuss about it. - $role = $repository->createRole('owner', 'Site Owner', 'User runs this instance of FF3'); - Log::error('Could not find role "owner". This is weird.'); - } - - Log::info(sprintf('Gave user #%d role #%d ("%s")', $user->id, $role->id, $role->name)); - // give user the role - $repository->attachRole($user, 'owner'); return true; } /** + * Set the demo user back to English. + * * @param Login $event * * @return bool @@ -130,6 +126,8 @@ class UserEventHandler } /** + * Send email to confirm email change. + * * @param UserChangedEmail $event * * @return bool @@ -154,6 +152,8 @@ class UserEventHandler } /** + * Send email to be able to undo email change. + * * @param UserChangedEmail $event * * @return bool @@ -178,6 +178,8 @@ class UserEventHandler } /** + * Send a new password to the user. + * * @param RequestedNewPassword $event * * @return bool @@ -211,27 +213,25 @@ class UserEventHandler * * @return bool */ - public function sendRegistrationMail(RegisteredUser $event) + public function sendRegistrationMail(RegisteredUser $event): bool { $sendMail = env('SEND_REGISTRATION_MAIL', true); - if (!$sendMail) { - return true; // @codeCoverageIgnore - } - // get the email address - $email = $event->user->email; - $uri = route('index'); - $ipAddress = $event->ipAddress; + if ($sendMail) { + // get the email address + $email = $event->user->email; + $uri = route('index'); + $ipAddress = $event->ipAddress; - // send email. - try { - Mail::to($email)->send(new RegisteredUserMail($uri, $ipAddress)); - // @codeCoverageIgnoreStart - } catch (Exception $e) { - Log::error($e->getMessage()); + // send email. + try { + Mail::to($email)->send(new RegisteredUserMail($uri, $ipAddress)); + // @codeCoverageIgnoreStart + } catch (Exception $e) { + Log::error($e->getMessage()); + } + // @codeCoverageIgnoreEnd } - // @codeCoverageIgnoreEnd - return true; } } diff --git a/app/Handlers/Events/VersionCheckEventHandler.php b/app/Handlers/Events/VersionCheckEventHandler.php index 2b7b9a1f0f..b7e7a14ced 100644 --- a/app/Handlers/Events/VersionCheckEventHandler.php +++ b/app/Handlers/Events/VersionCheckEventHandler.php @@ -18,14 +18,17 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ - +/** @noinspection MultipleReturnStatementsInspection */ +/** @noinspection NullPointerExceptionInspection */ declare(strict_types=1); namespace FireflyIII\Handlers\Events; +use Carbon\Carbon; use FireflyConfig; use FireflyIII\Events\RequestedVersionCheckStatus; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Helpers\Update\UpdateTrait; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Services\Github\Object\Release; use FireflyIII\Services\Github\Request\UpdateRequest; @@ -37,21 +40,26 @@ use Log; */ class VersionCheckEventHandler { + use UpdateTrait; /** + * Checks with GitHub to see if there is a new version. + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.NPathComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @param RequestedVersionCheckStatus $event */ public function checkForUpdates(RequestedVersionCheckStatus $event): void { // in Sandstorm, cannot check for updates: $sandstorm = 1 === (int)getenv('SANDSTORM'); - if ($sandstorm === true) { + if (true === $sandstorm) { return; // @codeCoverageIgnore } /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); - /** @var User $user */ $user = $event->user; if (!$repository->hasRole($user, 'owner')) { @@ -66,7 +74,7 @@ class VersionCheckEventHandler if ($diff < 604800) { Log::debug(sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data))); - return; + //return; } // last check time was more than a week ago. @@ -75,48 +83,17 @@ class VersionCheckEventHandler // have actual permission? if ($permission->data === -1) { // never asked before. - session()->flash('info', (string)trans('firefly.check_for_updates_permission', ['link' => route('admin.update-check')])); - - return; + //session()->flash('info', (string)trans('firefly.check_for_updates_permission', ['link' => route('admin.update-check')])); + //return; } - $current = config('firefly.version'); - /** @var UpdateRequest $request */ - $request = app(UpdateRequest::class); - $check = -2; - $first = new Release(['id' => '0', 'title' => '0.2', 'updated' => '2017-01-01', 'content' => '']); - try { - $request->call(); - $releases = $request->getReleases(); - // first entry should be the latest entry: - /** @var Release $first */ - $first = reset($releases); - $check = version_compare($current, $first->getTitle()); - Log::debug(sprintf('Comparing %s with %s, result is %s', $current, $first->getTitle(), $check)); - FireflyConfig::set('last_update_check', time()); - } catch (FireflyException $e) { - Log::error(sprintf('Could not check for updates: %s', $e->getMessage())); - } - $string = 'no result: ' . $check; - if ($check === -2) { - $string = (string)trans('firefly.update_check_error'); - } - if ($check === -1) { - // there is a new FF version! - $monthAndDayFormat = (string)trans('config.month_and_day'); - $string = (string)trans( - 'firefly.update_new_version_alert', - [ - 'your_version' => $current, - 'new_version' => $first->getTitle(), - 'date' => $first->getUpdated()->formatLocalized($monthAndDayFormat), - ] - ); - } - if ($check !== 0) { + $latestRelease = $this->getLatestRelease(); + $versionCheck = $this->versionCheck($latestRelease); + $resultString = $this->parseResult($latestRelease, $versionCheck); + if (0 !== $versionCheck && '' !== $resultString) { // flash info - session()->flash('info', $string); + session()->flash('info', $resultString); } + FireflyConfig::set('last_update_check', time()); } - } diff --git a/app/Helpers/Attachments/AttachmentHelper.php b/app/Helpers/Attachments/AttachmentHelper.php index b6d950042f..849705f2da 100644 --- a/app/Helpers/Attachments/AttachmentHelper.php +++ b/app/Helpers/Attachments/AttachmentHelper.php @@ -38,18 +38,18 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; */ class AttachmentHelper implements AttachmentHelperInterface { - /** @var Collection */ + /** @var Collection All attachments */ public $attachments; - /** @var MessageBag */ + /** @var MessageBag All errors */ public $errors; - /** @var MessageBag */ + /** @var MessageBag All messages */ public $messages; - /** @var array */ + /** @var array Allowed mimes */ protected $allowedMimes = []; - /** @var int */ + /** @var int Max upload size. */ protected $maxUploadSize = 0; - /** @var \Illuminate\Contracts\Filesystem\Filesystem */ + /** @var \Illuminate\Contracts\Filesystem\Filesystem The disk where attachments are stored. */ protected $uploadDisk; @@ -67,6 +67,8 @@ class AttachmentHelper implements AttachmentHelperInterface } /** + * Returns the content of an attachment. + * * @codeCoverageIgnore * * @param Attachment $attachment @@ -75,18 +77,19 @@ class AttachmentHelper implements AttachmentHelperInterface */ public function getAttachmentContent(Attachment $attachment): string { + $content = ''; try { $content = Crypt::decrypt($this->uploadDisk->get(sprintf('at-%d.data', $attachment->id))); } catch (DecryptException|FileNotFoundException $e) { - Log::error(sprintf('Could not decrypt data of attachment #%d', $attachment->id)); - - return ''; + Log::error(sprintf('Could not decrypt data of attachment #%d: %s', $attachment->id, $e->getMessage())); } return $content; } /** + * Returns the file location for an attachment, + * * @param Attachment $attachment * * @return string @@ -99,6 +102,8 @@ class AttachmentHelper implements AttachmentHelperInterface } /** + * Get all attachments. + * * @return Collection */ public function getAttachments(): Collection @@ -107,6 +112,8 @@ class AttachmentHelper implements AttachmentHelperInterface } /** + * Get all errors. + * * @return MessageBag */ public function getErrors(): MessageBag @@ -115,6 +122,8 @@ class AttachmentHelper implements AttachmentHelperInterface } /** + * Get all messages. + * * @return MessageBag */ public function getMessages(): MessageBag @@ -122,6 +131,7 @@ class AttachmentHelper implements AttachmentHelperInterface return $this->messages; } + /** @noinspection MultipleReturnStatementsInspection */ /** * Uploads a file as a string. * @@ -163,6 +173,8 @@ class AttachmentHelper implements AttachmentHelperInterface } /** + * Save attachments that get uploaded with models, through the app. + * * @param Model $model * @param array|null $files * @@ -180,15 +192,17 @@ class AttachmentHelper implements AttachmentHelperInterface } } Log::debug('Done processing uploads.'); - - return true; } - Log::debug('Array of files is not an array. Probably nothing uploaded. Will not store attachments.'); + if (!\is_array($files) || (\is_array($files) && 0 === \count($files))) { + Log::debug('Array of files is not an array. Probably nothing uploaded. Will not store attachments.'); + } return true; } /** + * Check if a model already has this file attached. + * * @param UploadedFile $file * @param Model $model * @@ -199,67 +213,70 @@ class AttachmentHelper implements AttachmentHelperInterface $md5 = md5_file($file->getRealPath()); $name = $file->getClientOriginalName(); $class = \get_class($model); - $count = $model->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(); - + /** @noinspection PhpUndefinedFieldInspection */ + $count = $model->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(); + $result = false; if ($count > 0) { $msg = (string)trans('validation.file_already_attached', ['name' => $name]); $this->errors->add('attachments', $msg); Log::error($msg); - - return true; + $result = true; } - return false; + return $result; } /** + * Process the upload of a file. + * * @param UploadedFile $file * @param Model $model * - * @return Attachment + * @return Attachment|null * @throws \Illuminate\Contracts\Encryption\EncryptException */ - protected function processFile(UploadedFile $file, Model $model): Attachment + protected function processFile(UploadedFile $file, Model $model): ?Attachment { Log::debug('Now in processFile()'); $validation = $this->validateUpload($file, $model); - if (false === $validation) { - return new Attachment; + $attachment = null; + if (false !== $validation) { + $attachment = new Attachment; // create Attachment object. + /** @noinspection PhpUndefinedFieldInspection */ + $attachment->user()->associate($model->user); + $attachment->attachable()->associate($model); + $attachment->md5 = md5_file($file->getRealPath()); + $attachment->filename = $file->getClientOriginalName(); + $attachment->mime = $file->getMimeType(); + $attachment->size = $file->getSize(); + $attachment->uploaded = 0; + $attachment->save(); + Log::debug('Created attachment:', $attachment->toArray()); + + $fileObject = $file->openFile('r'); + $fileObject->rewind(); + $content = $fileObject->fread($file->getSize()); + $encrypted = Crypt::encrypt($content); + Log::debug(sprintf('Full file length is %d and upload size is %d.', \strlen($content), $file->getSize())); + Log::debug(sprintf('Encrypted content is %d', \strlen($encrypted))); + + // store it: + $this->uploadDisk->put($attachment->fileName(), $encrypted); + $attachment->uploaded = 1; // update attachment + $attachment->save(); + $this->attachments->push($attachment); + + $name = e($file->getClientOriginalName()); // add message: + $msg = (string)trans('validation.file_attached', ['name' => $name]); + $this->messages->add('attachments', $msg); } - $attachment = new Attachment; // create Attachment object. - $attachment->user()->associate($model->user); - $attachment->attachable()->associate($model); - $attachment->md5 = md5_file($file->getRealPath()); - $attachment->filename = $file->getClientOriginalName(); - $attachment->mime = $file->getMimeType(); - $attachment->size = $file->getSize(); - $attachment->uploaded = 0; - $attachment->save(); - Log::debug('Created attachment:', $attachment->toArray()); - - $fileObject = $file->openFile('r'); - $fileObject->rewind(); - $content = $fileObject->fread($file->getSize()); - $encrypted = Crypt::encrypt($content); - Log::debug(sprintf('Full file length is %d and upload size is %d.', \strlen($content), $file->getSize())); - Log::debug(sprintf('Encrypted content is %d', \strlen($encrypted))); - - // store it: - $this->uploadDisk->put($attachment->fileName(), $encrypted); - $attachment->uploaded = 1; // update attachment - $attachment->save(); - $this->attachments->push($attachment); - - $name = e($file->getClientOriginalName()); // add message: - $msg = (string)trans('validation.file_attached', ['name' => $name]); - $this->messages->add('attachments', $msg); - - // return it. return $attachment; } /** + * Verify if the mime of a file is valid. + * * @param UploadedFile $file * * @return bool @@ -271,19 +288,22 @@ class AttachmentHelper implements AttachmentHelperInterface $name = e($file->getClientOriginalName()); Log::debug(sprintf('Name is %s, and mime is %s', $name, $mime)); Log::debug('Valid mimes are', $this->allowedMimes); + $result = true; if (!\in_array($mime, $this->allowedMimes, true)) { $msg = (string)trans('validation.file_invalid_mime', ['name' => $name, 'mime' => $mime]); $this->errors->add('attachments', $msg); Log::error($msg); - return false; + $result = false; } - return true; + return $result; } /** + * Verify if the size of a file is valid. + * * @codeCoverageIgnore * * @param UploadedFile $file @@ -292,20 +312,23 @@ class AttachmentHelper implements AttachmentHelperInterface */ protected function validSize(UploadedFile $file): bool { - $size = $file->getSize(); - $name = e($file->getClientOriginalName()); + $size = $file->getSize(); + $name = e($file->getClientOriginalName()); + $result = true; if ($size > $this->maxUploadSize) { $msg = (string)trans('validation.file_too_large', ['name' => $name]); $this->errors->add('attachments', $msg); Log::error($msg); - return false; + $result = false; } - return true; + return $result; } /** + * Verify if the file was uploaded correctly. + * * @param UploadedFile $file * @param Model $model * @@ -314,16 +337,17 @@ class AttachmentHelper implements AttachmentHelperInterface protected function validateUpload(UploadedFile $file, Model $model): bool { Log::debug('Now in validateUpload()'); + $result = true; if (!$this->validMime($file)) { - return false; + $result = false; } - if (!$this->validSize($file)) { - return false; // @codeCoverageIgnore + if (true === $result && !$this->validSize($file)) { + $result = false; } - if ($this->hasFile($file, $model)) { - return false; + if (true === $result && $this->hasFile($file, $model)) { + $result = false; } - return true; + return $result; } } diff --git a/app/Helpers/Attachments/AttachmentHelperInterface.php b/app/Helpers/Attachments/AttachmentHelperInterface.php index 8f34041faa..7305202738 100644 --- a/app/Helpers/Attachments/AttachmentHelperInterface.php +++ b/app/Helpers/Attachments/AttachmentHelperInterface.php @@ -33,6 +33,8 @@ use Illuminate\Support\MessageBag; interface AttachmentHelperInterface { /** + * Get content of an attachment. + * * @param Attachment $attachment * * @return string @@ -40,6 +42,8 @@ interface AttachmentHelperInterface public function getAttachmentContent(Attachment $attachment): string; /** + * Get the location of an attachment. + * * @param Attachment $attachment * * @return string @@ -47,16 +51,22 @@ interface AttachmentHelperInterface public function getAttachmentLocation(Attachment $attachment): string; /** + * Get all attachments. + * * @return Collection */ public function getAttachments(): Collection; /** + * Get all errors. + * * @return MessageBag */ public function getErrors(): MessageBag; /** + * Get all messages/ + * * @return MessageBag */ public function getMessages(): MessageBag; @@ -72,6 +82,8 @@ interface AttachmentHelperInterface public function saveAttachmentFromApi(Attachment $attachment, string $content): bool; /** + * Save attachments that got uploaded. + * * @param Model $model * @param null|array $files * diff --git a/app/Helpers/Chart/MetaPieChart.php b/app/Helpers/Chart/MetaPieChart.php index fb60b3db80..c9fd1e2e9a 100644 --- a/app/Helpers/Chart/MetaPieChart.php +++ b/app/Helpers/Chart/MetaPieChart.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ + declare(strict_types=1); namespace FireflyIII\Helpers\Chart; @@ -37,32 +38,31 @@ use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\User; use Illuminate\Support\Collection; -use Steam; /** * Class MetaPieChart. */ class MetaPieChart implements MetaPieChartInterface { - /** @var Collection */ - protected $accounts; - /** @var Collection */ - protected $budgets; - /** @var Collection */ - protected $categories; - /** @var bool */ - protected $collectOtherObjects = false; - /** @var Carbon */ - protected $end; - /** @var array */ - protected $grouping + /** @var array The ways to group transactions, given the type of chart. */ + static protected $grouping = [ 'account' => ['opposing_account_id'], 'budget' => ['transaction_journal_budget_id', 'transaction_budget_id'], 'category' => ['transaction_journal_category_id', 'transaction_category_id'], 'tag' => [], ]; - /** @var array */ + /** @var Collection Involved accounts. */ + protected $accounts; + /** @var Collection The budgets. */ + protected $budgets; + /** @var Collection The categories. */ + protected $categories; + /** @var bool Collect other objects. */ + protected $collectOtherObjects = false; + /** @var Carbon The end date./ */ + protected $end; + /** @var array The repositories. */ protected $repositories = [ 'account' => AccountRepositoryInterface::class, @@ -70,13 +70,13 @@ class MetaPieChart implements MetaPieChartInterface 'category' => CategoryRepositoryInterface::class, 'tag' => TagRepositoryInterface::class, ]; - /** @var Carbon */ + /** @var Carbon The start date. */ protected $start; - /** @var Collection */ + /** @var Collection The involved tags/ */ protected $tags; - /** @var string */ + /** @var string The total amount. */ protected $total = '0'; - /** @var User */ + /** @var User The user. */ protected $user; /** @@ -91,17 +91,18 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Generate the chart. + * * @param string $direction * @param string $group * * @return array - * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function generate(string $direction, string $group): array { $transactions = $this->getTransactions($direction); - $grouped = $this->groupByFields($transactions, $this->grouping[$group]); + $grouped = $this->groupByFields($transactions, self::$grouping[$group]); $chartData = $this->organizeByType($group, $grouped); $key = (string)trans('firefly.everything_else'); @@ -134,6 +135,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Accounts setter. + * * @codeCoverageIgnore * * @param Collection $accounts @@ -148,6 +151,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Budgets setter. + * * @codeCoverageIgnore * * @param Collection $budgets @@ -162,6 +167,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Categories setter. + * * @codeCoverageIgnore * * @param Collection $categories @@ -176,6 +183,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Set if other objects should be collected. + * * @codeCoverageIgnore * * @param bool $collectOtherObjects @@ -190,6 +199,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Set the end date. + * * @codeCoverageIgnore * * @param Carbon $end @@ -204,6 +215,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Set the start date. + * * @codeCoverageIgnore * * @param Carbon $start @@ -218,6 +231,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Set the tags. + * * @codeCoverageIgnore * * @param Collection $tags @@ -232,6 +247,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Set the user. + * * @codeCoverageIgnore * * @param User $user @@ -246,6 +263,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Get all transactions. + * * @param string $direction * * @return Collection @@ -289,36 +308,44 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Group by a specific field. + * * @param Collection $set * @param array $fields * * @return array * * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * */ protected function groupByFields(Collection $set, array $fields): array { + $grouped = []; if (0 === \count($fields) && $this->tags->count() > 0) { // do a special group on tags: - return $this->groupByTag($set); // @codeCoverageIgnore + $grouped = $this->groupByTag($set); // @codeCoverageIgnore } - $grouped = []; - /** @var Transaction $transaction */ - foreach ($set as $transaction) { - $values = []; - foreach ($fields as $field) { - $values[] = (int)$transaction->$field; + if (0 !== \count($fields) || $this->tags->count() <= 0) { + $grouped = []; + /** @var Transaction $transaction */ + foreach ($set as $transaction) { + $values = []; + foreach ($fields as $field) { + $values[] = (int)$transaction->$field; + } + $value = max($values); + $grouped[$value] = $grouped[$value] ?? '0'; + $grouped[$value] = bcadd($transaction->transaction_amount, $grouped[$value]); } - $value = max($values); - $grouped[$value] = $grouped[$value] ?? '0'; - $grouped[$value] = bcadd($transaction->transaction_amount, $grouped[$value]); } return $grouped; } /** + * Organise by certain type. + * * @param string $type * @param array $array * @@ -335,7 +362,7 @@ class MetaPieChart implements MetaPieChartInterface $object = $repository->find((int)$objectId); $names[$objectId] = $object->name ?? $object->tag; } - $amount = Steam::positive($amount); + $amount = app('steam')->positive($amount); $this->total = bcadd($this->total, $amount); $chartData[$names[$objectId]] = $amount; } @@ -344,6 +371,8 @@ class MetaPieChart implements MetaPieChartInterface } /** + * Group by tag (slightly different). + * * @codeCoverageIgnore * * @param Collection $set diff --git a/app/Helpers/Chart/MetaPieChartInterface.php b/app/Helpers/Chart/MetaPieChartInterface.php index c57fe15ed6..d0246d89f0 100644 --- a/app/Helpers/Chart/MetaPieChartInterface.php +++ b/app/Helpers/Chart/MetaPieChartInterface.php @@ -32,6 +32,8 @@ use Illuminate\Support\Collection; interface MetaPieChartInterface { /** + * Generate a chart. + * * @param string $direction * @param string $group * @@ -40,6 +42,8 @@ interface MetaPieChartInterface public function generate(string $direction, string $group): array; /** + * Accounts setter. + * * @param Collection $accounts * * @return MetaPieChartInterface @@ -47,6 +51,8 @@ interface MetaPieChartInterface public function setAccounts(Collection $accounts): MetaPieChartInterface; /** + * Budgets setter. + * * @param Collection $budgets * * @return MetaPieChartInterface @@ -54,6 +60,8 @@ interface MetaPieChartInterface public function setBudgets(Collection $budgets): MetaPieChartInterface; /** + * Categories setter. + * * @param Collection $categories * * @return MetaPieChartInterface @@ -61,6 +69,8 @@ interface MetaPieChartInterface public function setCategories(Collection $categories): MetaPieChartInterface; /** + * Set if other objects should be collected. + * * @param bool $collectOtherObjects * * @return MetaPieChartInterface @@ -68,6 +78,8 @@ interface MetaPieChartInterface public function setCollectOtherObjects(bool $collectOtherObjects): MetaPieChartInterface; /** + * Set the end date. + * * @param Carbon $end * * @return MetaPieChartInterface @@ -75,6 +87,8 @@ interface MetaPieChartInterface public function setEnd(Carbon $end): MetaPieChartInterface; /** + * Set the start date. + * * @param Carbon $start * * @return MetaPieChartInterface @@ -82,6 +96,8 @@ interface MetaPieChartInterface public function setStart(Carbon $start): MetaPieChartInterface; /** + * Set the tags. + * * @param Collection $tags * * @return MetaPieChartInterface @@ -89,6 +105,8 @@ interface MetaPieChartInterface public function setTags(Collection $tags): MetaPieChartInterface; /** + * Set the user. + * * @param User $user * * @return MetaPieChartInterface diff --git a/app/Helpers/Collection/Balance.php b/app/Helpers/Collection/Balance.php index 14e2f67f2b..b10674cefd 100644 --- a/app/Helpers/Collection/Balance.php +++ b/app/Helpers/Collection/Balance.php @@ -29,14 +29,14 @@ use Illuminate\Support\Collection; */ class Balance { - /** @var BalanceHeader */ + /** @var BalanceHeader Header row. */ protected $balanceHeader; - /** @var Collection */ + /** @var Collection Collection of lines. */ protected $balanceLines; /** - * + * Balance constructor. */ public function __construct() { @@ -44,14 +44,18 @@ class Balance } /** + * Add a line. + * * @param BalanceLine $line */ - public function addBalanceLine(BalanceLine $line) + public function addBalanceLine(BalanceLine $line): void { $this->balanceLines->push($line); } /** + * Get the header. + * * @return BalanceHeader */ public function getBalanceHeader(): BalanceHeader @@ -60,14 +64,18 @@ class Balance } /** + * Set the header. + * * @param BalanceHeader $balanceHeader */ - public function setBalanceHeader(BalanceHeader $balanceHeader) + public function setBalanceHeader(BalanceHeader $balanceHeader): void { $this->balanceHeader = $balanceHeader; } /** + * Get all lines. + * * @return Collection */ public function getBalanceLines(): Collection @@ -76,9 +84,11 @@ class Balance } /** + * Set all lines. + * * @param Collection $balanceLines */ - public function setBalanceLines(Collection $balanceLines) + public function setBalanceLines(Collection $balanceLines): void { $this->balanceLines = $balanceLines; } diff --git a/app/Helpers/Collection/BalanceEntry.php b/app/Helpers/Collection/BalanceEntry.php index 31b7062698..8f2e4fb195 100644 --- a/app/Helpers/Collection/BalanceEntry.php +++ b/app/Helpers/Collection/BalanceEntry.php @@ -29,14 +29,16 @@ use FireflyIII\Models\Account as AccountModel; */ class BalanceEntry { - /** @var AccountModel */ + /** @var AccountModel The account. */ protected $account; - /** @var string */ + /** @var string The amount left. */ protected $left = '0'; - /** @var string */ + /** @var string The amount spent. */ protected $spent = '0'; /** + * Account getter. + * * @return AccountModel */ public function getAccount(): AccountModel @@ -45,14 +47,18 @@ class BalanceEntry } /** + * Account setter. + * * @param AccountModel $account */ - public function setAccount(AccountModel $account) + public function setAccount(AccountModel $account): void { $this->account = $account; } /** + * Get amount left. + * * @return string */ public function getLeft(): string @@ -61,14 +67,18 @@ class BalanceEntry } /** + * Set amount left. + * * @param string $left */ - public function setLeft(string $left) + public function setLeft(string $left): void { $this->left = $left; } /** + * Get amount spent. + * * @return string */ public function getSpent(): string @@ -77,9 +87,11 @@ class BalanceEntry } /** + * Set amount spent. + * * @param string $spent */ - public function setSpent(string $spent) + public function setSpent(string $spent): void { $this->spent = $spent; } diff --git a/app/Helpers/Collection/BalanceHeader.php b/app/Helpers/Collection/BalanceHeader.php index 3d5aa6476f..46c3091333 100644 --- a/app/Helpers/Collection/BalanceHeader.php +++ b/app/Helpers/Collection/BalanceHeader.php @@ -30,11 +30,11 @@ use Illuminate\Support\Collection; */ class BalanceHeader { - /** @var Collection */ + /** @var Collection The accounts. */ protected $accounts; /** - * + * BalanceHeader constructor. */ public function __construct() { @@ -42,14 +42,18 @@ class BalanceHeader } /** + * Add an account. + * * @param AccountModel $account */ - public function addAccount(AccountModel $account) + public function addAccount(AccountModel $account): void { $this->accounts->push($account); } /** + * Get them all. + * * @return Collection */ public function getAccounts(): Collection diff --git a/app/Helpers/Collection/BalanceLine.php b/app/Helpers/Collection/BalanceLine.php index 9d62a4aa21..a679ef66ff 100644 --- a/app/Helpers/Collection/BalanceLine.php +++ b/app/Helpers/Collection/BalanceLine.php @@ -62,7 +62,7 @@ class BalanceLine /** * @param BalanceEntry $balanceEntry */ - public function addBalanceEntry(BalanceEntry $balanceEntry) + public function addBalanceEntry(BalanceEntry $balanceEntry): void { $this->balanceEntries->push($balanceEntry); } @@ -78,7 +78,7 @@ class BalanceLine /** * @param Collection $balanceEntries */ - public function setBalanceEntries(Collection $balanceEntries) + public function setBalanceEntries(Collection $balanceEntries): void { $this->balanceEntries = $balanceEntries; } @@ -94,7 +94,7 @@ class BalanceLine /** * @param BudgetModel $budget */ - public function setBudget(BudgetModel $budget) + public function setBudget(BudgetModel $budget): void { $this->budget = $budget; } @@ -110,7 +110,7 @@ class BalanceLine /** * @param BudgetLimit $budgetLimit */ - public function setBudgetLimit(BudgetLimit $budgetLimit) + public function setBudgetLimit(BudgetLimit $budgetLimit): void { $this->budgetLimit = $budgetLimit; } @@ -118,7 +118,7 @@ class BalanceLine /** * @return Carbon */ - public function getEndDate() + public function getEndDate(): Carbon { return $this->budgetLimit->end_date ?? new Carbon; } @@ -134,7 +134,7 @@ class BalanceLine /** * @param int $role */ - public function setRole(int $role) + public function setRole(int $role): void { $this->role = $role; } @@ -142,29 +142,28 @@ class BalanceLine /** * @return Carbon */ - public function getStartDate() + public function getStartDate(): Carbon { return $this->budgetLimit->start_date ?? new Carbon; } /** - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * * @return string */ public function getTitle(): string { + $title = ''; if ($this->getBudget() instanceof BudgetModel && null !== $this->getBudget()->id) { - return $this->getBudget()->name; + $title = $this->getBudget()->name; } - if (self::ROLE_DEFAULTROLE === $this->getRole()) { - return (string)trans('firefly.no_budget'); + if ('' === $title && self::ROLE_DEFAULTROLE === $this->getRole()) { + $title = (string)trans('firefly.no_budget'); } - if (self::ROLE_TAGROLE === $this->getRole()) { - return (string)trans('firefly.coveredWithTags'); + if ('' === $title && self::ROLE_TAGROLE === $this->getRole()) { + $title = (string)trans('firefly.coveredWithTags'); } - return ''; + return $title; } /** diff --git a/app/Helpers/Collection/Bill.php b/app/Helpers/Collection/Bill.php index 1cc2a7b50e..9ce761345d 100644 --- a/app/Helpers/Collection/Bill.php +++ b/app/Helpers/Collection/Bill.php @@ -32,17 +32,15 @@ use Log; */ class Bill { - /** - * @var Collection - */ + /** @var Collection The bills. */ private $bills; - /** @var Carbon */ + /** @var Carbon End date of the collection. */ private $endDate; - /** @var Carbon */ + /** @var Carbon Start date of the collection. */ private $startDate; /** - * + * Bill constructor. */ public function __construct() { @@ -50,17 +48,19 @@ class Bill } /** + * Add a bill line. + * * @param BillLine $bill */ - public function addBill(BillLine $bill) + public function addBill(BillLine $bill): void { $this->bills->push($bill); } /** - * + * Filter the bills (yes how very descriptive). */ - public function filterBills() + public function filterBills(): void { Log::debug('Now in filterBills()'); /** @var BillRepositoryInterface $repository */ @@ -95,6 +95,8 @@ class Bill } /** + * Bills getter. + * * @return Collection */ public function getBills(): Collection @@ -112,17 +114,21 @@ class Bill } /** + * End date setter. + * * @param Carbon $endDate */ - public function setEndDate(Carbon $endDate) + public function setEndDate(Carbon $endDate): void { $this->endDate = $endDate; } /** + * Start date setter. + * * @param Carbon $startDate */ - public function setStartDate(Carbon $startDate) + public function setStartDate(Carbon $startDate): void { $this->startDate = $startDate; } diff --git a/app/Helpers/Collection/BillLine.php b/app/Helpers/Collection/BillLine.php index ed5bcbdaf1..4be29cb07a 100644 --- a/app/Helpers/Collection/BillLine.php +++ b/app/Helpers/Collection/BillLine.php @@ -30,23 +30,23 @@ use FireflyIII\Models\Bill as BillModel; */ class BillLine { - /** @var string */ + /** @var string The amount */ protected $amount; - /** @var BillModel */ + /** @var BillModel The bill. */ protected $bill; - /** @var bool */ + /** @var bool Is it hit this period */ protected $hit; - /** @var string */ + /** @var string What was the max amount. */ protected $max; - /** @var string */ + /** @var string What was the min amount. */ protected $min; - /** @var Carbon */ + /** @var Carbon Latest date that payment is expected. */ private $endOfPayDate; - /** @var Carbon */ + /** @var Carbon Date of last hit */ private $lastHitDate; - /** @var Carbon */ + /** @var Carbon Date of last payment */ private $payDate; - /** @var int */ + /** @var int Journal */ private $transactionJournalId; /** @@ -58,6 +58,8 @@ class BillLine } /** + * Amount getter. + * * @return string */ public function getAmount(): string @@ -66,14 +68,18 @@ class BillLine } /** + * Amount setter. + * * @param string $amount */ - public function setAmount(string $amount) + public function setAmount(string $amount): void { $this->amount = $amount; } /** + * Bill getter. + * * @return BillModel */ public function getBill(): BillModel @@ -82,14 +88,18 @@ class BillLine } /** + * Bill setter. + * * @param BillModel $bill */ - public function setBill(BillModel $bill) + public function setBill(BillModel $bill): void { $this->bill = $bill; } /** + * End of pay date getter. + * * @return Carbon */ public function getEndOfPayDate(): Carbon @@ -98,6 +108,8 @@ class BillLine } /** + * End of pay date setter. + * * @param Carbon $endOfPayDate */ public function setEndOfPayDate(Carbon $endOfPayDate): void @@ -106,6 +118,8 @@ class BillLine } /** + * Last hit date getter. + * * @return Carbon */ public function getLastHitDate(): Carbon @@ -114,14 +128,18 @@ class BillLine } /** + * Last hit date setter. + * * @param Carbon $lastHitDate */ - public function setLastHitDate(Carbon $lastHitDate) + public function setLastHitDate(Carbon $lastHitDate): void { $this->lastHitDate = $lastHitDate; } /** + * Max getter. + * * @return string */ public function getMax(): string @@ -130,14 +148,18 @@ class BillLine } /** + * Max setter. + * * @param string $max */ - public function setMax(string $max) + public function setMax(string $max): void { $this->max = $max; } /** + * Min getter. + * * @return string */ public function getMin(): string @@ -146,14 +168,18 @@ class BillLine } /** + * Min setter. + * * @param string $min */ - public function setMin(string $min) + public function setMin(string $min): void { $this->min = $min; } /** + * Pay date getter. + * * @return Carbon */ public function getPayDate(): Carbon @@ -162,6 +188,8 @@ class BillLine } /** + * Pay date setter. + * * @param Carbon $payDate */ public function setPayDate(Carbon $payDate): void @@ -170,6 +198,8 @@ class BillLine } /** + * Journal ID getter. + * * @return int */ public function getTransactionJournalId(): int @@ -178,14 +208,18 @@ class BillLine } /** + * Journal ID setter. + * * @param int $transactionJournalId */ - public function setTransactionJournalId(int $transactionJournalId) + public function setTransactionJournalId(int $transactionJournalId): void { $this->transactionJournalId = $transactionJournalId; } /** + * Is active. + * * @return bool */ public function isActive(): bool @@ -194,6 +228,8 @@ class BillLine } /** + * Is hit. + * * @return bool */ public function isHit(): bool @@ -202,9 +238,11 @@ class BillLine } /** + * Set is hit. + * * @param bool $hit */ - public function setHit(bool $hit) + public function setHit(bool $hit): void { $this->hit = $hit; } diff --git a/app/Helpers/Collection/Category.php b/app/Helpers/Collection/Category.php index 12ed91b8e8..9868bdb945 100644 --- a/app/Helpers/Collection/Category.php +++ b/app/Helpers/Collection/Category.php @@ -30,13 +30,13 @@ use Illuminate\Support\Collection; */ class Category { - /** @var Collection */ + /** @var Collection The categories */ protected $categories; - /** @var string */ + /** @var string Total amount */ protected $total = '0'; /** - * + * Category constructor. */ public function __construct() { @@ -44,26 +44,32 @@ class Category } /** + * Add a category. + * * @param CategoryModel $category */ - public function addCategory(CategoryModel $category) + public function addCategory(CategoryModel $category): void { // spent is minus zero for an expense report: if ($category->spent < 0) { $this->categories->push($category); - $this->addTotal($category->spent); + $this->addTotal((string)$category->spent); } } /** + * Add to the total amount. + * * @param string $add */ - public function addTotal(string $add) + public function addTotal(string $add): void { $this->total = bcadd($this->total, $add); } /** + * Get all categories. + * * @return Collection */ public function getCategories(): Collection @@ -78,6 +84,8 @@ class Category } /** + * Get the total. + * * @return string */ public function getTotal(): string diff --git a/app/Helpers/Collector/JournalCollector.php b/app/Helpers/Collector/JournalCollector.php index 33d24fcaf7..2d07df89c2 100644 --- a/app/Helpers/Collector/JournalCollector.php +++ b/app/Helpers/Collector/JournalCollector.php @@ -18,6 +18,8 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ +/** @noinspection PropertyCanBeStaticInspection */ declare(strict_types=1); namespace FireflyIII\Helpers\Collector; @@ -47,17 +49,16 @@ use Illuminate\Database\Query\JoinClause; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Log; -use Steam; /** + * TODO rename references to journals to transactions * Maybe this is a good idea after all... * * Class JournalCollector - * - * + * @SuppressWarnings(PHPMD.TooManyPublicMethods) * @SuppressWarnings(PHPMD.ExcessiveClassComplexity) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @SuppressWarnings(PHPMD.TooManyPublicMethods) + * */ class JournalCollector implements JournalCollectorInterface { @@ -66,6 +67,7 @@ class JournalCollector implements JournalCollectorInterface private $accountIds = []; /** @var int */ private $count = 0; + /** @var array */ private $fields = [ @@ -139,7 +141,7 @@ class JournalCollector implements JournalCollectorInterface public function addFilter(string $filter): JournalCollectorInterface { $interfaces = class_implements($filter); - if (\in_array(FilterInterface::class, $interfaces) && !\in_array($filter, $this->filters)) { + if (\in_array(FilterInterface::class, $interfaces, true) && !\in_array($filter, $this->filters, true)) { Log::debug(sprintf('Enabled filter %s', $filter)); $this->filters[] = $filter; } @@ -245,8 +247,11 @@ class JournalCollector implements JournalCollectorInterface return $this->count; } + /** @noinspection MultipleReturnStatementsInspection */ /** * @return Collection + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ public function getJournals(): Collection { @@ -266,9 +271,6 @@ class JournalCollector implements JournalCollectorInterface return $cache->get(); // @codeCoverageIgnore } - if (true === $this->ignoreCache) { - Log::debug('Ignore cache in journal collector.'); - } /** @var Collection $set */ $set = $this->query->get(array_values($this->fields)); @@ -279,10 +281,10 @@ class JournalCollector implements JournalCollectorInterface $set->each( function (Transaction $transaction) { $transaction->date = new Carbon($transaction->date); - $transaction->description = Steam::decrypt((int)$transaction->encrypted, $transaction->description); + $transaction->description = app('steam')->decrypt((int)$transaction->encrypted, $transaction->description); if (null !== $transaction->bill_name) { - $transaction->bill_name = Steam::decrypt((int)$transaction->bill_name_encrypted, $transaction->bill_name); + $transaction->bill_name = app('steam')->decrypt((int)$transaction->bill_name_encrypted, $transaction->bill_name); } $transaction->account_name = app('steam')->tryDecrypt($transaction->account_name); $transaction->opposing_account_name = app('steam')->tryDecrypt($transaction->opposing_account_name); @@ -468,18 +470,17 @@ class JournalCollector implements JournalCollectorInterface public function setBudgets(Collection $budgets): JournalCollectorInterface { $budgetIds = $budgets->pluck('id')->toArray(); - if (0 === \count($budgetIds)) { - return $this; - } - $this->joinBudgetTables(); - Log::debug('Journal collector will filter for budgets', $budgetIds); + if (0 !== \count($budgetIds)) { + $this->joinBudgetTables(); + Log::debug('Journal collector will filter for budgets', $budgetIds); - $this->query->where( - function (EloquentBuilder $q) use ($budgetIds) { - $q->whereIn('budget_transaction.budget_id', $budgetIds); - $q->orWhereIn('budget_transaction_journal.budget_id', $budgetIds); - } - ); + $this->query->where( + function (EloquentBuilder $q) use ($budgetIds) { + $q->whereIn('budget_transaction.budget_id', $budgetIds); + $q->orWhereIn('budget_transaction_journal.budget_id', $budgetIds); + } + ); + } return $this; } @@ -492,17 +493,16 @@ class JournalCollector implements JournalCollectorInterface public function setCategories(Collection $categories): JournalCollectorInterface { $categoryIds = $categories->pluck('id')->toArray(); - if (0 === \count($categoryIds)) { - return $this; - } - $this->joinCategoryTables(); + if (0 !== \count($categoryIds)) { + $this->joinCategoryTables(); - $this->query->where( - function (EloquentBuilder $q) use ($categoryIds) { - $q->whereIn('category_transaction.category_id', $categoryIds); - $q->orWhereIn('category_transaction_journal.category_id', $categoryIds); - } - ); + $this->query->where( + function (EloquentBuilder $q) use ($categoryIds) { + $q->whereIn('category_transaction.category_id', $categoryIds); + $q->orWhereIn('category_transaction_journal.category_id', $categoryIds); + } + ); + } return $this; } @@ -606,10 +606,7 @@ class JournalCollector implements JournalCollectorInterface $this->offset = $offset; $this->query->skip($offset); Log::debug(sprintf('Changed offset to %d', $offset)); - - return $this; } - Log::debug('The limit is zero, cannot set the page.'); return $this; } @@ -688,7 +685,7 @@ class JournalCollector implements JournalCollectorInterface /** * */ - public function startQuery() + public function startQuery(): void { Log::debug('journalCollector::startQuery'); /** @var EloquentBuilder $query */ @@ -798,6 +795,7 @@ class JournalCollector implements JournalCollectorInterface foreach ($this->filters as $enabled) { if (isset($filters[$enabled])) { Log::debug(sprintf('Before filter %s: %d', $enabled, $set->count())); + /** @var Collection $set */ $set = $filters[$enabled]->filter($set); Log::debug(sprintf('After filter %s: %d', $enabled, $set->count())); } diff --git a/app/Helpers/Collector/JournalCollectorInterface.php b/app/Helpers/Collector/JournalCollectorInterface.php index b9c29ff4bf..bb42ea69de 100644 --- a/app/Helpers/Collector/JournalCollectorInterface.php +++ b/app/Helpers/Collector/JournalCollectorInterface.php @@ -38,6 +38,8 @@ interface JournalCollectorInterface { /** + * Add a specific filter. + * * @param string $filter * * @return JournalCollectorInterface @@ -45,6 +47,8 @@ interface JournalCollectorInterface public function addFilter(string $filter): JournalCollectorInterface; /** + * Get transactions with a specific amount. + * * @param string $amount * * @return JournalCollectorInterface @@ -52,6 +56,8 @@ interface JournalCollectorInterface public function amountIs(string $amount): JournalCollectorInterface; /** + * Get transactions where the amount is less than. + * * @param string $amount * * @return JournalCollectorInterface @@ -59,6 +65,8 @@ interface JournalCollectorInterface public function amountLess(string $amount): JournalCollectorInterface; /** + * Get transactions where the amount is more than. + * * @param string $amount * * @return JournalCollectorInterface @@ -66,31 +74,44 @@ interface JournalCollectorInterface public function amountMore(string $amount): JournalCollectorInterface; /** + * Count the result. + * * @return int */ public function count(): int; /** + * Get all journals. + * TODO rename me. + * * @return Collection */ public function getJournals(): Collection; /** + * Get a paginated result. + * * @return LengthAwarePaginator */ public function getPaginatedJournals(): LengthAwarePaginator; /** + * Get the query. + * * @return EloquentBuilder */ public function getQuery(): EloquentBuilder; /** + * Set to ignore the cache. + * * @return JournalCollectorInterface */ public function ignoreCache(): JournalCollectorInterface; /** + * Remove a filter. + * * @param string $filter * * @return JournalCollectorInterface @@ -98,6 +119,8 @@ interface JournalCollectorInterface public function removeFilter(string $filter): JournalCollectorInterface; /** + * Set the accounts to collect from. + * * @param Collection $accounts * * @return JournalCollectorInterface @@ -105,6 +128,8 @@ interface JournalCollectorInterface public function setAccounts(Collection $accounts): JournalCollectorInterface; /** + * Collect journals after a specific date. + * * @param Carbon $after * * @return JournalCollectorInterface @@ -112,11 +137,15 @@ interface JournalCollectorInterface public function setAfter(Carbon $after): JournalCollectorInterface; /** + * Include all asset accounts. + * * @return JournalCollectorInterface */ public function setAllAssetAccounts(): JournalCollectorInterface; /** + * Collect journals before a specific date. + * * @param Carbon $before * * @return JournalCollectorInterface @@ -124,6 +153,8 @@ interface JournalCollectorInterface public function setBefore(Carbon $before): JournalCollectorInterface; /** + * Set the bills to filter on. + * * @param Collection $bills * * @return JournalCollectorInterface @@ -131,6 +162,8 @@ interface JournalCollectorInterface public function setBills(Collection $bills): JournalCollectorInterface; /** + * Set the budget to filter on. + * * @param Budget $budget * * @return JournalCollectorInterface @@ -138,6 +171,8 @@ interface JournalCollectorInterface public function setBudget(Budget $budget): JournalCollectorInterface; /** + * Set the budgets to filter on. + * * @param Collection $budgets * * @return JournalCollectorInterface @@ -145,6 +180,8 @@ interface JournalCollectorInterface public function setBudgets(Collection $budgets): JournalCollectorInterface; /** + * Set the categories to filter on. + * * @param Collection $categories * * @return JournalCollectorInterface @@ -152,6 +189,8 @@ interface JournalCollectorInterface public function setCategories(Collection $categories): JournalCollectorInterface; /** + * Set the category to filter on. + * * @param Category $category * * @return JournalCollectorInterface @@ -159,6 +198,8 @@ interface JournalCollectorInterface public function setCategory(Category $category): JournalCollectorInterface; /** + * Set the journals to filter on. + * * @param Collection $journals * * @return JournalCollectorInterface @@ -166,6 +207,8 @@ interface JournalCollectorInterface public function setJournals(Collection $journals): JournalCollectorInterface; /** + * Set the page limit. + * * @param int $limit * * @return JournalCollectorInterface @@ -173,6 +216,8 @@ interface JournalCollectorInterface public function setLimit(int $limit): JournalCollectorInterface; /** + * Set the offset. + * * @param int $offset * * @return JournalCollectorInterface @@ -180,6 +225,8 @@ interface JournalCollectorInterface public function setOffset(int $offset): JournalCollectorInterface; /** + * Set the opposing accounts to collect from. + * * @param Collection $accounts * * @return JournalCollectorInterface @@ -187,6 +234,8 @@ interface JournalCollectorInterface public function setOpposingAccounts(Collection $accounts): JournalCollectorInterface; /** + * Set the page to get. + * * @param int $page * * @return JournalCollectorInterface @@ -194,6 +243,8 @@ interface JournalCollectorInterface public function setPage(int $page): JournalCollectorInterface; /** + * Set the date range. + * * @param Carbon $start * @param Carbon $end * @@ -202,6 +253,8 @@ interface JournalCollectorInterface public function setRange(Carbon $start, Carbon $end): JournalCollectorInterface; /** + * Set the tag to collect from. + * * @param Tag $tag * * @return JournalCollectorInterface @@ -209,6 +262,8 @@ interface JournalCollectorInterface public function setTag(Tag $tag): JournalCollectorInterface; /** + * Set the tags to collect from. + * * @param Collection $tags * * @return JournalCollectorInterface @@ -216,6 +271,8 @@ interface JournalCollectorInterface public function setTags(Collection $tags): JournalCollectorInterface; /** + * Set the types to collect. + * * @param array $types * * @return JournalCollectorInterface @@ -223,6 +280,8 @@ interface JournalCollectorInterface public function setTypes(array $types): JournalCollectorInterface; /** + * Set the user. + * * @param User $user * * @return mixed @@ -230,31 +289,41 @@ interface JournalCollectorInterface public function setUser(User $user); /** - * + * Start the query. */ public function startQuery(); /** + * Include budget information. + * * @return JournalCollectorInterface */ public function withBudgetInformation(): JournalCollectorInterface; /** + * Include category information. + * * @return JournalCollectorInterface */ public function withCategoryInformation(): JournalCollectorInterface; /** + * Include opposing account information. + * * @return JournalCollectorInterface */ public function withOpposingAccount(): JournalCollectorInterface; /** + * Include tranactions without a budget. + * * @return JournalCollectorInterface */ public function withoutBudget(): JournalCollectorInterface; /** + * Include tranactions without a category. + * * @return JournalCollectorInterface */ public function withoutCategory(): JournalCollectorInterface; diff --git a/app/Helpers/Filter/AmountFilter.php b/app/Helpers/Filter/AmountFilter.php index c6530a129a..e977e4d0a0 100644 --- a/app/Helpers/Filter/AmountFilter.php +++ b/app/Helpers/Filter/AmountFilter.php @@ -34,7 +34,7 @@ use Log; */ class AmountFilter implements FilterInterface { - /** @var int */ + /** @var int Either -1 or +1 for the filter. */ private $modifier; /** @@ -48,6 +48,8 @@ class AmountFilter implements FilterInterface } /** + * Filter on amount. + * * @param Collection $set * * @return Collection diff --git a/app/Helpers/Filter/CountAttachmentsFilter.php b/app/Helpers/Filter/CountAttachmentsFilter.php index 94a58c4bba..bcb61fa3c2 100644 --- a/app/Helpers/Filter/CountAttachmentsFilter.php +++ b/app/Helpers/Filter/CountAttachmentsFilter.php @@ -36,6 +36,8 @@ class CountAttachmentsFilter implements FilterInterface { /** + * Adds the number of transactions to each given transaction. + * * @param Collection $set * * @return Collection diff --git a/app/Helpers/Filter/EmptyFilter.php b/app/Helpers/Filter/EmptyFilter.php index 60c03d9769..2235fe2bfa 100644 --- a/app/Helpers/Filter/EmptyFilter.php +++ b/app/Helpers/Filter/EmptyFilter.php @@ -30,6 +30,8 @@ use Illuminate\Support\Collection; class EmptyFilter implements FilterInterface { /** + * Simply returns the set. + * * @param Collection $set * * @return Collection diff --git a/app/Helpers/Filter/FilterInterface.php b/app/Helpers/Filter/FilterInterface.php index e1ed2ed163..4b08036b51 100644 --- a/app/Helpers/Filter/FilterInterface.php +++ b/app/Helpers/Filter/FilterInterface.php @@ -30,6 +30,8 @@ use Illuminate\Support\Collection; interface FilterInterface { /** + * Apply the filter. + * * @param Collection $set * * @return Collection diff --git a/app/Helpers/Filter/InternalTransferFilter.php b/app/Helpers/Filter/InternalTransferFilter.php index c36e5f1353..1442db3d20 100644 --- a/app/Helpers/Filter/InternalTransferFilter.php +++ b/app/Helpers/Filter/InternalTransferFilter.php @@ -35,7 +35,7 @@ use Log; */ class InternalTransferFilter implements FilterInterface { - /** @var array */ + /** @var array The accounts */ private $accounts; /** @@ -49,6 +49,8 @@ class InternalTransferFilter implements FilterInterface } /** + * See class description. + * * @param Collection $set * * @return Collection @@ -61,7 +63,7 @@ class InternalTransferFilter implements FilterInterface return $transaction; } // both id's in $parameters? - if (\in_array($transaction->account_id, $this->accounts) && \in_array($transaction->opposing_account_id, $this->accounts)) { + if (\in_array($transaction->account_id, $this->accounts, true) && \in_array($transaction->opposing_account_id, $this->accounts, true)) { Log::debug( sprintf( 'Transaction #%d has #%d and #%d in set, so removed', diff --git a/app/Helpers/Filter/NegativeAmountFilter.php b/app/Helpers/Filter/NegativeAmountFilter.php index 2eb266a07c..b6b0f10cf6 100644 --- a/app/Helpers/Filter/NegativeAmountFilter.php +++ b/app/Helpers/Filter/NegativeAmountFilter.php @@ -34,6 +34,8 @@ use Log; class NegativeAmountFilter implements FilterInterface { /** + * See class description. + * * @param Collection $set * * @return Collection diff --git a/app/Helpers/Filter/OpposingAccountFilter.php b/app/Helpers/Filter/OpposingAccountFilter.php index 7868f67556..5df2170ce6 100644 --- a/app/Helpers/Filter/OpposingAccountFilter.php +++ b/app/Helpers/Filter/OpposingAccountFilter.php @@ -34,7 +34,7 @@ use Log; */ class OpposingAccountFilter implements FilterInterface { - /** @var array */ + /** @var array The asset accounts. */ private $accounts; /** @@ -48,6 +48,8 @@ class OpposingAccountFilter implements FilterInterface } /** + * Only return specific transactions. See class description. + * * @param Collection $set * * @return Collection @@ -58,7 +60,7 @@ class OpposingAccountFilter implements FilterInterface function (Transaction $transaction) { $opposing = $transaction->opposing_account_id; // remove internal transfer - if (\in_array($opposing, $this->accounts)) { + if (\in_array($opposing, $this->accounts, true)) { Log::debug(sprintf('Filtered #%d because its opposite is in accounts.', $transaction->id), $this->accounts); return null; diff --git a/app/Helpers/Filter/PositiveAmountFilter.php b/app/Helpers/Filter/PositiveAmountFilter.php index 67d2f289d0..155c6c3f33 100644 --- a/app/Helpers/Filter/PositiveAmountFilter.php +++ b/app/Helpers/Filter/PositiveAmountFilter.php @@ -37,6 +37,8 @@ use Log; class PositiveAmountFilter implements FilterInterface { /** + * See class description. + * * @param Collection $set * * @return Collection diff --git a/app/Helpers/Filter/SplitIndicatorFilter.php b/app/Helpers/Filter/SplitIndicatorFilter.php index c85880e098..afc42c30c5 100644 --- a/app/Helpers/Filter/SplitIndicatorFilter.php +++ b/app/Helpers/Filter/SplitIndicatorFilter.php @@ -35,6 +35,8 @@ class SplitIndicatorFilter implements FilterInterface { /** + * Adds a property if the journal is a split one. + * * @param Collection $set * * @return Collection diff --git a/app/Helpers/Filter/TransactionViewFilter.php b/app/Helpers/Filter/TransactionViewFilter.php index ea83a62e75..1c8dc2938a 100644 --- a/app/Helpers/Filter/TransactionViewFilter.php +++ b/app/Helpers/Filter/TransactionViewFilter.php @@ -39,7 +39,10 @@ use Log; class TransactionViewFilter implements FilterInterface { /** + * See class description. + * * @param Collection $set + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * * @return Collection */ diff --git a/app/Helpers/Filter/TransferFilter.php b/app/Helpers/Filter/TransferFilter.php index 5a9cbb86df..40f2037a3b 100644 --- a/app/Helpers/Filter/TransferFilter.php +++ b/app/Helpers/Filter/TransferFilter.php @@ -25,7 +25,6 @@ namespace FireflyIII\Helpers\Filter; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use Illuminate\Support\Collection; -use Steam; /** * Class TransferFilter. @@ -35,6 +34,8 @@ use Steam; class TransferFilter implements FilterInterface { /** + * See class transaction. + * * @param Collection $set * * @return Collection @@ -51,7 +52,7 @@ class TransferFilter implements FilterInterface } // make property string: $journalId = $transaction->transaction_journal_id; - $amount = Steam::positive($transaction->transaction_amount); + $amount = app('steam')->positive($transaction->transaction_amount); $accountIds = [(int)$transaction->account_id, (int)$transaction->opposing_account_id]; $transactionIds = [$transaction->id, (int)$transaction->opposing_id]; sort($accountIds); diff --git a/app/Helpers/FiscalHelper.php b/app/Helpers/FiscalHelper.php index 10130eb16f..b34de8da9f 100644 --- a/app/Helpers/FiscalHelper.php +++ b/app/Helpers/FiscalHelper.php @@ -54,10 +54,10 @@ class FiscalHelper implements FiscalHelperInterface // add 1 year and sub 1 day $endDate->addYear(); $endDate->subDay(); - - return $endDate; } - $endDate->endOfYear(); + if (false === $this->useCustomFiscalYear) { + $endDate->endOfYear(); + } return $endDate; } @@ -80,10 +80,10 @@ class FiscalHelper implements FiscalHelperInterface if ($startDate > $date) { $startDate->subYear(); } - - return $startDate; } - $startDate->startOfYear(); + if (false === $this->useCustomFiscalYear) { + $startDate->startOfYear(); + } return $startDate; } diff --git a/app/Helpers/Help/Help.php b/app/Helpers/Help/Help.php index a9fcd1869a..818517d6f3 100644 --- a/app/Helpers/Help/Help.php +++ b/app/Helpers/Help/Help.php @@ -35,14 +35,14 @@ use Route; */ class Help implements HelpInterface { - /** - * - */ + /** @var string The cache key */ public const CACHEKEY = 'help_%s_%s'; - /** @var string */ + /** @var string The user agent. */ protected $userAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36'; /** + * Get from cache. + * * @param string $route * @param string $language * @@ -56,31 +56,30 @@ class Help implements HelpInterface } /** + * Get text from GitHub. + * * @param string $route * @param string $language * * @return string */ - public function getFromGithub(string $route, string $language): string + public function getFromGitHub(string $route, string $language): string { $uri = sprintf('https://raw.githubusercontent.com/firefly-iii/help/master/%s/%s.md', $language, $route); Log::debug(sprintf('Trying to get %s...', $uri)); - $opt = ['headers' => ['User-Agent' => $this->userAgent]]; - $content = ''; + $opt = ['headers' => ['User-Agent' => $this->userAgent]]; + $content = ''; + $statusCode = 500; + $client = new Client; try { - $client = new Client; - $res = $client->request('GET', $uri, $opt); + $res = $client->request('GET', $uri, $opt); + $statusCode = $res->getStatusCode(); + $content = trim($res->getBody()->getContents()); } catch (GuzzleException|Exception $e) { Log::error($e); - - return ''; } - Log::debug(sprintf('Status code is %d', $res->getStatusCode())); - - if (200 === $res->getStatusCode()) { - $content = trim($res->getBody()->getContents()); - } + Log::debug(sprintf('Status code is %d', $statusCode)); if (\strlen($content) > 0) { Log::debug('Content is longer than zero. Expect something.'); @@ -92,6 +91,8 @@ class Help implements HelpInterface } /** + * Do we have the route? + * * @param string $route * * @return bool @@ -102,6 +103,8 @@ class Help implements HelpInterface } /** + * Is in cache? + * * @param string $route * @param string $language * @@ -122,11 +125,13 @@ class Help implements HelpInterface } /** + * Put help text in cache. + * * @param string $route * @param string $language * @param string $content */ - public function putInCache(string $route, string $language, string $content) + public function putInCache(string $route, string $language, string $content): void { $key = sprintf(self::CACHEKEY, $route, $language); if (\strlen($content) > 0) { diff --git a/app/Helpers/Help/HelpInterface.php b/app/Helpers/Help/HelpInterface.php index a74284a078..7962423d42 100644 --- a/app/Helpers/Help/HelpInterface.php +++ b/app/Helpers/Help/HelpInterface.php @@ -28,6 +28,8 @@ namespace FireflyIII\Helpers\Help; interface HelpInterface { /** + * Get the help text from cache. + * * @param string $route * @param string $language * @@ -36,14 +38,18 @@ interface HelpInterface public function getFromCache(string $route, string $language): string; /** + * Get the help text from GitHub. + * * @param string $route * @param string $language * * @return string */ - public function getFromGithub(string $route, string $language): string; + public function getFromGitHub(string $route, string $language): string; /** + * Is the route a known route? + * * @param string $route * * @return bool @@ -51,6 +57,8 @@ interface HelpInterface public function hasRoute(string $route): bool; /** + * Is the help text in cache? + * * @param string $route * @param string $language * @@ -59,6 +67,8 @@ interface HelpInterface public function inCache(string $route, string $language): bool; /** + * Put the result in cache. + * * @param string $route * @param string $language * @param string $content diff --git a/app/Helpers/Report/BalanceReportHelper.php b/app/Helpers/Report/BalanceReportHelper.php index f44dfc15a4..1daec53c1c 100644 --- a/app/Helpers/Report/BalanceReportHelper.php +++ b/app/Helpers/Report/BalanceReportHelper.php @@ -34,12 +34,10 @@ use Log; /** * Class BalanceReportHelper. - * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) // I can't really help it. */ class BalanceReportHelper implements BalanceReportHelperInterface { - /** @var BudgetRepositoryInterface */ + /** @var BudgetRepositoryInterface Budget repository */ protected $budgetRepository; /** @@ -54,6 +52,8 @@ class BalanceReportHelper implements BalanceReportHelperInterface } /** + * Generate a balance report. + * * @param Collection $accounts * @param Carbon $start * @param Carbon $end @@ -93,6 +93,8 @@ class BalanceReportHelper implements BalanceReportHelperInterface } /** + * Create one balance line. + * * @param BudgetLimit $budgetLimit * @param Collection $accounts * @@ -122,6 +124,8 @@ class BalanceReportHelper implements BalanceReportHelperInterface } /** + * Create a line for transactions without a budget. + * * @param Collection $accounts * @param Carbon $start * @param Carbon $end @@ -145,8 +149,10 @@ class BalanceReportHelper implements BalanceReportHelperInterface } /** + * Remove unused budgets from the report. + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @param Balance $balance - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5. * * @return Balance */ @@ -157,6 +163,7 @@ class BalanceReportHelper implements BalanceReportHelperInterface foreach ($set as $entry) { if (null !== $entry->getBudget()->id) { $sum = '0'; + /** @var BalanceEntry $balanceEntry */ foreach ($entry->getBalanceEntries() as $balanceEntry) { $sum = bcadd($sum, $balanceEntry->getSpent()); } diff --git a/app/Helpers/Report/BalanceReportHelperInterface.php b/app/Helpers/Report/BalanceReportHelperInterface.php index 820def7669..2a18d6abe9 100644 --- a/app/Helpers/Report/BalanceReportHelperInterface.php +++ b/app/Helpers/Report/BalanceReportHelperInterface.php @@ -32,6 +32,8 @@ use Illuminate\Support\Collection; interface BalanceReportHelperInterface { /** + * Generates the report (duh). + * * @param Collection $accounts * @param Carbon $start * @param Carbon $end diff --git a/app/Helpers/Report/BudgetReportHelper.php b/app/Helpers/Report/BudgetReportHelper.php index 7e8382d84f..5d33e5ca71 100644 --- a/app/Helpers/Report/BudgetReportHelper.php +++ b/app/Helpers/Report/BudgetReportHelper.php @@ -33,7 +33,7 @@ use Illuminate\Support\Collection; */ class BudgetReportHelper implements BudgetReportHelperInterface { - /** @var BudgetRepositoryInterface */ + /** @var BudgetRepositoryInterface The budget repository interface. */ private $repository; /** @@ -47,9 +47,10 @@ class BudgetReportHelper implements BudgetReportHelperInterface } /** - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5. - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) // all the arrays make it long. + * Get the full budget report. * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @param Carbon $start * @param Carbon $end * @param Collection $accounts @@ -113,6 +114,8 @@ class BudgetReportHelper implements BudgetReportHelperInterface } /** + * Get all budgets and the expenses in these budgets. + * * @param Carbon $start * @param Carbon $end * @param Collection $accounts @@ -143,6 +146,8 @@ class BudgetReportHelper implements BudgetReportHelperInterface } /** + * Calculate the expenses for a budget. + * * @param Budget $budget * @param BudgetLimit $budgetLimit * @param Collection $accounts diff --git a/app/Helpers/Report/BudgetReportHelperInterface.php b/app/Helpers/Report/BudgetReportHelperInterface.php index 4b60e5e18f..b470265709 100644 --- a/app/Helpers/Report/BudgetReportHelperInterface.php +++ b/app/Helpers/Report/BudgetReportHelperInterface.php @@ -31,6 +31,8 @@ use Illuminate\Support\Collection; interface BudgetReportHelperInterface { /** + * Generates the budget report. + * * @param Carbon $start * @param Carbon $end * @param Collection $accounts @@ -40,6 +42,8 @@ interface BudgetReportHelperInterface public function getBudgetReport(Carbon $start, Carbon $end, Collection $accounts): array; /** + * Get budgets and the expenses in each budget. + * * @param Carbon $start * @param Carbon $end * @param Collection $accounts diff --git a/app/Helpers/Report/PopupReport.php b/app/Helpers/Report/PopupReport.php index 24c1bd2d9e..c0dac93458 100644 --- a/app/Helpers/Report/PopupReport.php +++ b/app/Helpers/Report/PopupReport.php @@ -37,6 +37,8 @@ use Illuminate\Support\Collection; class PopupReport implements PopupReportInterface { /** + * Collect the tranactions for one account and one budget. + * * @param Budget $budget * @param Account $account * @param array $attributes @@ -53,6 +55,8 @@ class PopupReport implements PopupReportInterface } /** + * Collect the tranactions for one account and no budget. + * * @param Account $account * @param array $attributes * @@ -72,6 +76,8 @@ class PopupReport implements PopupReportInterface } /** + * Collect the tranactions for a budget. + * * @param Budget $budget * @param array $attributes * @@ -95,6 +101,8 @@ class PopupReport implements PopupReportInterface } /** + * Collect journals by a category. + * * @param Category $category * @param array $attributes * @@ -112,6 +120,8 @@ class PopupReport implements PopupReportInterface } /** + * Group transactions by expense. + * * @param Account $account * @param array $attributes * @@ -119,6 +129,10 @@ class PopupReport implements PopupReportInterface */ public function byExpenses(Account $account, array $attributes): Collection { + /** @var JournalRepositoryInterface $repository */ + $repository = app(JournalRepositoryInterface::class); + $repository->setUser($account->user); + /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); @@ -130,9 +144,9 @@ class PopupReport implements PopupReportInterface // filter for transfers and withdrawals TO the given $account $journals = $journals->filter( - function (Transaction $transaction) use ($report) { + function (Transaction $transaction) use ($report, $repository) { // get the destinations: - $sources = $transaction->transactionJournal->sourceAccountList()->pluck('id')->toArray(); + $sources = $repository->getJournalSourceAccounts($transaction->transactionJournal)->pluck('id')->toArray(); // do these intersect with the current list? return !empty(array_intersect($report, $sources)); @@ -143,6 +157,8 @@ class PopupReport implements PopupReportInterface } /** + * Collect transactions by income. + * * @param Account $account * @param array $attributes * diff --git a/app/Helpers/Report/PopupReportInterface.php b/app/Helpers/Report/PopupReportInterface.php index 6345afdcc3..ca38466bca 100644 --- a/app/Helpers/Report/PopupReportInterface.php +++ b/app/Helpers/Report/PopupReportInterface.php @@ -33,6 +33,8 @@ use Illuminate\Support\Collection; interface PopupReportInterface { /** + * Get balances for budget. + * * @param Budget $budget * @param Account $account * @param array $attributes @@ -42,6 +44,8 @@ interface PopupReportInterface public function balanceForBudget(Budget $budget, Account $account, array $attributes): Collection; /** + * Get balances for transactions without a budget. + * * @param Account $account * @param array $attributes * @@ -50,6 +54,8 @@ interface PopupReportInterface public function balanceForNoBudget(Account $account, array $attributes): Collection; /** + * Group by budget. + * * @param Budget $budget * @param array $attributes * @@ -58,6 +64,8 @@ interface PopupReportInterface public function byBudget(Budget $budget, array $attributes): Collection; /** + * Group by category. + * * @param Category $category * @param array $attributes * @@ -66,6 +74,8 @@ interface PopupReportInterface public function byCategory(Category $category, array $attributes): Collection; /** + * Do something with expense. Sorry, I am not very inspirational here. + * * @param Account $account * @param array $attributes * @@ -74,6 +84,8 @@ interface PopupReportInterface public function byExpenses(Account $account, array $attributes): Collection; /** + * Do something with income. Sorry, I am not very inspirational here. + * * @param Account $account * @param array $attributes * diff --git a/app/Helpers/Report/ReportHelper.php b/app/Helpers/Report/ReportHelper.php index 1365e1a27d..8f1cad60b1 100644 --- a/app/Helpers/Report/ReportHelper.php +++ b/app/Helpers/Report/ReportHelper.php @@ -38,7 +38,7 @@ use Illuminate\Support\Collection; */ class ReportHelper implements ReportHelperInterface { - /** @var BudgetRepositoryInterface */ + /** @var BudgetRepositoryInterface The budget repository */ protected $budgetRepository; /** @@ -56,10 +56,11 @@ class ReportHelper implements ReportHelperInterface * This method generates a full report for the given period on all * the users bills and their payments. * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly 5. - * * Excludes bills which have not had a payment on the mentioned accounts. * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * * @param Carbon $start * @param Carbon $end * @param Collection $accounts @@ -82,6 +83,7 @@ class ReportHelper implements ReportHelperInterface foreach ($expectedDates as $payDate) { $endOfPayPeriod = app('navigation')->endOfX($payDate, $bill->repeat_freq, null); + /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAccounts($accounts)->setRange($payDate, $endOfPayPeriod)->setBills($bills); $journals = $collector->getJournals(); @@ -116,6 +118,8 @@ class ReportHelper implements ReportHelperInterface } /** + * Generate a list of months for the report. + * * @param Carbon $date * * @return array diff --git a/app/Helpers/Report/ReportHelperInterface.php b/app/Helpers/Report/ReportHelperInterface.php index 2d182cb6d8..703aa149a9 100644 --- a/app/Helpers/Report/ReportHelperInterface.php +++ b/app/Helpers/Report/ReportHelperInterface.php @@ -46,6 +46,8 @@ interface ReportHelperInterface public function getBillReport(Carbon $start, Carbon $end, Collection $accounts): BillCollection; /** + * Generate a list of months. + * * @param Carbon $date * * @return array diff --git a/app/Helpers/Update/UpdateTrait.php b/app/Helpers/Update/UpdateTrait.php new file mode 100644 index 0000000000..64a02b4a51 --- /dev/null +++ b/app/Helpers/Update/UpdateTrait.php @@ -0,0 +1,131 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Helpers\Update; + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Services\Github\Object\Release; +use FireflyIII\Services\Github\Request\UpdateRequest; +use Log; + +/** + * Trait UpdateTrait + * + * @package FireflyIII\Helpers\Update + */ +trait UpdateTrait +{ + /** + * Get object for the latest release from GitHub. + * + * @return Release|null + */ + public function getLatestRelease(): ?Release + { + $return = null; + /** @var UpdateRequest $request */ + $request = app(UpdateRequest::class); + try { + $request->call(); + } catch (FireflyException $e) { + Log::error(sprintf('Could not check for updates: %s', $e->getMessage())); + } + + // get releases from array. + $releases = $request->getReleases(); + if (\count($releases) > 0) { + // first entry should be the latest entry: + /** @var Release $first */ + $first = reset($releases); + $return = $first; + } + + return $return; + } + + /** + * Parses the version check result in a human readable sentence. + * + * @param Release|null $release + * @param int $versionCheck + * + * @return string + */ + public function parseResult(Release $release = null, int $versionCheck): string + { + $current = (string)config('firefly.version'); + $return = ''; + if ($versionCheck === -2) { + $return = (string)trans('firefly.update_check_error'); + } + if ($versionCheck === -1 && null !== $release) { + // there is a new FF version! + // has it been released for at least three days? + $today = new Carbon; + $releaseDate = $release->getUpdated(); + if ($today->diffInDays($releaseDate, true) > 3) { + $monthAndDayFormat = (string)trans('config.month_and_day'); + $return = (string)trans( + 'firefly.update_new_version_alert', + [ + 'your_version' => $current, + 'new_version' => $release->getTitle(), + 'date' => $release->getUpdated()->formatLocalized($monthAndDayFormat), + ] + ); + } + } + + if (0 === $versionCheck) { + // you are running the current version! + $return = (string)trans('firefly.update_current_version_alert', ['version' => $current]); + } + if (1 === $versionCheck && null !== $release) { + // you are running a newer version! + $return = (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $release->getTitle()]); + } + + return $return; + } + + /** + * Compare version and store result. + * + * @param Release|null $release + * + * @return int + */ + public function versionCheck(Release $release = null): int + { + if (null === $release) { + return -2; + } + $current = (string)config('firefly.version'); + $latest = $release->getTitle(); + $check = version_compare($current, $latest); + Log::debug(sprintf('Comparing %s with %s, result is %s', $current, $latest, $check)); + + return $check; + } +} \ No newline at end of file diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index d004c440aa..f1c96b4055 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -18,13 +18,13 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection CallableParameterUseCaseInTypeContextInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Helpers\Collector\JournalCollectorInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\ReconciliationStoreRequest; use FireflyIII\Http\Requests\ReconciliationUpdateRequest; @@ -37,8 +37,6 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Services\Internal\Update\CurrencyUpdateService; -use Illuminate\Http\Request; -use Illuminate\Support\Collection; use Log; use Preferences; @@ -113,69 +111,14 @@ class ReconcileController extends Controller )->with('data', $preFilled); } - /** - * @param Request $request - * @param Account $account - * @param Carbon $start - * @param Carbon $end - * - * @return \Illuminate\Http\JsonResponse - * - * @throws FireflyException - * @throws \Throwable - */ - public function overview(Request $request, Account $account, Carbon $start, Carbon $end) - { - if (AccountType::ASSET !== $account->accountType->type) { - throw new FireflyException(sprintf('Account %s is not an asset account.', $account->name)); - } - $startBalance = $request->get('startBalance'); - $endBalance = $request->get('endBalance'); - $transactionIds = $request->get('transactions') ?? []; - $clearedIds = $request->get('cleared') ?? []; - $amount = '0'; - $clearedAmount = '0'; - $route = route('accounts.reconcile.submit', [$account->id, $start->format('Ymd'), $end->format('Ymd')]); - // get sum of transaction amounts: - $transactions = $this->repository->getTransactionsById($transactionIds); - $cleared = $this->repository->getTransactionsById($clearedIds); - $countCleared = 0; - - /** @var Transaction $transaction */ - foreach ($transactions as $transaction) { - $amount = bcadd($amount, $transaction->amount); - } - - /** @var Transaction $transaction */ - foreach ($cleared as $transaction) { - if ($transaction->transactionJournal->date <= $end) { - $clearedAmount = bcadd($clearedAmount, $transaction->amount); - ++$countCleared; - } - } - $difference = bcadd(bcadd(bcsub($startBalance, $endBalance), $clearedAmount), $amount); - $diffCompare = bccomp($difference, '0'); - $return = [ - 'post_uri' => $route, - 'html' => view( - 'accounts.reconcile.overview', compact( - 'account', 'start', 'diffCompare', 'difference', 'end', 'clearedIds', 'transactionIds', 'clearedAmount', - 'startBalance', 'endBalance', 'amount', - 'route', 'countCleared' - ) - )->render(), - ]; - - return response()->json($return); - } - /** * @param Account $account * @param Carbon|null $start * @param Carbon|null $end * * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View - * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * @throws FireflyException */ public function reconcile(Account $account, Carbon $start = null, Carbon $end = null) @@ -230,6 +173,7 @@ class ReconcileController extends Controller * @param TransactionJournal $journal * * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View + * @throws FireflyException */ public function show(TransactionJournal $journal) { @@ -241,28 +185,35 @@ class ReconcileController extends Controller // get main transaction: $transaction = $this->repository->getAssetTransaction($journal); - $account = $transaction->account; + if (null === $transaction) { + throw new FireflyException('The transaction data is incomplete. This is probably a bug. Apologies.'); + } + $account = $transaction->account; return view('accounts.reconcile.show', compact('journal', 'subTitle', 'transaction', 'account')); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param ReconciliationStoreRequest $request - * @param JournalRepositoryInterface $repository * @param Account $account * @param Carbon $start * @param Carbon $end * * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @throws FireflyException + * + * @SuppressWarnings(PHPMD.CyclomaticComplexity) + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ - public function submit(ReconciliationStoreRequest $request, JournalRepositoryInterface $repository, Account $account, Carbon $start, Carbon $end) + public function submit(ReconciliationStoreRequest $request, Account $account, Carbon $start, Carbon $end) { Log::debug('In ReconcileController::submit()'); $data = $request->getAll(); /** @var Transaction $transaction */ foreach ($data['transactions'] as $transactionId) { - $repository->reconcileById((int)$transactionId); + $this->repository->reconcileById((int)$transactionId); } Log::debug('Reconciled all transactions.'); @@ -270,16 +221,13 @@ class ReconcileController extends Controller if ('create' === $data['reconcile']) { // get "opposing" account. $reconciliation = $this->accountRepos->getReconciliation($account); - - - $difference = $data['difference']; - $source = $reconciliation; - $destination = $account; - if (bccomp($difference, '0') === 1) { + $difference = $data['difference']; + $source = $reconciliation; + $destination = $account; + if (1 === bccomp($difference, '0')) { // amount is positive. Add it to reconciliation? $source = $account; $destination = $reconciliation; - } // data for journal @@ -321,63 +269,15 @@ class ReconcileController extends Controller 'notes' => implode(', ', $data['transactions']), ]; - $repository->store($journalData); + $this->repository->store($journalData); } Log::debug('End of routine.'); - - Preferences::mark(); - + app('preferences')->mark(); session()->flash('success', trans('firefly.reconciliation_stored')); return redirect(route('accounts.show', [$account->id])); } - /** - * @param Account $account - * @param Carbon $start - * @param Carbon $end - * - * @return mixed - * - * @throws FireflyException - * @throws \Throwable - */ - public function transactions(Account $account, Carbon $start, Carbon $end) - { - if (AccountType::INITIAL_BALANCE === $account->accountType->type) { - return $this->redirectToOriginalAccount($account); - } - - $startDate = clone $start; - $startDate->subDays(1); - - $currencyId = (int)$this->accountRepos->getMetaValue($account, 'currency_id'); - $currency = $this->currencyRepos->findNull($currencyId); - if (0 === $currency) { - $currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore - } - - $startBalance = round(app('steam')->balance($account, $startDate), $currency->decimal_places); - $endBalance = round(app('steam')->balance($account, $end), $currency->decimal_places); - - // get the transactions - $selectionStart = clone $start; - $selectionStart->subDays(3); - $selectionEnd = clone $end; - $selectionEnd->addDays(3); - - // grab transactions: - /** @var JournalCollectorInterface $collector */ - $collector = app(JournalCollectorInterface::class); - $collector->setAccounts(new Collection([$account])) - ->setRange($selectionStart, $selectionEnd)->withBudgetInformation()->withOpposingAccount()->withCategoryInformation(); - $transactions = $collector->getJournals(); - $html = view( - 'accounts.reconcile.transactions', compact('account', 'transactions', 'currency', 'start', 'end', 'selectionStart', 'selectionEnd') - )->render(); - - return response()->json(['html' => $html, 'startBalance' => $startBalance, 'endBalance' => $endBalance]); - } /** * @param ReconciliationUpdateRequest $request @@ -401,7 +301,7 @@ class ReconcileController extends Controller // amount pos neg influences the accounts: $source = $this->repository->getJournalSourceAccounts($journal)->first(); $destination = $this->repository->getJournalDestinationAccounts($journal)->first(); - if (bccomp($submitted['amount'], '0') === 1) { + if (1 === bccomp($submitted['amount'], '0')) { // amount is positive, switch accounts: [$source, $destination] = [$destination, $source]; diff --git a/app/Http/Controllers/AccountController.php b/app/Http/Controllers/AccountController.php index 225e52b89a..7859efca25 100644 --- a/app/Http/Controllers/AccountController.php +++ b/app/Http/Controllers/AccountController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection CallableParameterUseCaseInTypeContextInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers; @@ -39,13 +40,11 @@ use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Preferences; -use Steam; use View; /** * Class AccountController. * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class AccountController extends Controller { @@ -76,13 +75,14 @@ class AccountController extends Controller } /** - * @param Request $request - * @param string $what + * @param Request $request + * @param string|null $what * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function create(Request $request, string $what = 'asset') + public function create(Request $request, string $what = null) { + $what = $what ?? 'asset'; $defaultCurrency = app('amount')->getDefaultCurrency(); $subTitleIcon = config('firefly.subIconsByIdentifier.' . $what); $subTitle = trans('firefly.make_new_' . $what . '_account'); @@ -106,7 +106,7 @@ class AccountController extends Controller /** * @param Account $account * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(Account $account) { @@ -137,25 +137,17 @@ class AccountController extends Controller $this->repository->destroy($account, $moveTo); $request->session()->flash('success', (string)trans('firefly.' . $typeName . '_deleted', ['name' => $name])); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('accounts.delete.uri')); } /** - * Edit an account. - * * @param Request $request * @param Account $account - * * @param AccountRepositoryInterface $repository * - * @return View - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // long and complex but not that excessively so. - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - * - + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Request $request, Account $account, AccountRepositoryInterface $repository) { @@ -214,7 +206,7 @@ class AccountController extends Controller * @param Request $request * @param string $what * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(Request $request, string $what) { @@ -235,9 +227,9 @@ class AccountController extends Controller $start->subDay(); $ids = $accounts->pluck('id')->toArray(); - $startBalances = Steam::balancesByAccounts($accounts, $start); - $endBalances = Steam::balancesByAccounts($accounts, $end); - $activities = Steam::getLastActivities($ids); + $startBalances = app('steam')->balancesByAccounts($accounts, $start); + $endBalances = app('steam')->balancesByAccounts($accounts, $end); + $activities = app('steam')->getLastActivities($ids); $accounts->each( function (Account $account) use ($activities, $startBalances, $endBalances) { @@ -255,6 +247,8 @@ class AccountController extends Controller return view('accounts.index', compact('what', 'subTitleIcon', 'subTitle', 'page', 'accounts')); } + + /** @noinspection MoreThanThreeArgumentsInspection */ /** * Show an account. * @@ -294,11 +288,12 @@ class AccountController extends Controller if (0 === $currencyId) { $currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore } - $fStart = $start->formatLocalized($this->monthAndDayFormat); - $fEnd = $end->formatLocalized($this->monthAndDayFormat); - $subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]); - $chartUri = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); - $periods = $this->getPeriodOverview($account, $end); + $fStart = $start->formatLocalized($this->monthAndDayFormat); + $fEnd = $end->formatLocalized($this->monthAndDayFormat); + $subTitle = trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]); + $chartUri = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); + $periods = $this->getPeriodOverview($account, $end); + /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page); $collector->setRange($start, $end); @@ -312,6 +307,7 @@ class AccountController extends Controller ); } + /** * Show an account. * @@ -339,8 +335,9 @@ class AccountController extends Controller if (0 === $currencyId) { $currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore } - $subTitle = trans('firefly.all_journals_for_account', ['name' => $account->name]); - $periods = new Collection; + $subTitle = trans('firefly.all_journals_for_account', ['name' => $account->name]); + $periods = new Collection; + /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page); $transactions = $collector->getPaginatedJournals(); @@ -364,7 +361,7 @@ class AccountController extends Controller $data = $request->getAccountData(); $account = $this->repository->store($data); $request->session()->flash('success', (string)trans('firefly.stored_new_account', ['name' => $account->name])); - Preferences::mark(); + app('preferences')->mark(); // update preferences if necessary: $frontPage = Preferences::get('frontPageAccounts', [])->data; @@ -374,16 +371,16 @@ class AccountController extends Controller Preferences::set('frontPageAccounts', $frontPage); // @codeCoverageIgnoreEnd } - + // redirect to previous URL. + $redirect = redirect($this->getPreviousUri('accounts.create.uri')); if (1 === (int)$request->get('create_another')) { // set value so create routine will not overwrite URL: $request->session()->put('accounts.create.fromStore', true); - return redirect(route('accounts.create', [$request->input('what')]))->withInput(); + $redirect = redirect(route('accounts.create', [$request->input('what')]))->withInput(); } - // redirect to previous URL. - return redirect($this->getPreviousUri('accounts.create.uri')); + return $redirect; } /** @@ -398,17 +395,17 @@ class AccountController extends Controller $this->repository->update($account, $data); $request->session()->flash('success', (string)trans('firefly.updated_account', ['name' => $account->name])); - Preferences::mark(); + app('preferences')->mark(); + $redirect = redirect($this->getPreviousUri('accounts.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // set value so edit routine will not overwrite URL: $request->session()->put('accounts.edit.fromUpdate', true); - return redirect(route('accounts.edit', [$account->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('accounts.edit', [$account->id]))->withInput(['return_to_edit' => 1]); } - // redirect to previous URL. - return redirect($this->getPreviousUri('accounts.edit.uri')); + return $redirect; } /** @@ -419,13 +416,15 @@ class AccountController extends Controller */ protected function isInArray(array $array, int $entryId) { + $result = '0'; if (isset($array[$entryId])) { - return $array[$entryId]; + $result = $array[$entryId]; } - return '0'; + return $result; } + /** * This method returns "period entries", so nov-2015, dec-2015, etc etc (this depends on the users session range) * and for each period, the amount of money spent and earned. This is a complex operation which is cached for @@ -437,7 +436,6 @@ class AccountController extends Controller * * @return Collection * - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ private function getPeriodOverview(Account $account, ?Carbon $date): Collection { @@ -478,6 +476,7 @@ class AccountController extends Controller $spent = (string)$collector->getJournals()->sum('transaction_amount'); $dateName = app('navigation')->periodShow($currentDate['start'], $currentDate['period']); + /** @noinspection PhpUndefinedMethodInspection */ $entries->push( [ 'name' => $dateName, diff --git a/app/Http/Controllers/Admin/ConfigurationController.php b/app/Http/Controllers/Admin/ConfigurationController.php index f38c2263a8..65ae4cbc24 100644 --- a/app/Http/Controllers/Admin/ConfigurationController.php +++ b/app/Http/Controllers/Admin/ConfigurationController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpUndefinedClassInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Admin; @@ -27,9 +28,7 @@ use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Middleware\IsSandStormUser; use FireflyIII\Http\Requests\ConfigurationRequest; use FireflyIII\Support\Facades\FireflyConfig; -use Preferences; -use Redirect; -use View; +use Illuminate\Http\RedirectResponse; /** * Class ConfigurationController. @@ -56,7 +55,7 @@ class ConfigurationController extends Controller } /** - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index() { @@ -78,9 +77,9 @@ class ConfigurationController extends Controller /** * @param ConfigurationRequest $request * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function postIndex(ConfigurationRequest $request) + public function postIndex(ConfigurationRequest $request): RedirectResponse { // get config values: $data = $request->getConfigurationData(); @@ -91,8 +90,8 @@ class ConfigurationController extends Controller // flash message session()->flash('success', (string)trans('firefly.configuration_updated')); - Preferences::mark(); + app('preferences')->mark(); - return Redirect::route('admin.configuration.index'); + return redirect()->route('admin.configuration.index'); } } diff --git a/app/Http/Controllers/Admin/HomeController.php b/app/Http/Controllers/Admin/HomeController.php index b53ac0b274..668ce53214 100644 --- a/app/Http/Controllers/Admin/HomeController.php +++ b/app/Http/Controllers/Admin/HomeController.php @@ -26,6 +26,7 @@ use FireflyIII\Events\AdminRequestedTestMessage; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Middleware\IsSandStormUser; +use FireflyIII\User; use Illuminate\Http\Request; use Log; @@ -63,9 +64,11 @@ class HomeController extends Controller */ public function testMessage(Request $request) { + /** @var User $user */ + $user = auth()->user(); $ipAddress = $request->ip(); Log::debug(sprintf('Now in testMessage() controller. IP is %s', $ipAddress)); - event(new AdminRequestedTestMessage(auth()->user(), $ipAddress)); + event(new AdminRequestedTestMessage($user, $ipAddress)); session()->flash('info', (string)trans('firefly.send_test_triggered')); return redirect(route('admin.index')); diff --git a/app/Http/Controllers/Admin/LinkController.php b/app/Http/Controllers/Admin/LinkController.php index 5884596fa0..1515260fd4 100644 --- a/app/Http/Controllers/Admin/LinkController.php +++ b/app/Http/Controllers/Admin/LinkController.php @@ -28,7 +28,6 @@ use FireflyIII\Http\Requests\LinkTypeFormRequest; use FireflyIII\Models\LinkType; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; use Illuminate\Http\Request; -use Preferences; use View; /** @@ -116,7 +115,7 @@ class LinkController extends Controller $repository->destroy($linkType, $moveTo); $request->session()->flash('success', (string)trans('firefly.deleted_link_type', ['name' => $name])); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('link_types.delete.uri')); } @@ -194,16 +193,16 @@ class LinkController extends Controller ]; $linkType = $repository->store($data); $request->session()->flash('success', (string)trans('firefly.stored_new_link_type', ['name' => $linkType->name])); - + $redirect = redirect($this->getPreviousUri('link_types.create.uri')); if (1 === (int)$request->get('create_another')) { // set value so create routine will not overwrite URL: $request->session()->put('link_types.create.fromStore', true); - return redirect(route('admin.links.create'))->withInput(); + $redirect = redirect(route('admin.links.create'))->withInput(); } // redirect to previous URL. - return redirect($this->getPreviousUri('link_types.create.uri')); + return $redirect; } /** @@ -229,16 +228,16 @@ class LinkController extends Controller $repository->update($linkType, $data); $request->session()->flash('success', (string)trans('firefly.updated_link_type', ['name' => $linkType->name])); - Preferences::mark(); - + app('preferences')->mark(); + $redirect = redirect($this->getPreviousUri('link_types.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // set value so edit routine will not overwrite URL: $request->session()->put('link_types.edit.fromUpdate', true); - return redirect(route('admin.links.edit', [$linkType->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('admin.links.edit', [$linkType->id]))->withInput(['return_to_edit' => 1]); } // redirect to previous URL. - return redirect($this->getPreviousUri('link_types.edit.uri')); + return $redirect; } } diff --git a/app/Http/Controllers/Admin/UpdateController.php b/app/Http/Controllers/Admin/UpdateController.php index 8a6b0b5494..9c4adfa4f7 100644 --- a/app/Http/Controllers/Admin/UpdateController.php +++ b/app/Http/Controllers/Admin/UpdateController.php @@ -18,27 +18,24 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpMethodParametersCountMismatchInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Admin; -use Carbon\Carbon; use FireflyConfig; -use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Helpers\Update\UpdateTrait; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Middleware\IsSandStormUser; -use FireflyIII\Services\Github\Object\Release; -use FireflyIII\Services\Github\Request\UpdateRequest; use Illuminate\Http\Request; -use Log; /** * Class HomeController. */ class UpdateController extends Controller { - + use UpdateTrait; /** * ConfigurationController constructor. @@ -70,9 +67,9 @@ class UpdateController extends Controller $permission = app('fireflyconfig')->get('permission_update_check', -1); $selected = $permission->data; $options = [ - '-1' => trans('firefly.updates_ask_me_later'), - '0' => trans('firefly.updates_do_not_check'), - '1' => trans('firefly.updates_enable_check'), + -1 => trans('firefly.updates_ask_me_later'), + 0 => trans('firefly.updates_do_not_check'), + 1 => trans('firefly.updates_enable_check'), ]; return view('admin.update.index', compact('subTitle', 'subTitleIcon', 'selected', 'options')); @@ -98,51 +95,16 @@ class UpdateController extends Controller */ public function updateCheck() { - $current = config('firefly.version'); - /** @var UpdateRequest $request */ - $request = app(UpdateRequest::class); - $check = -2; - $first = new Release(['id' => '0', 'title' => '0', 'updated' => '2017-01-01', 'content' => '']); - $string = ''; - try { - $request->call(); - $releases = $request->getReleases(); - // first entry should be the latest entry: - /** @var Release $first */ - $first = reset($releases); - $check = version_compare($current, $first->getTitle()); - FireflyConfig::set('last_update_check', time()); - } catch (FireflyException $e) { - Log::error(sprintf('Could not check for updates: %s', $e->getMessage())); - } - if ($check === -2) { - $string = (string)trans('firefly.update_check_error'); - } + $latestRelease = $this->getLatestRelease(); + $versionCheck = $this->versionCheck($latestRelease); + $resultString = $this->parseResult($latestRelease, $versionCheck); - if ($check === -1) { - // there is a new FF version! - // has it been released for more than three days? - $today = new Carbon; - if ($today->diffInDays($first->getUpdated(), true) > 3) { - $string = (string)trans( - 'firefly.update_new_version_alert', - [ - 'your_version' => $current, - 'new_version' => $first->getTitle(), - 'date' => $first->getUpdated()->formatLocalized($this->monthAndDayFormat), - ] - ); - } - } - if ($check === 0) { - // you are running the current version! - $string = (string)trans('firefly.update_current_version_alert', ['version' => $current]); - } - if ($check === 1) { - // you are running a newer version! - $string = (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $first->getTitle()]); + if (0 !== $versionCheck && '' !== $resultString) { + // flash info + session()->flash('info', $resultString); } + FireflyConfig::set('last_update_check', time()); - return response()->json(['result' => $string]); + return response()->json(['result' => $resultString]); } } diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index 02be837ae9..2a09646643 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -30,7 +30,6 @@ use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Log; use Preferences; -use View; /** * Class UserController. @@ -85,7 +84,7 @@ class UserController extends Controller /** * @param User $user * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(User $user) { @@ -110,7 +109,7 @@ class UserController extends Controller /** * @param UserRepositoryInterface $repository * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(UserRepositoryInterface $repository) { @@ -120,13 +119,13 @@ class UserController extends Controller // add meta stuff. $users->each( - function (User $user) { + function (User $user) use ($repository) { $list = ['twoFactorAuthEnabled', 'twoFactorAuthSecret']; $preferences = Preferences::getArrayForUser($user, $list); - $user->isAdmin = $user->hasRole('owner'); + $user->isAdmin = $repository->hasRole($user, 'owner'); $is2faEnabled = 1 === $preferences['twoFactorAuthEnabled']; $has2faSecret = null !== $preferences['twoFactorAuthSecret']; - $user->has2FA = ($is2faEnabled && $has2faSecret) ? true : false; + $user->has2FA = ($is2faEnabled && $has2faSecret); $user->prefs = $preferences; } ); @@ -149,15 +148,9 @@ class UserController extends Controller $information = $repository->getUserData($user); return view( - 'admin.users.show', - compact( - 'title', - 'mainTitleIcon', - 'subTitle', - 'subTitleIcon', - 'information', - 'user' - ) + 'admin.users.show', compact( + 'title', 'mainTitleIcon', 'subTitle', 'subTitleIcon', 'information', 'user' + ) ); } @@ -182,17 +175,17 @@ class UserController extends Controller $repository->updateEmail($user, $data['email']); session()->flash('success', (string)trans('firefly.updated_user', ['email' => $user->email])); - Preferences::mark(); - + app('preferences')->mark(); + $redirect = redirect($this->getPreviousUri('users.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart session()->put('users.edit.fromUpdate', true); - return redirect(route('admin.users.edit', [$user->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('admin.users.edit', [$user->id]))->withInput(['return_to_edit' => 1]); // @codeCoverageIgnoreEnd } // redirect to previous URL. - return redirect($this->getPreviousUri('users.edit.uri')); + return $redirect; } } diff --git a/app/Http/Controllers/AttachmentController.php b/app/Http/Controllers/AttachmentController.php index d698f4d732..0e9fc5f01c 100644 --- a/app/Http/Controllers/AttachmentController.php +++ b/app/Http/Controllers/AttachmentController.php @@ -26,15 +26,13 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Requests\AttachmentFormRequest; use FireflyIII\Models\Attachment; use FireflyIII\Repositories\Attachment\AttachmentRepositoryInterface; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Http\Response as LaravelResponse; -use Preferences; -use View; /** * Class AttachmentController. * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) // it's 13. */ class AttachmentController extends Controller { @@ -63,7 +61,7 @@ class AttachmentController extends Controller /** * @param Attachment $attachment * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(Attachment $attachment) { @@ -88,7 +86,7 @@ class AttachmentController extends Controller $this->repository->destroy($attachment); $request->session()->flash('success', (string)trans('firefly.attachment_deleted', ['name' => $name])); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('attachments.delete.uri')); } @@ -128,7 +126,7 @@ class AttachmentController extends Controller * @param Request $request * @param Attachment $attachment * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Request $request, Attachment $attachment) { @@ -169,35 +167,36 @@ class AttachmentController extends Controller * @param AttachmentFormRequest $request * @param Attachment $attachment * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function update(AttachmentFormRequest $request, Attachment $attachment) + public function update(AttachmentFormRequest $request, Attachment $attachment): RedirectResponse { $data = $request->getAttachmentData(); $this->repository->update($attachment, $data); $request->session()->flash('success', (string)trans('firefly.attachment_updated', ['name' => $attachment->filename])); - Preferences::mark(); + app('preferences')->mark(); + $redirect = redirect($this->getPreviousUri('attachments.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart $request->session()->put('attachments.edit.fromUpdate', true); - return redirect(route('attachments.edit', [$attachment->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('attachments.edit', [$attachment->id]))->withInput(['return_to_edit' => 1]); // @codeCoverageIgnoreEnd } // redirect to previous URL. - return redirect($this->getPreviousUri('attachments.edit.uri')); + return $redirect; } /** * @param Attachment $attachment * - * @return \Illuminate\Http\Response + * @return LaravelResponse * @throws FireflyException */ - public function view(Attachment $attachment) + public function view(Attachment $attachment): LaravelResponse { if ($this->repository->exists($attachment)) { $content = $this->repository->getContent($attachment); diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index bd870e2b45..d5b28d405f 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Auth; @@ -84,7 +85,7 @@ class ForgotPasswordController extends Controller $request->only('email') ); - if ($response == Password::RESET_LINK_SENT) { + if ($response === Password::RESET_LINK_SENT) { return back()->with('status', trans($response)); } @@ -93,9 +94,8 @@ class ForgotPasswordController extends Controller /** * @codeCoverageIgnore - * Display the form to request a password reset link. * - * @return \Illuminate\Http\Response + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function showLinkRequestForm() { diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 8b76348ea1..2fe7a26b1d 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Auth; @@ -59,12 +60,9 @@ class LoginController extends Controller } /** - * Handle a login request to the application. - * * @param Request $request * - * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response - * + * @return \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response|void * @throws \Illuminate\Validation\ValidationException */ public function login(Request $request) @@ -77,6 +75,8 @@ class LoginController extends Controller if ($this->hasTooManyLoginAttempts($request)) { $this->fireLockoutEvent($request); + /** @noinspection PhpInconsistentReturnPointsInspection */ + /** @noinspection PhpVoidFunctionResultUsedInspection */ return $this->sendLockoutResponse($request); } @@ -84,6 +84,8 @@ class LoginController extends Controller // user is logged in. Save in session if the user requested session to be remembered: $request->session()->put('remember_login', $request->filled('remember')); + /** @noinspection PhpInconsistentReturnPointsInspection */ + /** @noinspection PhpVoidFunctionResultUsedInspection */ return $this->sendLoginResponse($request); } @@ -92,6 +94,8 @@ class LoginController extends Controller // user surpasses their maximum number of attempts they will get locked out. $this->incrementLoginAttempts($request); + /** @noinspection PhpInconsistentReturnPointsInspection */ + /** @noinspection PhpVoidFunctionResultUsedInspection */ return $this->sendFailedLoginResponse($request); } @@ -123,7 +127,7 @@ class LoginController extends Controller public function showLoginForm(Request $request) { $count = DB::table('users')->count(); - if ($count === 0) { + if (0 === $count) { return redirect(route('register')); // @codeCoverageIgnore } diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index 265cd0924d..a49f12116a 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Auth; @@ -26,6 +27,7 @@ use FireflyConfig; use FireflyIII\Http\Controllers\Controller; use FireflyIII\User; use Illuminate\Auth\Events\Registered; +use Illuminate\Contracts\Validation\Validator as ValidatorContract; use Illuminate\Foundation\Auth\RegistersUsers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; @@ -61,9 +63,9 @@ class RegisterController extends Controller /** * Handle a registration request for the application. * - * @param \Illuminate\Http\Request $request + * @param Request $request * - * @return \Illuminate\Http\Response + * @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View */ public function register(Request $request) { @@ -76,6 +78,7 @@ class RegisterController extends Controller return view('error', compact('message')); } + /** @noinspection PhpUndefinedMethodInspection */ $this->validator($request->all())->validate(); event(new Registered($user = $this->create($request->all()))); @@ -93,7 +96,7 @@ class RegisterController extends Controller * * @param Request $request * - * @return \Illuminate\Http\Response + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function showRegistrationForm(Request $request) { @@ -121,7 +124,7 @@ class RegisterController extends Controller * * @return \FireflyIII\User */ - protected function create(array $data) + protected function create(array $data): User { return User::create( [ @@ -136,9 +139,9 @@ class RegisterController extends Controller * * @param array $data * - * @return \Illuminate\Contracts\Validation\Validator + * @return ValidatorContract */ - protected function validator(array $data) + protected function validator(array $data): ValidatorContract { return Validator::make( $data, diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index fe0040156d..2f43ad6461 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Auth; @@ -76,6 +77,7 @@ class ResetPasswordController extends Controller $allowRegistration = false; } + /** @noinspection PhpUndefinedFieldInspection */ return view('auth.passwords.reset')->with( ['token' => $token, 'email' => $request->email, 'allowRegistration' => $allowRegistration] ); diff --git a/app/Http/Controllers/Auth/TwoFactorController.php b/app/Http/Controllers/Auth/TwoFactorController.php index 1e1d6f6d94..3bc779fde6 100644 --- a/app/Http/Controllers/Auth/TwoFactorController.php +++ b/app/Http/Controllers/Auth/TwoFactorController.php @@ -25,6 +25,7 @@ namespace FireflyIII\Http\Controllers\Auth; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\TokenFormRequest; +use FireflyIII\User; use Illuminate\Cookie\CookieJar; use Illuminate\Http\Request; use Log; @@ -42,7 +43,6 @@ class TwoFactorController extends Controller * * @throws FireflyException * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function index(Request $request) { @@ -59,7 +59,7 @@ class TwoFactorController extends Controller return redirect(route('index')); } - if (0 === \strlen((string)$secret)) { + if ('' === (string)$secret) { throw new FireflyException('Your two factor authentication secret is empty, which it cannot be at this point. Please check the log files.'); } $request->session()->flash('two-factor-secret', $secret); @@ -72,6 +72,7 @@ class TwoFactorController extends Controller */ public function lostTwoFactor() { + /** @var User $user */ $user = auth()->user(); $siteOwner = env('SITE_OWNER', ''); $title = (string)trans('firefly.two_factor_forgot_title'); @@ -90,7 +91,6 @@ class TwoFactorController extends Controller * @param CookieJar $cookieJar * * @return mixed - * @SuppressWarnings(PHPMD.UnusedFormalParameter) // it's unused but the class does some validation. */ public function postIndex(TokenFormRequest $request, CookieJar $cookieJar) { diff --git a/app/Http/Controllers/BillController.php b/app/Http/Controllers/BillController.php index b0ae134570..c3258b9fea 100644 --- a/app/Http/Controllers/BillController.php +++ b/app/Http/Controllers/BillController.php @@ -30,6 +30,7 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\TransactionRules\TransactionMatcher; use FireflyIII\Transformers\BillTransformer; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Collection; use League\Fractal\Manager; @@ -80,7 +81,7 @@ class BillController extends Controller /** * @param Request $request * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function create(Request $request) { @@ -105,7 +106,7 @@ class BillController extends Controller /** * @param Bill $bill * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(Bill $bill) { @@ -120,7 +121,7 @@ class BillController extends Controller * @param Request $request * @param Bill $bill * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|\Illuminate\Routing\Redirector */ public function destroy(Request $request, Bill $bill) { @@ -128,7 +129,7 @@ class BillController extends Controller $this->billRepository->destroy($bill); $request->session()->flash('success', (string)trans('firefly.deleted_bill', ['name' => $name])); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('bills.delete.uri')); } @@ -137,7 +138,7 @@ class BillController extends Controller * @param Request $request * @param Bill $bill * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Request $request, Bill $bill) { @@ -177,7 +178,7 @@ class BillController extends Controller } /** - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index() { @@ -220,34 +221,34 @@ class BillController extends Controller * @param Request $request * @param Bill $bill * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|\Illuminate\Routing\Redirector * @throws \FireflyIII\Exceptions\FireflyException */ public function rescan(Request $request, Bill $bill) { - if (0 === (int)$bill->active) { + if (false === $bill->active) { $request->session()->flash('warning', (string)trans('firefly.cannot_scan_inactive_bill')); - - return redirect(URL::previous()); } - $set = $this->billRepository->getRulesForBill($bill); - $total = 0; - foreach ($set as $rule) { - // simply fire off all rules? - /** @var TransactionMatcher $matcher */ - $matcher = app(TransactionMatcher::class); - $matcher->setLimit(100000); // large upper limit - $matcher->setRange(100000); // large upper limit - $matcher->setRule($rule); - $matchingTransactions = $matcher->findTransactionsByRule(); - $total += $matchingTransactions->count(); - $this->billRepository->linkCollectionToBill($bill, $matchingTransactions); + if (true === $bill->active) { + $set = $this->billRepository->getRulesForBill($bill); + $total = 0; + foreach ($set as $rule) { + // simply fire off all rules? + /** @var TransactionMatcher $matcher */ + $matcher = app(TransactionMatcher::class); + $matcher->setLimit(100000); // large upper limit + $matcher->setRange(100000); // large upper limit + $matcher->setRule($rule); + $matchingTransactions = $matcher->findTransactionsByRule(); + $total += $matchingTransactions->count(); + $this->billRepository->linkCollectionToBill($bill, $matchingTransactions); + } + + + $request->session()->flash('success', (string)trans('firefly.rescanned_bill', ['total' => $total])); + app('preferences')->mark(); } - - $request->session()->flash('success', (string)trans('firefly.rescanned_bill', ['total' => $total])); - Preferences::mark(); - return redirect(URL::previous()); } @@ -255,7 +256,7 @@ class BillController extends Controller * @param Request $request * @param Bill $bill * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function show(Request $request, Bill $bill) { @@ -292,22 +293,24 @@ class BillController extends Controller return view('bills.show', compact('transactions', 'rules', 'yearAverage', 'overallAverage', 'year', 'object', 'bill', 'subTitle')); } + /** * @param BillFormRequest $request * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function store(BillFormRequest $request) + public function store(BillFormRequest $request): RedirectResponse { - $billData = $request->getBillData(); - $bill = $this->billRepository->store($billData); + $billData = $request->getBillData(); + $billData['active'] = true; + $bill = $this->billRepository->store($billData); if (null === $bill) { $request->session()->flash('error', (string)trans('firefly.bill_store_error')); return redirect(route('bills.create'))->withInput(); } $request->session()->flash('success', (string)trans('firefly.stored_new_bill', ['name' => $bill->name])); - Preferences::mark(); + app('preferences')->mark(); /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; @@ -324,9 +327,10 @@ class BillController extends Controller $return = 'true'; } + $group = null; // find first rule group, or create one: $count = $this->ruleGroupRepos->count(); - if ($count === 0) { + if (0 === $count) { $data = [ 'title' => (string)trans('firefly.rulegroup_for_bills_title'), 'description' => (string)trans('firefly.rulegroup_for_bills_description'), @@ -334,7 +338,7 @@ class BillController extends Controller $group = $this->ruleGroupRepos->store($data); } if ($count > 0) { - $group = $this->ruleGroupRepos->getActiveGroups(auth()->user())->first(); + $group = $this->ruleGroupRepos->getActiveGroups($bill->user)->first(); } // redirect to page that will create a new rule. @@ -347,15 +351,15 @@ class BillController extends Controller * @param BillFormRequest $request * @param Bill $bill * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function update(BillFormRequest $request, Bill $bill) + public function update(BillFormRequest $request, Bill $bill): RedirectResponse { $billData = $request->getBillData(); $bill = $this->billRepository->update($bill, $billData); $request->session()->flash('success', (string)trans('firefly.updated_bill', ['name' => $bill->name])); - Preferences::mark(); + app('preferences')->mark(); /** @var array $files */ $files = $request->hasFile('attachments') ? $request->file('attachments') : null; @@ -365,15 +369,16 @@ class BillController extends Controller if (\count($this->attachments->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachments->getMessages()->get('attachments')); // @codeCoverageIgnore } + $redirect = redirect($this->getPreviousUri('bills.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart $request->session()->put('bills.edit.fromUpdate', true); - return redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('bills.edit.uri')); + return $redirect; } } diff --git a/app/Http/Controllers/BudgetController.php b/app/Http/Controllers/BudgetController.php index df6f0d8954..e3a1ce7b0d 100644 --- a/app/Http/Controllers/BudgetController.php +++ b/app/Http/Controllers/BudgetController.php @@ -34,6 +34,8 @@ use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; @@ -44,8 +46,6 @@ use View; /** * Class BudgetController. * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - * @SuppressWarnings(PHPMD.TooManyPublicMethods) */ class BudgetController extends Controller { @@ -77,9 +77,9 @@ class BudgetController extends Controller * @param BudgetRepositoryInterface $repository * @param Budget $budget * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function amount(Request $request, BudgetRepositoryInterface $repository, Budget $budget) + public function amount(Request $request, BudgetRepositoryInterface $repository, Budget $budget): JsonResponse { $amount = (string)$request->get('amount'); $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); @@ -105,8 +105,8 @@ class BudgetController extends Controller $days = $start->diffInDays($end); $daysInMonth = $start->diffInDays($end); } - $days = $days === 0 ? 1 : $days; - $daysInMonth = $daysInMonth === 0 ? 1 : $daysInMonth; + $days = 0 === $days ? 1 : $days; + $daysInMonth = 0 === $daysInMonth ? 1 : $daysInMonth; // calculate left in budget: $spent = $repository->spentInPeriod(new Collection([$budget]), new Collection, $start, $end); @@ -139,7 +139,7 @@ class BudgetController extends Controller ); } - Preferences::mark(); + app('preferences')->mark(); return response()->json( [ @@ -161,7 +161,7 @@ class BudgetController extends Controller /** * @param Request $request * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function create(Request $request) { @@ -178,7 +178,7 @@ class BudgetController extends Controller /** * @param Budget $budget * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(Budget $budget) { @@ -201,7 +201,7 @@ class BudgetController extends Controller $name = $budget->name; $this->repository->destroy($budget); $request->session()->flash('success', (string)trans('firefly.deleted_budget', ['name' => $name])); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('budgets.delete.uri')); } @@ -210,7 +210,7 @@ class BudgetController extends Controller * @param Request $request * @param Budget $budget * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Request $request, Budget $budget) { @@ -236,10 +236,7 @@ class BudgetController extends Controller * @param Request $request * @param string|null $moment * - * @return View - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) complex because of while loop - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(Request $request, string $moment = null) { @@ -258,7 +255,7 @@ class BudgetController extends Controller $end = app('navigation')->endOfPeriod($start, $range); } catch (Exception $e) { // start and end are already defined. - Log::debug('start and end are already defined.'); + Log::debug(sprintf('start and end are already defined: %s', $e->getMessage())); } } @@ -273,8 +270,8 @@ class BudgetController extends Controller $days = $start->diffInDays($end); $daysInMonth = $start->diffInDays($end); } - $days = $days === 0 ? 1 : $days; - $daysInMonth = $daysInMonth === 0 ? 1 : $daysInMonth; + $days = 0 === $days ? 1 : $days; + $daysInMonth = 0 === $daysInMonth ? 1 : $daysInMonth; $next = clone $end; @@ -301,6 +298,7 @@ class BudgetController extends Controller // select thing for last 12 periods: $previousLoop = []; + /** @var Carbon $previousDate */ $previousDate = clone $start; $count = 0; while ($count < 12) { @@ -313,6 +311,7 @@ class BudgetController extends Controller // select thing for next 12 periods: $nextLoop = []; + /** @var Carbon $nextDate */ $nextDate = clone $end; $nextDate->addDay(); $count = 0; @@ -339,10 +338,10 @@ class BudgetController extends Controller ); } + /** * @param Carbon $start * @param Carbon $end - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ @@ -371,7 +370,8 @@ class BudgetController extends Controller ]; $currency = app('amount')->getDefaultCurrency(); $range = Preferences::get('viewRange', '1M')->data; - $begin = app('navigation')->subtractPeriod($start, $range, 3); + /** @var Carbon $begin */ + $begin = app('navigation')->subtractPeriod($start, $range, 3); Log::debug(sprintf('Range is %s', $range)); Log::debug(sprintf('infoIncome begin is %s', $begin->format('Y-m-d'))); @@ -381,6 +381,7 @@ class BudgetController extends Controller $count = 0; $currentStart = clone $begin; while ($currentStart < $start) { + Log::debug(sprintf('Loop: currentStart is %s', $currentStart->format('Y-m-d'))); $currentEnd = app('navigation')->endOfPeriod($currentStart, $range); $total = bcadd($total, $this->repository->getAvailableBudget($currency, $currentStart, $currentEnd)); @@ -420,16 +421,14 @@ class BudgetController extends Controller /** * @param Request $request * @param JournalRepositoryInterface $repository - * @param string $moment + * @param string|null $moment * - * @return View - * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function noBudget(Request $request, JournalRepositoryInterface $repository, string $moment = '') + public function noBudget(Request $request, JournalRepositoryInterface $repository, string $moment = null) { // default values: + $moment = $moment ?? ''; $range = Preferences::get('viewRange', '1M')->data; $start = null; $end = null; @@ -445,7 +444,8 @@ class BudgetController extends Controller // prep for "specific date" view. if ('all' !== $moment && \strlen($moment) > 0) { - $start = new Carbon($moment); + $start = new Carbon($moment); + /** @var Carbon $end */ $end = app('navigation')->endOfPeriod($start, $range); $subTitle = trans( 'firefly.without_budget_between', @@ -481,18 +481,18 @@ class BudgetController extends Controller /** * @param BudgetIncomeRequest $request * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function postUpdateIncome(BudgetIncomeRequest $request) + public function postUpdateIncome(BudgetIncomeRequest $request): RedirectResponse { $start = Carbon::createFromFormat('Y-m-d', $request->string('start')); $end = Carbon::createFromFormat('Y-m-d', $request->string('end')); $defaultCurrency = app('amount')->getDefaultCurrency(); $amount = $request->get('amount'); - $page = $request->integer('page') === 0 ? 1 : $request->integer('page'); + $page = 0 === $request->integer('page') ? 1 : $request->integer('page'); $this->repository->cleanupBudgets(); $this->repository->setAvailableBudget($defaultCurrency, $start, $end, $amount); - Preferences::mark(); + app('preferences')->mark(); return redirect(route('budgets.index', [$start->format('Y-m-d')]) . '?page=' . $page); } @@ -501,7 +501,7 @@ class BudgetController extends Controller * @param Request $request * @param Budget $budget * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function show(Request $request, Budget $budget) { @@ -530,8 +530,7 @@ class BudgetController extends Controller * @param Budget $budget * @param BudgetLimit $budgetLimit * - * @return View - * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View * @throws FireflyException */ public function showByBudgetLimit(Request $request, Budget $budget, BudgetLimit $budgetLimit) @@ -570,49 +569,54 @@ class BudgetController extends Controller * * @return \Illuminate\Http\RedirectResponse */ - public function store(BudgetFormRequest $request) + public function store(BudgetFormRequest $request): RedirectResponse { $data = $request->getBudgetData(); $budget = $this->repository->store($data); $this->repository->cleanupBudgets(); $request->session()->flash('success', (string)trans('firefly.stored_new_budget', ['name' => $budget->name])); - Preferences::mark(); + app('preferences')->mark(); + + $redirect = redirect($this->getPreviousUri('budgets.create.uri')); if (1 === (int)$request->get('create_another')) { // @codeCoverageIgnoreStart $request->session()->put('budgets.create.fromStore', true); - return redirect(route('budgets.create'))->withInput(); + $redirect = redirect(route('budgets.create'))->withInput(); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('budgets.create.uri')); + return $redirect; } + /** * @param BudgetFormRequest $request * @param Budget $budget * * @return \Illuminate\Http\RedirectResponse */ - public function update(BudgetFormRequest $request, Budget $budget) + public function update(BudgetFormRequest $request, Budget $budget): RedirectResponse { $data = $request->getBudgetData(); $this->repository->update($budget, $data); $request->session()->flash('success', (string)trans('firefly.updated_budget', ['name' => $budget->name])); $this->repository->cleanupBudgets(); - Preferences::mark(); + app('preferences')->mark(); + + $redirect = redirect($this->getPreviousUri('budgets.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart $request->session()->put('budgets.edit.fromUpdate', true); - return redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('budgets.edit', [$budget->id]))->withInput(['return_to_edit' => 1]); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('budgets.edit.uri')); + return $redirect; } /** @@ -632,6 +636,7 @@ class BudgetController extends Controller return view('budgets.income', compact('available', 'start', 'end', 'page')); } + /** * @param Budget $budget * @param Carbon $start @@ -665,6 +670,7 @@ class BudgetController extends Controller return $set; } + /** * @return Collection */ @@ -696,6 +702,7 @@ class BudgetController extends Controller $set = $collector->getJournals(); $sum = (string)($set->sum('transaction_amount') ?? '0'); $journals = $set->count(); + /** @noinspection PhpUndefinedMethodInspection */ $dateStr = $date['end']->format('Y-m-d'); $dateName = app('navigation')->periodShow($date['end'], $date['period']); $entries->push(['string' => $dateStr, 'name' => $dateName, 'count' => $journals, 'sum' => $sum, 'date' => clone $date['end']]); diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index 87af547c89..d16cc0f81b 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -38,8 +38,6 @@ use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Log; use Preferences; -use Steam; -use View; /** * Class CategoryController. @@ -54,7 +52,7 @@ class CategoryController extends Controller private $repository; /** - * + * CategoryController constructor. */ public function __construct() { @@ -76,7 +74,7 @@ class CategoryController extends Controller /** * @param Request $request * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function create(Request $request) { @@ -92,7 +90,7 @@ class CategoryController extends Controller /** * @param Category $category * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(Category $category) { @@ -116,7 +114,7 @@ class CategoryController extends Controller $this->repository->destroy($category); $request->session()->flash('success', (string)trans('firefly.deleted_category', ['name' => $name])); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('categories.delete.uri')); } @@ -125,7 +123,7 @@ class CategoryController extends Controller * @param Request $request * @param Category $category * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Request $request, Category $category) { @@ -167,38 +165,43 @@ class CategoryController extends Controller } /** - * @param Request $request - * @param string $moment + * @param Request $request + * @param string|null $moment * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function noCategory(Request $request, string $moment = '') + public function noCategory(Request $request, string $moment = null) { // default values: + $moment = $moment ?? ''; $range = Preferences::get('viewRange', '1M')->data; $start = null; $end = null; $periods = new Collection; $page = (int)$request->get('page'); $pageSize = (int)Preferences::get('listPageSize', 50)->data; - + Log::debug('Start of noCategory()'); // prep for "all" view. if ('all' === $moment) { $subTitle = trans('firefly.all_journals_without_category'); $first = $this->journalRepos->firstNull(); $start = null === $first ? new Carbon : $first->date; $end = new Carbon; + Log::debug('Moment is all()'); } // prep for "specific date" view. if ('all' !== $moment && \strlen($moment) > 0) { - $start = app('navigation')->startOfPeriod(new Carbon($moment), $range); + /** @var Carbon $start */ + $start = app('navigation')->startOfPeriod(new Carbon($moment), $range); + /** @var Carbon $end */ $end = app('navigation')->endOfPeriod($start, $range); $subTitle = trans( 'firefly.without_category_between', ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] ); $periods = $this->getNoCategoryPeriodOverview($start); + } // prep for current period @@ -211,6 +214,8 @@ class CategoryController extends Controller ['start' => $start->formatLocalized($this->monthAndDayFormat), 'end' => $end->formatLocalized($this->monthAndDayFormat)] ); } + Log::debug(sprintf('Start for noCategory() is %s', $start->format('Y-m-d'))); + Log::debug(sprintf('End for noCategory() is %s', $end->format('Y-m-d'))); /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); @@ -224,16 +229,16 @@ class CategoryController extends Controller } /** - * @param Request $request - * @param CategoryRepositoryInterface $repository - * @param Category $category - * @param string $moment + * @param Request $request + * @param Category $category + * @param string|null $moment * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function show(Request $request, CategoryRepositoryInterface $repository, Category $category, string $moment = '') + public function show(Request $request, Category $category, string $moment = null) { // default values: + $moment = $moment ?? ''; $subTitle = $category->name; $subTitleIcon = 'fa-bar-chart'; $page = (int)$request->get('page'); @@ -247,7 +252,7 @@ class CategoryController extends Controller // prep for "all" view. if ('all' === $moment) { $subTitle = trans('firefly.all_journals_for_category', ['name' => $category->name]); - $first = $repository->firstUseDate($category); + $first = $this->repository->firstUseDate($category); /** @var Carbon $start */ $start = $first ?? new Carbon; $end = new Carbon; @@ -255,8 +260,9 @@ class CategoryController extends Controller } // prep for "specific date" view. - if (\strlen($moment) > 0 && 'all' !== $moment) { - $start = app('navigation')->startOfPeriod(new Carbon($moment), $range); + if ('all' !== $moment && \strlen($moment) > 0) { + $start = app('navigation')->startOfPeriod(new Carbon($moment), $range); + /** @var Carbon $end */ $end = app('navigation')->endOfPeriod($start, $range); $subTitle = trans( 'firefly.journals_in_period_for_category', @@ -268,7 +274,7 @@ class CategoryController extends Controller } // prep for current period - if (0 === \strlen($moment)) { + if ('' === $moment) { /** @var Carbon $start */ $start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range)); /** @var Carbon $end */ @@ -304,19 +310,21 @@ class CategoryController extends Controller $category = $repository->store($data); $request->session()->flash('success', (string)trans('firefly.stored_category', ['name' => $category->name])); - Preferences::mark(); + app('preferences')->mark(); + $redirect = redirect(route('categories.index')); if (1 === (int)$request->get('create_another')) { // @codeCoverageIgnoreStart $request->session()->put('categories.create.fromStore', true); - return redirect(route('categories.create'))->withInput(); + $redirect = redirect(route('categories.create'))->withInput(); // @codeCoverageIgnoreEnd } - return redirect(route('categories.index')); + return $redirect; } + /** * @param CategoryFormRequest $request * @param CategoryRepositoryInterface $repository @@ -330,19 +338,22 @@ class CategoryController extends Controller $repository->update($category, $data); $request->session()->flash('success', (string)trans('firefly.updated_category', ['name' => $category->name])); - Preferences::mark(); + app('preferences')->mark(); + + $redirect = redirect($this->getPreviousUri('categories.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart $request->session()->put('categories.edit.fromUpdate', true); - return redirect(route('categories.edit', [$category->id])); + $redirect = redirect(route('categories.edit', [$category->id])); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('categories.edit.uri')); + return $redirect; } + /** * @param Carbon $theDate * @@ -350,11 +361,15 @@ class CategoryController extends Controller */ private function getNoCategoryPeriodOverview(Carbon $theDate): Collection { + Log::debug(sprintf('Now in getNoCategoryPeriodOverview(%s)', $theDate->format('Y-m-d'))); $range = Preferences::get('viewRange', '1M')->data; $first = $this->journalRepos->firstNull(); $start = null === $first ? new Carbon : $first->date; $end = $theDate ?? new Carbon; + Log::debug(sprintf('Start for getNoCategoryPeriodOverview() is %s', $start->format('Y-m-d'))); + Log::debug(sprintf('End for getNoCategoryPeriodOverview() is %s', $end->format('Y-m-d'))); + // properties for cache $cache = new CacheProperties; $cache->addProperty($start); @@ -384,7 +399,7 @@ class CategoryController extends Controller $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory() ->withOpposingAccount()->setTypes([TransactionType::TRANSFER]); $collector->removeFilter(InternalTransferFilter::class); - $transferred = Steam::positive($collector->getJournals()->sum('transaction_amount')); + $transferred = app('steam')->positive((string)$collector->getJournals()->sum('transaction_amount')); // amount spent /** @var JournalCollectorInterface $collector */ @@ -400,7 +415,8 @@ class CategoryController extends Controller $collector->setAllAssetAccounts()->setRange($date['start'], $date['end'])->withoutCategory()->withOpposingAccount()->setTypes( [TransactionType::DEPOSIT] ); - $earned = $collector->getJournals()->sum('transaction_amount'); + $earned = $collector->getJournals()->sum('transaction_amount'); + /** @noinspection PhpUndefinedMethodInspection */ $dateStr = $date['end']->format('Y-m-d'); $dateName = app('navigation')->periodShow($date['end'], $date['period']); $entries->push( @@ -421,6 +437,7 @@ class CategoryController extends Controller return $entries; } + /** * @param Category $category * @@ -452,8 +469,9 @@ class CategoryController extends Controller $entries = new Collection; foreach ($dates as $currentDate) { - $spent = $this->repository->spentInPeriod(new Collection([$category]), $accounts, $currentDate['start'], $currentDate['end']); - $earned = $this->repository->earnedInPeriod(new Collection([$category]), $accounts, $currentDate['start'], $currentDate['end']); + $spent = $this->repository->spentInPeriod(new Collection([$category]), $accounts, $currentDate['start'], $currentDate['end']); + $earned = $this->repository->earnedInPeriod(new Collection([$category]), $accounts, $currentDate['start'], $currentDate['end']); + /** @noinspection PhpUndefinedMethodInspection */ $dateStr = $currentDate['end']->format('Y-m-d'); $dateName = app('navigation')->periodShow($currentDate['end'], $currentDate['period']); @@ -463,7 +481,7 @@ class CategoryController extends Controller $collector->setAllAssetAccounts()->setRange($currentDate['start'], $currentDate['end'])->setCategory($category) ->withOpposingAccount()->setTypes([TransactionType::TRANSFER]); $collector->removeFilter(InternalTransferFilter::class); - $transferred = Steam::positive($collector->getJournals()->sum('transaction_amount')); + $transferred = app('steam')->positive((string)$collector->getJournals()->sum('transaction_amount')); $entries->push( [ diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index e0e18773b8..3ebf46d7bc 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection NullPointerExceptionInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; @@ -35,6 +36,7 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; use Log; use Preferences; @@ -62,9 +64,9 @@ class AccountController extends Controller * * @param AccountRepositoryInterface $repository * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function expenseAccounts(AccountRepositoryInterface $repository) + public function expenseAccounts(AccountRepositoryInterface $repository): JsonResponse { $start = clone session('start', Carbon::now()->startOfMonth()); $end = clone session('end', Carbon::now()->endOfMonth()); @@ -99,14 +101,15 @@ class AccountController extends Controller return response()->json($data); } + /** * @param Account $account * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function expenseBudget(Account $account, Carbon $start, Carbon $end) + public function expenseBudget(Account $account, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty($account->id); @@ -146,9 +149,9 @@ class AccountController extends Controller * @param AccountRepositoryInterface $repository * @param Account $account * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function expenseBudgetAll(AccountRepositoryInterface $repository, Account $account) + public function expenseBudgetAll(AccountRepositoryInterface $repository, Account $account): JsonResponse { $start = $repository->oldestJournalDate($account); $end = Carbon::now(); @@ -156,14 +159,15 @@ class AccountController extends Controller return $this->expenseBudget($account, $start, $end); } + /** * @param Account $account * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function expenseCategory(Account $account, Carbon $start, Carbon $end) + public function expenseCategory(Account $account, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty($account->id); @@ -203,9 +207,9 @@ class AccountController extends Controller * @param AccountRepositoryInterface $repository * @param Account $account * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function expenseCategoryAll(AccountRepositoryInterface $repository, Account $account) + public function expenseCategoryAll(AccountRepositoryInterface $repository, Account $account): JsonResponse { $start = $repository->oldestJournalDate($account); $end = Carbon::now(); @@ -213,20 +217,23 @@ class AccountController extends Controller return $this->expenseCategory($account, $start, $end); } + /** * Shows the balances for all the user's frontpage accounts. * * @param AccountRepositoryInterface $repository * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function frontpage(AccountRepositoryInterface $repository) + public function frontpage(AccountRepositoryInterface $repository): JsonResponse { $start = clone session('start', Carbon::now()->startOfMonth()); $end = clone session('end', Carbon::now()->endOfMonth()); $defaultSet = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray(); Log::debug('Default set is ', $defaultSet); $frontPage = Preferences::get('frontPageAccounts', $defaultSet); + + Log::debug('Frontpage preference set is ', $frontPage->data); if (0 === \count($frontPage->data)) { $frontPage->data = $defaultSet; @@ -238,14 +245,15 @@ class AccountController extends Controller return response()->json($this->accountBalanceChart($accounts, $start, $end)); } + /** * @param Account $account * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function incomeCategory(Account $account, Carbon $start, Carbon $end) + public function incomeCategory(Account $account, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty($account->id); @@ -285,9 +293,9 @@ class AccountController extends Controller * @param AccountRepositoryInterface $repository * @param Account $account * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function incomeCategoryAll(AccountRepositoryInterface $repository, Account $account) + public function incomeCategoryAll(AccountRepositoryInterface $repository, Account $account): JsonResponse { $start = $repository->oldestJournalDate($account); $end = Carbon::now(); @@ -295,15 +303,16 @@ class AccountController extends Controller return $this->incomeCategory($account, $start, $end); } + /** * @param Account $account * @param Carbon $start * * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function period(Account $account, Carbon $start, Carbon $end) + public function period(Account $account, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty('chart.account.period'); @@ -367,21 +376,22 @@ class AccountController extends Controller * @param Carbon $end * @param Collection $accounts * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function report(Collection $accounts, Carbon $start, Carbon $end) + public function report(Collection $accounts, Carbon $start, Carbon $end): JsonResponse { return response()->json($this->accountBalanceChart($accounts, $start, $end)); } + /** * Shows the balances for all the user's revenue accounts. * * @param AccountRepositoryInterface $repository * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function revenueAccounts(AccountRepositoryInterface $repository) + public function revenueAccounts(AccountRepositoryInterface $repository): JsonResponse { $start = clone session('start', Carbon::now()->startOfMonth()); $end = clone session('end', Carbon::now()->endOfMonth()); @@ -417,6 +427,7 @@ class AccountController extends Controller return response()->json($data); } + /** * @param Collection $accounts * @param Carbon $start diff --git a/app/Http/Controllers/Chart/BillController.php b/app/Http/Controllers/Chart/BillController.php index b145249092..4a9a3bf3b1 100644 --- a/app/Http/Controllers/Chart/BillController.php +++ b/app/Http/Controllers/Chart/BillController.php @@ -30,6 +30,7 @@ use FireflyIII\Models\Bill; use FireflyIII\Models\Transaction; use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; /** @@ -49,14 +50,15 @@ class BillController extends Controller $this->generator = app(GeneratorInterface::class); } + /** * Shows all bills and whether or not they've been paid this month (pie chart). * * @param BillRepositoryInterface $repository * - * @return \Symfony\Component\HttpFoundation\Response + * @return JsonResponse */ - public function frontpage(BillRepositoryInterface $repository) + public function frontpage(BillRepositoryInterface $repository): JsonResponse { $start = session('start', Carbon::now()->startOfMonth()); $end = session('end', Carbon::now()->endOfMonth()); @@ -81,13 +83,14 @@ class BillController extends Controller return response()->json($data); } + /** * @param JournalCollectorInterface $collector * @param Bill $bill * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function single(JournalCollectorInterface $collector, Bill $bill) + public function single(JournalCollectorInterface $collector, Bill $bill): JsonResponse { $cache = new CacheProperties; $cache->addProperty('chart.bill.single'); diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php index 379c4efa8a..d954ab92b0 100644 --- a/app/Http/Controllers/Chart/BudgetController.php +++ b/app/Http/Controllers/Chart/BudgetController.php @@ -36,13 +36,12 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; -use Steam; /** * Class BudgetController. * - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) // can't realy be helped. */ class BudgetController extends Controller { @@ -69,12 +68,13 @@ class BudgetController extends Controller ); } + /** * @param Budget $budget * - * @return \Symfony\Component\HttpFoundation\Response + * @return JsonResponse */ - public function budget(Budget $budget) + public function budget(Budget $budget): JsonResponse { $start = $this->repository->firstUseDate($budget); $end = session('end', new Carbon); @@ -106,8 +106,9 @@ class BudgetController extends Controller $current = app('navigation')->startOfPeriod($current, $step); while ($end >= $current) { + /** @var Carbon $currentEnd */ $currentEnd = app('navigation')->endOfPeriod($current, $step); - if ($step === '1Y') { + if ('1Y' === $step) { $currentEnd->subDay(); // @codeCoverageIgnore } $spent = $this->repository->spentInPeriod($budgetCollection, new Collection, $current, $currentEnd); @@ -124,19 +125,19 @@ class BudgetController extends Controller return response()->json($data); } + /** * Shows the amount left in a specific budget limit. * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five. * * @param Budget $budget * @param BudgetLimit $budgetLimit * - * @return \Symfony\Component\HttpFoundation\Response + * @return JsonResponse * * @throws FireflyException */ - public function budgetLimit(Budget $budget, BudgetLimit $budgetLimit) + public function budgetLimit(Budget $budget, BudgetLimit $budgetLimit): JsonResponse { if ($budgetLimit->budget->id !== $budget->id) { throw new FireflyException('This budget limit is not part of this budget.'); @@ -172,17 +173,19 @@ class BudgetController extends Controller return response()->json($data); } + /** * @param Budget $budget * @param BudgetLimit|null $budgetLimit * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function expenseAsset(Budget $budget, ?BudgetLimit $budgetLimit) + public function expenseAsset(Budget $budget, ?BudgetLimit $budgetLimit): JsonResponse { - $cache = new CacheProperties; + $budgetLimitId = null === $budgetLimit ? 0 : $budgetLimit->id; + $cache = new CacheProperties; $cache->addProperty($budget->id); - $cache->addProperty($budgetLimit->id ?? 0); + $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-asset'); if ($cache->has()) { return response()->json($cache->get()); // @codeCoverageIgnore @@ -191,7 +194,7 @@ class BudgetController extends Controller /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAllAssetAccounts()->setBudget($budget); - if (null !== $budgetLimit->id) { + if (null !== $budgetLimit) { $collector->setRange($budgetLimit->start_date, $budgetLimit->end_date); } @@ -216,17 +219,19 @@ class BudgetController extends Controller return response()->json($data); } + /** * @param Budget $budget * @param BudgetLimit|null $budgetLimit * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function expenseCategory(Budget $budget, ?BudgetLimit $budgetLimit) + public function expenseCategory(Budget $budget, ?BudgetLimit $budgetLimit): JsonResponse { - $cache = new CacheProperties; + $budgetLimitId = null === $budgetLimit ? 0 : $budgetLimit->id; + $cache = new CacheProperties; $cache->addProperty($budget->id); - $cache->addProperty($budgetLimit->id ?? 0); + $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-category'); if ($cache->has()) { return response()->json($cache->get()); // @codeCoverageIgnore @@ -235,7 +240,7 @@ class BudgetController extends Controller /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAllAssetAccounts()->setBudget($budget)->withCategoryInformation(); - if (null !== $budgetLimit->id) { + if (null !== $budgetLimit) { $collector->setRange($budgetLimit->start_date, $budgetLimit->end_date); } @@ -262,17 +267,19 @@ class BudgetController extends Controller return response()->json($data); } + /** * @param Budget $budget * @param BudgetLimit|null $budgetLimit * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function expenseExpense(Budget $budget, ?BudgetLimit $budgetLimit) + public function expenseExpense(Budget $budget, ?BudgetLimit $budgetLimit): JsonResponse { - $cache = new CacheProperties; + $budgetLimitId = null === $budgetLimit ? 0 : $budgetLimit->id; + $cache = new CacheProperties; $cache->addProperty($budget->id); - $cache->addProperty($budgetLimit->id ?? 0); + $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-expense'); if ($cache->has()) { return response()->json($cache->get()); // @codeCoverageIgnore @@ -281,7 +288,7 @@ class BudgetController extends Controller /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); $collector->setAllAssetAccounts()->setTypes([TransactionType::WITHDRAWAL])->setBudget($budget)->withOpposingAccount(); - if (null !== $budgetLimit->id) { + if (null !== $budgetLimit) { $collector->setRange($budgetLimit->start_date, $budgetLimit->end_date); } @@ -307,15 +314,13 @@ class BudgetController extends Controller return response()->json($data); } + /** * Shows a budget list with spent/left/overspent. * - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five. - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) // 46 lines, I'm fine with this. - * * @return \Symfony\Component\HttpFoundation\Response */ - public function frontpage() + public function frontpage(): \Symfony\Component\HttpFoundation\Response { $start = session('start', Carbon::now()->startOfMonth()); $end = session('end', Carbon::now()->endOfMonth()); @@ -361,17 +366,17 @@ class BudgetController extends Controller return response()->json($data); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five. * * @param Budget $budget * @param Carbon $start * @param Carbon $end * @param Collection $accounts * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function period(Budget $budget, Collection $accounts, Carbon $start, Carbon $end) + public function period(Budget $budget, Collection $accounts, Carbon $start, Carbon $end): JsonResponse { // chart properties for cache: $cache = new CacheProperties(); @@ -406,14 +411,15 @@ class BudgetController extends Controller return response()->json($data); } + /** * @param Collection $accounts * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function periodNoBudget(Collection $accounts, Carbon $start, Carbon $end) + public function periodNoBudget(Collection $accounts, Carbon $start, Carbon $end): JsonResponse { // chart properties for cache: $cache = new CacheProperties(); @@ -478,7 +484,9 @@ class BudgetController extends Controller $current = clone $start; $budgeted = []; while ($current < $end) { - $currentStart = app('navigation')->startOfPeriod($current, $range); + /** @var Carbon $currentStart */ + $currentStart = app('navigation')->startOfPeriod($current, $range); + /** @var Carbon $currentEnd */ $currentEnd = app('navigation')->endOfPeriod($current, $range); $budgetLimits = $this->repository->getBudgetLimits($budget, $currentStart, $currentEnd); $index = $currentStart->format($key); @@ -514,8 +522,8 @@ class BudgetController extends Controller return $return; } + /** @noinspection MoreThanThreeArgumentsInspection */ /** - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's 6 but ok. * * @param Collection $limits * @param Budget $budget @@ -544,13 +552,12 @@ class BudgetController extends Controller $return[$name] = $row; } } - unset($rows, $row); + unset($rows); return $return; } /** - * @SuppressWarnings(PHPMD.CyclomaticComplexity) // it's exactly five. * * Returns an array with the following values: * 0 => @@ -573,7 +580,7 @@ class BudgetController extends Controller /** @var BudgetLimit $budgetLimit */ foreach ($limits as $budgetLimit) { $expenses = $this->repository->spentInPeriod(new Collection([$budget]), new Collection, $budgetLimit->start_date, $budgetLimit->end_date); - $expenses = Steam::positive($expenses); + $expenses = app('steam')->positive($expenses); if ($limits->count() > 1) { $name = $budget->name . ' ' . trans( @@ -595,7 +602,7 @@ class BudgetController extends Controller $left = $hasOverspent ? '0' : bcsub($amount, $expenses); $spent = $hasOverspent ? $amount : $expenses; - $overspent = $hasOverspent ? Steam::positive($leftInLimit) : '0'; + $overspent = $hasOverspent ? app('steam')->positive($leftInLimit) : '0'; $return[$name] = [ 'left' => $left, diff --git a/app/Http/Controllers/Chart/BudgetReportController.php b/app/Http/Controllers/Chart/BudgetReportController.php index 6f433c0ad2..8927ecf773 100644 --- a/app/Http/Controllers/Chart/BudgetReportController.php +++ b/app/Http/Controllers/Chart/BudgetReportController.php @@ -36,6 +36,7 @@ use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; /** @@ -66,6 +67,7 @@ class BudgetReportController extends Controller ); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $budgets @@ -73,9 +75,9 @@ class BudgetReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function accountExpense(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end, string $others) + public function accountExpense(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -90,6 +92,7 @@ class BudgetReportController extends Controller return response()->json($data); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $budgets @@ -97,9 +100,9 @@ class BudgetReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function budgetExpense(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end, string $others) + public function budgetExpense(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -114,15 +117,16 @@ class BudgetReportController extends Controller return response()->json($data); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $budgets * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function mainChart(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end) + public function mainChart(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty('chart.budget.report.main'); @@ -187,6 +191,7 @@ class BudgetReportController extends Controller $chartData[$budget->id . '-left']['entries'][$label] = $leftOfLimits[$budgetLimitId]; } } + /** @var Carbon $currentStart */ $currentStart = clone $currentEnd; $currentStart->addDay(); } @@ -197,6 +202,7 @@ class BudgetReportController extends Controller return response()->json($data); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * Returns the budget limits belonging to the given budget and valid on the given day. * @@ -225,6 +231,7 @@ class BudgetReportController extends Controller return $set; } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $budgets diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php index 130c482aea..3d016639c1 100644 --- a/app/Http/Controllers/Chart/CategoryController.php +++ b/app/Http/Controllers/Chart/CategoryController.php @@ -30,6 +30,7 @@ use FireflyIII\Models\Category; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; use Preferences; @@ -51,6 +52,7 @@ class CategoryController extends Controller $this->generator = app(GeneratorInterface::class); } + /** * Show an overview for a category for all time, per month/week/year. * @@ -58,9 +60,9 @@ class CategoryController extends Controller * @param AccountRepositoryInterface $accountRepository * @param Category $category * - * @return \Symfony\Component\HttpFoundation\Response + * @return JsonResponse */ - public function all(CategoryRepositoryInterface $repository, AccountRepositoryInterface $accountRepository, Category $category) + public function all(CategoryRepositoryInterface $repository, AccountRepositoryInterface $accountRepository, Category $category): JsonResponse { $cache = new CacheProperties; $cache->addProperty('chart.category.all'); @@ -116,13 +118,14 @@ class CategoryController extends Controller return response()->json($data); } + /** * @param CategoryRepositoryInterface $repository * @param AccountRepositoryInterface $accountRepository * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function frontpage(CategoryRepositoryInterface $repository, AccountRepositoryInterface $accountRepository) + public function frontpage(CategoryRepositoryInterface $repository, AccountRepositoryInterface $accountRepository): JsonResponse { $start = session('start', Carbon::now()->startOfMonth()); $end = session('end', Carbon::now()->endOfMonth()); @@ -156,16 +159,17 @@ class CategoryController extends Controller return response()->json($data); } + + /** @noinspection MoreThanThreeArgumentsInspection */ /** - * @param CategoryRepositoryInterface $repository - * @param Category $category - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Category $category + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse|mixed + * @return JsonResponse */ - public function reportPeriod(CategoryRepositoryInterface $repository, Category $category, Collection $accounts, Carbon $start, Carbon $end) + public function reportPeriod(Category $category, Collection $accounts, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty($start); @@ -176,10 +180,11 @@ class CategoryController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - $expenses = $repository->periodExpenses(new Collection([$category]), $accounts, $start, $end); - $income = $repository->periodIncome(new Collection([$category]), $accounts, $start, $end); - $periods = app('navigation')->listOfPeriods($start, $end); - $chartData = [ + $repository = app(CategoryRepositoryInterface::class); + $expenses = $repository->periodExpenses(new Collection([$category]), $accounts, $start, $end); + $income = $repository->periodIncome(new Collection([$category]), $accounts, $start, $end); + $periods = app('navigation')->listOfPeriods($start, $end); + $chartData = [ [ 'label' => (string)trans('firefly.spent'), 'entries' => [], @@ -214,15 +219,15 @@ class CategoryController extends Controller return response()->json($data); } + /** - * @param CategoryRepositoryInterface $repository - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse|mixed + * @return JsonResponse */ - public function reportPeriodNoCategory(CategoryRepositoryInterface $repository, Collection $accounts, Carbon $start, Carbon $end) + public function reportPeriodNoCategory(Collection $accounts, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty($start); @@ -232,10 +237,11 @@ class CategoryController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - $expenses = $repository->periodExpensesNoCategory($accounts, $start, $end); - $income = $repository->periodIncomeNoCategory($accounts, $start, $end); - $periods = app('navigation')->listOfPeriods($start, $end); - $chartData = [ + $repository = app(CategoryRepositoryInterface::class); + $expenses = $repository->periodExpensesNoCategory($accounts, $start, $end); + $income = $repository->periodIncomeNoCategory($accounts, $start, $end); + $periods = app('navigation')->listOfPeriods($start, $end); + $chartData = [ [ 'label' => (string)trans('firefly.spent'), 'entries' => [], @@ -270,31 +276,30 @@ class CategoryController extends Controller } /** - * @param CategoryRepositoryInterface $repository * @param Category $category * @param $date * - * @return \Symfony\Component\HttpFoundation\Response + * @return JsonResponse */ - public function specificPeriod(CategoryRepositoryInterface $repository, Category $category, Carbon $date) + public function specificPeriod(Category $category, Carbon $date): JsonResponse { $range = Preferences::get('viewRange', '1M')->data; $start = app('navigation')->startOfPeriod($date, $range); $end = app('navigation')->endOfPeriod($date, $range); - $data = $this->makePeriodChart($repository, $category, $start, $end); + $data = $this->makePeriodChart($category, $start, $end); return response()->json($data); } + /** - * @param CategoryRepositoryInterface $repository - * @param Category $category - * @param Carbon $start - * @param Carbon $end + * @param Category $category + * @param Carbon $start + * @param Carbon $end * * @return array */ - private function makePeriodChart(CategoryRepositoryInterface $repository, Category $category, Carbon $start, Carbon $end) + private function makePeriodChart(Category $category, Carbon $start, Carbon $end): array { $cache = new CacheProperties; $cache->addProperty($start); @@ -302,14 +307,16 @@ class CategoryController extends Controller $cache->addProperty($category->id); $cache->addProperty('chart.category.period-chart'); - /** @var AccountRepositoryInterface $accountRepository */ - $accountRepository = app(AccountRepositoryInterface::class); - $accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } + /** @var AccountRepositoryInterface $accountRepository */ + $accountRepository = app(AccountRepositoryInterface::class); + $accounts = $accountRepository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + $repository = app(CategoryRepositoryInterface::class); + // chart data $chartData = [ [ diff --git a/app/Http/Controllers/Chart/CategoryReportController.php b/app/Http/Controllers/Chart/CategoryReportController.php index 116fdce7d2..ea2d1f22ce 100644 --- a/app/Http/Controllers/Chart/CategoryReportController.php +++ b/app/Http/Controllers/Chart/CategoryReportController.php @@ -35,6 +35,7 @@ use FireflyIII\Models\Category; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; /** @@ -62,6 +63,7 @@ class CategoryReportController extends Controller ); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $categories @@ -69,9 +71,9 @@ class CategoryReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function accountExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others) + public function accountExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -83,6 +85,7 @@ class CategoryReportController extends Controller return response()->json($data); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $categories @@ -90,9 +93,9 @@ class CategoryReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function accountIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others) + public function accountIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -107,6 +110,7 @@ class CategoryReportController extends Controller return response()->json($data); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $categories @@ -114,9 +118,9 @@ class CategoryReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function categoryExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others) + public function categoryExpense(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -131,6 +135,7 @@ class CategoryReportController extends Controller return response()->json($data); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $categories @@ -138,9 +143,9 @@ class CategoryReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function categoryIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others) + public function categoryIncome(Collection $accounts, Collection $categories, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -155,15 +160,17 @@ class CategoryReportController extends Controller return response()->json($data); } + + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $categories * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function mainChart(Collection $accounts, Collection $categories, Carbon $start, Carbon $end) + public function mainChart(Collection $accounts, Collection $categories, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty('chart.category.report.main'); @@ -241,6 +248,7 @@ class CategoryReportController extends Controller $chartData[$labelSumIn]['entries'][$label] = $sumOfIncome[$category->id]; $chartData[$labelSumOut]['entries'][$label] = $sumOfExpense[$category->id]; } + /** @var Carbon $currentStart */ $currentStart = clone $currentEnd; $currentStart->addDay(); } @@ -260,6 +268,7 @@ class CategoryReportController extends Controller return response()->json($data); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $categories @@ -282,6 +291,7 @@ class CategoryReportController extends Controller return $collector->getJournals(); } + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Collection $accounts * @param Collection $categories diff --git a/app/Http/Controllers/Chart/ExpenseReportController.php b/app/Http/Controllers/Chart/ExpenseReportController.php index 3848afe95f..3bb7d264fc 100644 --- a/app/Http/Controllers/Chart/ExpenseReportController.php +++ b/app/Http/Controllers/Chart/ExpenseReportController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection MoreThanThreeArgumentsInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; @@ -32,6 +33,7 @@ use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; /** @@ -68,9 +70,9 @@ class ExpenseReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function mainChart(Collection $accounts, Collection $expense, Carbon $start, Carbon $end) + public function mainChart(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty('chart.expense.report.main'); @@ -163,6 +165,7 @@ class ExpenseReportController extends Controller $chartData[$labelSumIn]['entries'][$label] = $sumOfIncome[$exp->id]; $chartData[$labelSumOut]['entries'][$label] = $sumOfExpense[$exp->id]; } + /** @var Carbon $currentStart */ $currentStart = clone $currentEnd; $currentStart->addDay(); } diff --git a/app/Http/Controllers/Chart/PiggyBankController.php b/app/Http/Controllers/Chart/PiggyBankController.php index bf6d1df692..c023656ed6 100644 --- a/app/Http/Controllers/Chart/PiggyBankController.php +++ b/app/Http/Controllers/Chart/PiggyBankController.php @@ -29,6 +29,7 @@ use FireflyIII\Models\PiggyBank; use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; /** @@ -55,9 +56,9 @@ class PiggyBankController extends Controller * @param PiggyBankRepositoryInterface $repository * @param PiggyBank $piggyBank * - * @return \Symfony\Component\HttpFoundation\Response + * @return JsonResponse */ - public function history(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank) + public function history(PiggyBankRepositoryInterface $repository, PiggyBank $piggyBank): JsonResponse { // chart properties for cache: $cache = new CacheProperties; @@ -105,13 +106,13 @@ class PiggyBankController extends Controller $chartData[$label] = $currentSum; $oldest = app('navigation')->addPeriod($oldest, $step, 0); } - /** @var Collection $filtered */ + /** @var Collection $finalFiltered */ $finalFiltered = $set->filter( function (PiggyBankEvent $event) use ($today) { return $event->date->lte($today); } ); - $finalSum = $filtered->sum('amount'); + $finalSum = $finalFiltered->sum('amount'); $finalLabel = $today->formatLocalized((string)trans('config.month_and_day')); $chartData[$finalLabel] = $finalSum; diff --git a/app/Http/Controllers/Chart/ReportController.php b/app/Http/Controllers/Chart/ReportController.php index dfc8f77e1d..600fc46020 100644 --- a/app/Http/Controllers/Chart/ReportController.php +++ b/app/Http/Controllers/Chart/ReportController.php @@ -30,7 +30,6 @@ use FireflyIII\Support\CacheProperties; use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; use Log; -use Steam; /** * Class ReportController. @@ -74,7 +73,7 @@ class ReportController extends Controller $current = clone $start; $chartData = []; while ($current < $end) { - $balances = Steam::balancesByAccounts($accounts, $current); + $balances = app('steam')->balancesByAccounts($accounts, $current); $sum = $this->arraySum($balances); $label = $current->formatLocalized((string)trans('config.month_and_day')); $chartData[$label] = $sum; @@ -96,7 +95,7 @@ class ReportController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function operations(Collection $accounts, Carbon $start, Carbon $end) + public function operations(Collection $accounts, Carbon $start, Carbon $end): JsonResponse { // chart properties for cache: $cache = new CacheProperties; @@ -153,7 +152,7 @@ class ReportController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function sum(Collection $accounts, Carbon $start, Carbon $end) + public function sum(Collection $accounts, Carbon $start, Carbon $end): JsonResponse { // chart properties for cache: $cache = new CacheProperties; diff --git a/app/Http/Controllers/Chart/TagReportController.php b/app/Http/Controllers/Chart/TagReportController.php index 552aa239a1..8488049c85 100644 --- a/app/Http/Controllers/Chart/TagReportController.php +++ b/app/Http/Controllers/Chart/TagReportController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection MoreThanThreeArgumentsInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; @@ -35,6 +36,7 @@ use FireflyIII\Models\Tag; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionType; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; use Illuminate\Support\Collection; /** @@ -62,9 +64,9 @@ class TagReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function accountExpense(Collection $accounts, Collection $tags, Carbon $start, Carbon $end, string $others) + public function accountExpense(Collection $accounts, Collection $tags, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -86,9 +88,9 @@ class TagReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function accountIncome(Collection $accounts, Collection $tags, Carbon $start, Carbon $end, string $others) + public function accountIncome(Collection $accounts, Collection $tags, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -109,9 +111,9 @@ class TagReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function budgetExpense(Collection $accounts, Collection $tags, Carbon $start, Carbon $end) + public function budgetExpense(Collection $accounts, Collection $tags, Carbon $start, Carbon $end): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -132,9 +134,9 @@ class TagReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function categoryExpense(Collection $accounts, Collection $tags, Carbon $start, Carbon $end) + public function categoryExpense(Collection $accounts, Collection $tags, Carbon $start, Carbon $end): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -155,9 +157,9 @@ class TagReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function mainChart(Collection $accounts, Collection $tags, Carbon $start, Carbon $end) + public function mainChart(Collection $accounts, Collection $tags, Carbon $start, Carbon $end): JsonResponse { $cache = new CacheProperties; $cache->addProperty('chart.category.report.main'); @@ -235,6 +237,7 @@ class TagReportController extends Controller $chartData[$labelSumIn]['entries'][$label] = $sumOfIncome[$tag->id]; $chartData[$labelSumOut]['entries'][$label] = $sumOfExpense[$tag->id]; } + /** @var Carbon $currentStart */ $currentStart = clone $currentEnd; $currentStart->addDay(); } @@ -261,9 +264,9 @@ class TagReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function tagExpense(Collection $accounts, Collection $tags, Carbon $start, Carbon $end, string $others) + public function tagExpense(Collection $accounts, Collection $tags, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); @@ -285,9 +288,9 @@ class TagReportController extends Controller * @param Carbon $end * @param string $others * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function tagIncome(Collection $accounts, Collection $tags, Carbon $start, Carbon $end, string $others) + public function tagIncome(Collection $accounts, Collection $tags, Carbon $start, Carbon $end, string $others): JsonResponse { /** @var MetaPieChartInterface $helper */ $helper = app(MetaPieChartInterface::class); diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index d343926732..4cfd23cd0f 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -145,6 +145,7 @@ class Controller extends BaseController return TransactionType::OPENING_BALANCE === $journal->transactionType->type; } + /** * @param TransactionJournal $journal * @@ -157,7 +158,7 @@ class Controller extends BaseController /** @var Transaction $transaction */ foreach ($transactions as $transaction) { $account = $transaction->account; - if (\in_array($account->accountType->type, $valid)) { + if (\in_array($account->accountType->type, $valid, true)) { return redirect(route('accounts.show', [$account->id])); } } @@ -171,7 +172,7 @@ class Controller extends BaseController /** * @param string $identifier */ - protected function rememberPreviousUri(string $identifier) + protected function rememberPreviousUri(string $identifier): void { session()->put($identifier, URL::previous()); } diff --git a/app/Http/Controllers/CurrencyController.php b/app/Http/Controllers/CurrencyController.php index 67d62ea22f..7458016608 100644 --- a/app/Http/Controllers/CurrencyController.php +++ b/app/Http/Controllers/CurrencyController.php @@ -27,6 +27,7 @@ use FireflyIII\Http\Requests\CurrencyFormRequest; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\User; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; use Log; @@ -63,6 +64,7 @@ class CurrencyController extends Controller ); } + /** * @param Request $request * @@ -70,7 +72,9 @@ class CurrencyController extends Controller */ public function create(Request $request) { - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + /** @var User $user */ + $user = auth()->user(); + if (!$this->userRepository->hasRole($user, 'owner')) { $request->session()->flash('error', trans('firefly.ask_site_owner', ['owner' => env('SITE_OWNER')])); return redirect(route('currencies.index')); @@ -97,7 +101,7 @@ class CurrencyController extends Controller public function defaultCurrency(Request $request, TransactionCurrency $currency) { Preferences::set('currencyPreference', $currency->code); - Preferences::mark(); + app('preferences')->mark(); $request->session()->flash('success', trans('firefly.new_default_currency', ['name' => $currency->name])); Cache::forget('FFCURRENCYSYMBOL'); @@ -106,6 +110,7 @@ class CurrencyController extends Controller return redirect(route('currencies.index')); } + /** * @param Request $request * @param TransactionCurrency $currency @@ -114,7 +119,9 @@ class CurrencyController extends Controller */ public function delete(Request $request, TransactionCurrency $currency) { - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + /** @var User $user */ + $user = auth()->user(); + if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', trans('firefly.ask_site_owner', ['owner' => env('SITE_OWNER')])); @@ -135,6 +142,7 @@ class CurrencyController extends Controller return view('currencies.delete', compact('currency', 'subTitle')); } + /** * @param Request $request * @param TransactionCurrency $currency @@ -143,7 +151,9 @@ class CurrencyController extends Controller */ public function destroy(Request $request, TransactionCurrency $currency) { - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + /** @var User $user */ + $user = auth()->user(); + if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', trans('firefly.ask_site_owner', ['owner' => env('SITE_OWNER')])); @@ -163,6 +173,7 @@ class CurrencyController extends Controller return redirect($this->getPreviousUri('currencies.delete.uri')); } + /** * @param Request $request * @param TransactionCurrency $currency @@ -171,7 +182,9 @@ class CurrencyController extends Controller */ public function edit(Request $request, TransactionCurrency $currency) { - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + /** @var User $user */ + $user = auth()->user(); + if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', trans('firefly.ask_site_owner', ['owner' => env('SITE_OWNER')])); @@ -195,10 +208,12 @@ class CurrencyController extends Controller /** * @param Request $request * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(Request $request) { + /** @var User $user */ + $user = auth()->user(); $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); $pageSize = (int)Preferences::get('listPageSize', 50)->data; $collection = $this->repository->get(); @@ -214,7 +229,7 @@ class CurrencyController extends Controller $defaultCurrency = $this->repository->getCurrencyByPreference(Preferences::get('currencyPreference', config('firefly.default_currency', 'EUR'))); $isOwner = true; - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + if (!$this->userRepository->hasRole($user, 'owner')) { $request->session()->flash('info', trans('firefly.ask_site_owner', ['owner' => env('SITE_OWNER')])); $isOwner = false; } @@ -222,6 +237,7 @@ class CurrencyController extends Controller return view('currencies.index', compact('currencies', 'defaultCurrency', 'isOwner')); } + /** * @param CurrencyFormRequest $request * @@ -229,7 +245,9 @@ class CurrencyController extends Controller */ public function store(CurrencyFormRequest $request) { - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + /** @var User $user */ + $user = auth()->user(); + if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart Log::error('User ' . auth()->user()->id . ' is not admin, but tried to store a currency.'); @@ -239,19 +257,27 @@ class CurrencyController extends Controller $data = $request->getCurrencyData(); $currency = $this->repository->store($data); - $request->session()->flash('success', trans('firefly.created_currency', ['name' => $currency->name])); + $redirect = redirect($this->getPreviousUri('currencies.create.uri')); + if (null !== $currency) { + $request->session()->flash('success', trans('firefly.created_currency', ['name' => $currency->name])); - if (1 === (int)$request->get('create_another')) { - // @codeCoverageIgnoreStart - $request->session()->put('currencies.create.fromStore', true); + if (1 === (int)$request->get('create_another')) { + // @codeCoverageIgnoreStart + $request->session()->put('currencies.create.fromStore', true); + + $redirect = redirect(route('currencies.create'))->withInput(); + // @codeCoverageIgnoreEnd + } + } + if (null === $currency) { + $request->session()->flash('error', trans('firefly.could_not_store_currency')); - return redirect(route('currencies.create'))->withInput(); - // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('currencies.create.uri')); + return $redirect; } + /** * @param CurrencyFormRequest $request * @param TransactionCurrency $currency @@ -260,7 +286,9 @@ class CurrencyController extends Controller */ public function update(CurrencyFormRequest $request, TransactionCurrency $currency) { - if (!$this->userRepository->hasRole(auth()->user(), 'owner')) { + /** @var User $user */ + $user = auth()->user(); + if (!$this->userRepository->hasRole($user, 'owner')) { // @codeCoverageIgnoreStart $request->session()->flash('error', trans('firefly.ask_site_owner', ['owner' => env('SITE_OWNER')])); @@ -271,7 +299,7 @@ class CurrencyController extends Controller $data = $request->getCurrencyData(); $currency = $this->repository->update($currency, $data); $request->session()->flash('success', trans('firefly.updated_currency', ['name' => $currency->name])); - Preferences::mark(); + app('preferences')->mark(); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart diff --git a/app/Http/Controllers/DebugController.php b/app/Http/Controllers/DebugController.php index 1caf4925df..dbdad0512d 100644 --- a/app/Http/Controllers/DebugController.php +++ b/app/Http/Controllers/DebugController.php @@ -33,7 +33,6 @@ use Illuminate\Http\Request; use Illuminate\Routing\Route; use Log; use Monolog\Handler\RotatingFileHandler; -use Preferences; use Route as RouteFacade; /** @@ -53,7 +52,7 @@ class DebugController extends Controller /** * @throws FireflyException */ - public function displayError() + public function displayError(): void { Log::debug('This is a test message at the DEBUG level.'); Log::info('This is a test message at the INFO level.'); @@ -73,7 +72,7 @@ class DebugController extends Controller */ public function flush(Request $request) { - Preferences::mark(); + app('preferences')->mark(); $request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range']); Log::debug('Call cache:clear...'); Artisan::call('cache:clear'); @@ -87,7 +86,7 @@ class DebugController extends Controller // @codeCoverageIgnoreStart } catch (Exception $e) { // don't care - Log::debug('Called twig:clean.'); + Log::debug(sprintf('Called twig:clean: %s', $e->getMessage())); } // @codeCoverageIgnoreEnd Log::debug('Call view:clear...'); @@ -202,7 +201,7 @@ class DebugController extends Controller break; } } - if ($found === false) { + if (false === $found) { $return .= 'touch ' . $route->getName() . '.md;'; } } @@ -235,7 +234,7 @@ class DebugController extends Controller */ protected function errorReporting(int $value): string { - $array = [ + $array = [ -1 => 'ALL errors', E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED => 'E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED', E_ALL => 'E_ALL', @@ -244,11 +243,12 @@ class DebugController extends Controller E_ALL & ~E_NOTICE & ~E_STRICT => 'E_ALL & ~E_NOTICE & ~E_STRICT', E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR => 'E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR', ]; + $result = (string)$value; if (isset($array[$value])) { - return $array[$value]; + $result = $array[$value]; } - return (string)$value; // @codeCoverageIgnore + return $result; } /** @@ -258,7 +258,7 @@ class DebugController extends Controller { $packages = []; $file = \dirname(__DIR__, 3) . '/vendor/composer/installed.json'; - if (!($file === false) && file_exists($file)) { + if (!(false === $file) && file_exists($file)) { // file exists! $content = file_get_contents($file); $json = json_decode($content, true); diff --git a/app/Http/Controllers/ExportController.php b/app/Http/Controllers/ExportController.php index a6836ba004..34102365bb 100644 --- a/app/Http/Controllers/ExportController.php +++ b/app/Http/Controllers/ExportController.php @@ -30,9 +30,9 @@ use FireflyIII\Http\Requests\ExportFormRequest; use FireflyIII\Models\ExportJob; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\ExportJob\ExportJobRepositoryInterface; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Response as LaravelResponse; use Preferences; -use View; /** * Class ExportController. @@ -99,7 +99,7 @@ class ExportController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function getStatus(ExportJob $job) + public function getStatus(ExportJob $job): JsonResponse { return response()->json(['status' => trans('firefly.' . $job->status)]); } @@ -107,7 +107,7 @@ class ExportController extends Controller /** * @param ExportJobRepositoryInterface $jobs * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(ExportJobRepositoryInterface $jobs) { @@ -130,9 +130,9 @@ class ExportController extends Controller * @param AccountRepositoryInterface $repository * @param ExportJobRepositoryInterface $jobs * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function postIndex(ExportFormRequest $request, AccountRepositoryInterface $repository, ExportJobRepositoryInterface $jobs) + public function postIndex(ExportFormRequest $request, AccountRepositoryInterface $repository, ExportJobRepositoryInterface $jobs): JsonResponse { $job = $jobs->findByKey($request->get('job')); $accounts = $request->get('accounts') ?? []; diff --git a/app/Http/Controllers/HelpController.php b/app/Http/Controllers/HelpController.php index a4fcf0a520..b472f8ea9d 100644 --- a/app/Http/Controllers/HelpController.php +++ b/app/Http/Controllers/HelpController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; use FireflyIII\Helpers\Help\HelpInterface; +use Illuminate\Http\JsonResponse; use Log; use Preferences; @@ -53,9 +54,9 @@ class HelpController extends Controller /** * @param $route * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function show(string $route) + public function show(string $route): JsonResponse { $language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data; $html = $this->getHelpText($route, $language); @@ -90,10 +91,10 @@ class HelpController extends Controller } // get help content from Github: - $content = $this->help->getFromGithub($route, $language); + $content = $this->help->getFromGitHub($route, $language); // content will have 0 length when Github failed. Try en_US when it does: - if (0 === \strlen($content)) { + if ('' === $content) { $language = 'en_US'; // also check cache first: @@ -104,11 +105,11 @@ class HelpController extends Controller return $content; } - $content = $this->help->getFromGithub($route, $language); + $content = $this->help->getFromGitHub($route, $language); } // help still empty? - if (0 !== \strlen($content)) { + if ('' !== $content) { $this->help->putInCache($route, $language, $content); return $content; diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 6dc45a198d..2c67ce8520 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -31,6 +31,8 @@ use FireflyIII\Http\Middleware\IsSandStormUser; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Collection; use Log; @@ -59,9 +61,9 @@ class HomeController extends Controller /** * @param Request $request * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function dateRange(Request $request) + public function dateRange(Request $request): JsonResponse { $start = new Carbon($request->get('start')); $end = new Carbon($request->get('end')); @@ -116,7 +118,8 @@ class HomeController extends Controller /** @var Carbon $start */ $start = session('start', Carbon::now()->startOfMonth()); /** @var Carbon $end */ - $end = session('end', Carbon::now()->endOfMonth()); + $end = session('end', Carbon::now()->endOfMonth()); + /** @noinspection NullPointerExceptionInspection */ $accounts = $repository->getAccountsById($frontPage->data); $today = new Carbon; @@ -133,7 +136,9 @@ class HomeController extends Controller } // fire check update event: - event(new RequestedVersionCheckStatus(auth()->user())); + /** @var User $user */ + $user = auth()->user(); + event(new RequestedVersionCheckStatus($user)); return view( 'index', diff --git a/app/Http/Controllers/Import/IndexController.php b/app/Http/Controllers/Import/IndexController.php index 72c422caad..21a41c2a7d 100644 --- a/app/Http/Controllers/Import/IndexController.php +++ b/app/Http/Controllers/Import/IndexController.php @@ -28,9 +28,9 @@ use FireflyIII\Import\Prerequisites\PrerequisitesInterface; use FireflyIII\Models\ImportJob; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\User; use Illuminate\Http\Response as LaravelResponse; use Log; -use View; /** * Class FileController. @@ -89,10 +89,10 @@ class IndexController extends Controller $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 ($hasPreReq === false) { + if (false === $hasPreReq) { Log::debug('Provider has no prerequisites. Continue.'); // if job provider also has no configuration: - if ($hasConfig === false) { + if (false === $hasConfig) { // @codeCoverageIgnoreStart Log::debug('Provider needs no configuration for job. Job is ready to start.'); $this->repository->updateStatus($importJob, 'ready_to_run'); @@ -118,7 +118,7 @@ class IndexController extends Controller } /** @var PrerequisitesInterface $providerPre */ $providerPre = app($class); - $providerPre->setUser(auth()->user()); + $providerPre->setUser($importJob->user); if (!$providerPre->isComplete()) { Log::debug('Job provider prerequisites are not yet filled in. Redirect to prerequisites-page.'); @@ -130,7 +130,7 @@ class IndexController extends Controller // update job to say "has_prereq". $this->repository->setStatus($importJob, 'has_prereq'); - if ($hasConfig === false) { + if (false === $hasConfig) { // @codeCoverageIgnoreStart Log::debug('Provider has no configuration. Job is ready to start.'); $this->repository->updateStatus($importJob, 'ready_to_run'); @@ -180,7 +180,7 @@ class IndexController extends Controller /** * General import index. * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index() { @@ -197,10 +197,12 @@ class IndexController extends Controller 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(auth()->user(), 'demo'); + $isDemoUser = $this->userRepository->hasRole($user, 'demo'); $isDebug = (bool)config('app.debug'); foreach ($providerNames as $providerName) { //Log::debug(sprintf('Now with provider %s', $providerName)); @@ -208,16 +210,16 @@ class IndexController extends Controller $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 ($enabled === false) { + if (false === $enabled) { //Log::debug('Provider is not enabled. NEXT!'); continue; } - if ($isDemoUser === true && $allowedForDemo === false) { + if (true === $isDemoUser && false === $allowedForDemo) { //Log::debug('User is demo and this provider is not allowed for demo user. NEXT!'); continue; } - if ($isDemoUser === false && $allowedForUser === false && $isDebug === false) { + 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 } @@ -227,11 +229,11 @@ class IndexController extends Controller ]; $class = (string)config(sprintf('import.prerequisites.%s', $providerName)); $result = false; - if ($class !== '' && class_exists($class)) { + if ('' !== $class && class_exists($class)) { //Log::debug('Will not check prerequisites.'); /** @var PrerequisitesInterface $object */ $object = app($class); - $object->setUser(auth()->user()); + $object->setUser($user); $result = $object->isComplete(); } $providers[$providerName]['prereq_complete'] = $result; diff --git a/app/Http/Controllers/Import/JobStatusController.php b/app/Http/Controllers/Import/JobStatusController.php index 8a9ce1d851..8cae35eb92 100644 --- a/app/Http/Controllers/Import/JobStatusController.php +++ b/app/Http/Controllers/Import/JobStatusController.php @@ -90,7 +90,7 @@ class JobStatusController extends Controller 'download_config_text' => '', ]; - if ($importJob->provider === 'file') { + if ('file' === $importJob->provider) { $json['download_config'] = true; $json['download_config_text'] = trans('import.should_download_config', ['route' => route('import.job.download', [$importJob->key])]) . ' ' @@ -101,10 +101,10 @@ class JobStatusController extends Controller if (null !== $importJob->tag_id) { $count = $importJob->tag->transactionJournals->count(); } - if ($count === 0) { + if (0 === $count) { $json['report_txt'] = trans('import.result_no_transactions'); } - if ($count === 1 && null !== $importJob->tag_id) { + if (1 === $count && null !== $importJob->tag_id) { $json['report_txt'] = trans( 'import.result_one_transaction', ['route' => route('tags.show', [$importJob->tag_id, 'all']), 'tag' => $importJob->tag->tag] ); diff --git a/app/Http/Controllers/Import/PrerequisitesController.php b/app/Http/Controllers/Import/PrerequisitesController.php index d0e4d5bbd6..8b37e1178b 100644 --- a/app/Http/Controllers/Import/PrerequisitesController.php +++ b/app/Http/Controllers/Import/PrerequisitesController.php @@ -27,6 +27,7 @@ use FireflyIII\Http\Controllers\Controller; use FireflyIII\Import\Prerequisites\PrerequisitesInterface; use FireflyIII\Models\ImportJob; use FireflyIII\Repositories\ImportJob\ImportJobRepositoryInterface; +use FireflyIII\User; use Illuminate\Http\Request; use Log; @@ -73,7 +74,7 @@ class PrerequisitesController extends Controller { // catch impossible status: $allowed = ['new']; - if (null !== $importJob && !in_array($importJob->status, $allowed)) { + if (null !== $importJob && !\in_array($importJob->status, $allowed, true)) { Log::error(sprintf('Job has state "%s" but this Prerequisites::index() only accepts %s', $importJob->status, json_encode($allowed))); session()->flash('error', trans('import.bad_job_status', ['status' => $importJob->status])); @@ -85,9 +86,11 @@ class PrerequisitesController extends Controller 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 */ $object = app($class); - $object->setUser(auth()->user()); + $object->setUser($user); if (null !== $importJob && $object->isComplete()) { // update job: @@ -139,9 +142,11 @@ class PrerequisitesController extends Controller if (!class_exists($class)) { throw new FireflyException(sprintf('Cannot find class %s', $class)); // @codeCoverageIgnore } + /** @var User $user */ + $user = auth()->user(); /** @var PrerequisitesInterface $object */ $object = app($class); - $object->setUser(auth()->user()); + $object->setUser($user); Log::debug('Going to store entered prerequisites.'); // store post data $data = $request->all(); diff --git a/app/Http/Controllers/JavascriptController.php b/app/Http/Controllers/JavascriptController.php index 0ebb2d5192..cc63fdab0c 100644 --- a/app/Http/Controllers/JavascriptController.php +++ b/app/Http/Controllers/JavascriptController.php @@ -44,18 +44,20 @@ class JavascriptController extends Controller * * @return \Illuminate\Http\Response */ - public function accounts(AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository) + public function accounts(AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository): Response { $accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); $preference = Preferences::get('currencyPreference', config('firefly.default_currency', 'EUR')); - $default = $currencyRepository->findByCodeNull($preference->data); + /** @noinspection NullPointerExceptionInspection */ + $default = $currencyRepository->findByCodeNull($preference->data); $data = ['accounts' => []]; /** @var Account $account */ foreach ($accounts as $account) { - $accountId = $account->id; - $currency = (int)$repository->getMetaValue($account, 'currency_id'); + $accountId = $account->id; + $currency = (int)$repository->getMetaValue($account, 'currency_id'); + /** @noinspection NullPointerExceptionInspection */ $currency = 0 === $currency ? $default->id : $currency; $entry = ['preferredCurrency' => $currency, 'name' => $account->name]; $data['accounts'][$accountId] = $entry; @@ -94,7 +96,7 @@ class JavascriptController extends Controller * * @return \Illuminate\Http\Response */ - public function variables(Request $request, AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository) + public function variables(Request $request, AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository): Response { $account = $repository->findNull((int)$request->get('account')); $currencyId = 0; @@ -113,8 +115,9 @@ class JavascriptController extends Controller $localeconv = localeconv(); $localeconv['frac_digits'] = $currency->decimal_places; $pref = Preferences::get('language', config('firefly.default_language', 'en_US')); - $lang = $pref->data; - $dateRange = $this->getDateRangeConfig(); + /** @noinspection NullPointerExceptionInspection */ + $lang = $pref->data; + $dateRange = $this->getDateRangeConfig(); $data = [ 'currencyCode' => $currency->code, @@ -173,8 +176,10 @@ class JavascriptController extends Controller $ranges[$index] = [$nextStart, $nextEnd]; // today: + /** @var Carbon $todayStart */ $todayStart = app('navigation')->startOfPeriod($today, $viewRange); - $todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange); + /** @var Carbon $todayEnd */ + $todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange); if ($todayStart->ne($start) || $todayEnd->ne($end)) { $ranges[ucfirst((string)trans('firefly.today'))] = [$todayStart, $todayEnd]; } diff --git a/app/Http/Controllers/Json/AutoCompleteController.php b/app/Http/Controllers/Json/AutoCompleteController.php index 6ff6c92e1d..9472195946 100644 --- a/app/Http/Controllers/Json/AutoCompleteController.php +++ b/app/Http/Controllers/Json/AutoCompleteController.php @@ -50,7 +50,7 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function allAccounts(AccountRepositoryInterface $repository) + public function allAccounts(AccountRepositoryInterface $repository): JsonResponse { $return = array_unique( $repository->getAccountsByType( @@ -98,7 +98,7 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function budgets(BudgetRepositoryInterface $repository) + public function budgets(BudgetRepositoryInterface $repository): JsonResponse { $return = array_unique($repository->getBudgets()->pluck('name')->toArray()); sort($return); @@ -113,7 +113,7 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function categories(CategoryRepositoryInterface $repository) + public function categories(CategoryRepositoryInterface $repository): JsonResponse { $return = array_unique($repository->getCategories()->pluck('name')->toArray()); sort($return); @@ -126,7 +126,7 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function currencyNames(CurrencyRepositoryInterface $repository) + public function currencyNames(CurrencyRepositoryInterface $repository): JsonResponse { $return = $repository->get()->pluck('name')->toArray(); sort($return); @@ -141,12 +141,12 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function expenseAccounts(AccountRepositoryInterface $repository) + public function expenseAccounts(AccountRepositoryInterface $repository): JsonResponse { $set = $repository->getAccountsByType([AccountType::EXPENSE, AccountType::BENEFICIARY]); $filtered = $set->filter( function (Account $account) { - if ($account->active === true) { + if (true === $account->active) { return $account; } @@ -160,6 +160,7 @@ class AutoCompleteController extends Controller return response()->json($return); } + /** * @param JournalCollectorInterface $collector * @param TransactionJournal $except @@ -198,12 +199,12 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function revenueAccounts(AccountRepositoryInterface $repository) + public function revenueAccounts(AccountRepositoryInterface $repository): JsonResponse { $set = $repository->getAccountsByType([AccountType::REVENUE]); $filtered = $set->filter( function (Account $account) { - if ($account->active === true) { + if (true === $account->active) { return $account; } @@ -223,7 +224,7 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function tags(TagRepositoryInterface $tagRepository) + public function tags(TagRepositoryInterface $tagRepository): JsonResponse { $return = array_unique($tagRepository->get()->pluck('tag')->toArray()); sort($return); @@ -237,7 +238,7 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function transactionJournals(JournalCollectorInterface $collector, string $what) + public function transactionJournals(JournalCollectorInterface $collector, string $what): JsonResponse { $type = config('firefly.transactionTypesByWhat.' . $what); $types = [$type]; @@ -254,7 +255,7 @@ class AutoCompleteController extends Controller * * @return JsonResponse */ - public function transactionTypes(JournalRepositoryInterface $repository) + public function transactionTypes(JournalRepositoryInterface $repository): JsonResponse { $return = array_unique($repository->getTransactionTypes()->pluck('type')->toArray()); sort($return); diff --git a/app/Http/Controllers/Json/BoxController.php b/app/Http/Controllers/Json/BoxController.php index e61c522daf..50302790a9 100644 --- a/app/Http/Controllers/Json/BoxController.php +++ b/app/Http/Controllers/Json/BoxController.php @@ -35,18 +35,20 @@ use FireflyIII\Repositories\Bill\BillRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\JsonResponse; /** * Class BoxController. */ class BoxController extends Controller { + /** * @param BudgetRepositoryInterface $repository * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function available(BudgetRepositoryInterface $repository) + public function available(BudgetRepositoryInterface $repository): JsonResponse { $start = session('start', Carbon::now()->startOfMonth()); $end = session('end', Carbon::now()->endOfMonth()); @@ -92,12 +94,13 @@ class BoxController extends Controller return response()->json($return); } + /** * @param CurrencyRepositoryInterface $repository * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function balance(CurrencyRepositoryInterface $repository) + public function balance(CurrencyRepositoryInterface $repository): JsonResponse { // Cache result, return cache if present. $start = session('start', Carbon::now()->startOfMonth()); @@ -153,7 +156,7 @@ class BoxController extends Controller $incomes[$currencyId] = Amount::formatAnything($currency, $incomes[$currencyId] ?? '0', false); $expenses[$currencyId] = Amount::formatAnything($currency, $expenses[$currencyId] ?? '0', false); } - if (\count($sums) === 0) { + if (0 === \count($sums)) { $currency = app('amount')->getDefaultCurrency(); $sums[$currency->id] = Amount::formatAnything($currency, '0', false); $incomes[$currency->id] = Amount::formatAnything($currency, '0', false); @@ -173,12 +176,13 @@ class BoxController extends Controller return response()->json($response); } + /** * @param BillRepositoryInterface $repository * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function bills(BillRepositoryInterface $repository) + public function bills(BillRepositoryInterface $repository): JsonResponse { $start = session('start', Carbon::now()->startOfMonth()); $end = session('end', Carbon::now()->endOfMonth()); @@ -208,14 +212,15 @@ class BoxController extends Controller return response()->json($return); } + /** * @param AccountRepositoryInterface $repository * * @param CurrencyRepositoryInterface $currencyRepos * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function netWorth(AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepos) + public function netWorth(AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepos): JsonResponse { $date = new Carbon(date('Y-m-d')); // needed so its per day. /** @var Carbon $start */ @@ -248,7 +253,7 @@ class BoxController extends Controller $accountCurrency = null; $balance = $balances[$account->id] ?? '0'; $currencyId = (int)$repository->getMetaValue($account, 'currency_id'); - if ($currencyId !== 0) { + if (0 !== $currencyId) { $accountCurrency = $currencyRepos->findNull($currencyId); } if (null === $accountCurrency) { @@ -259,7 +264,7 @@ class BoxController extends Controller // to better reflect that this is not money that is actually "yours". $role = (string)$repository->getMetaValue($account, 'accountRole'); $virtualBalance = (string)$account->virtual_balance; - if ($role === 'ccAsset' && $virtualBalance !== '' && (float)$virtualBalance > 0) { + if ('ccAsset' === $role && '' !== $virtualBalance && (float)$virtualBalance > 0) { $balance = bcsub($balance, $virtualBalance); } diff --git a/app/Http/Controllers/Json/ExchangeController.php b/app/Http/Controllers/Json/ExchangeController.php index 34b8eeddd6..85e3b510ca 100644 --- a/app/Http/Controllers/Json/ExchangeController.php +++ b/app/Http/Controllers/Json/ExchangeController.php @@ -27,6 +27,8 @@ use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Services\Currency\ExchangeRateInterface; +use FireflyIII\User; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; @@ -35,15 +37,16 @@ use Log; */ class ExchangeController extends Controller { + /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Request $request * @param TransactionCurrency $fromCurrency * @param TransactionCurrency $toCurrency * @param Carbon $date * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function getRate(Request $request, TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date) + public function getRate(Request $request, TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date): JsonResponse { /** @var CurrencyRepositoryInterface $repository */ $repository = app(CurrencyRepositoryInterface::class); @@ -54,9 +57,11 @@ class ExchangeController extends Controller Log::debug(sprintf('No cached exchange rate in database for %s to %s on %s', $fromCurrency->code, $toCurrency->code, $date->format('Y-m-d'))); // create service: + /** @var User $user */ + $user = auth()->user(); /** @var ExchangeRateInterface $service */ $service = app(ExchangeRateInterface::class); - $service->setUser(auth()->user()); + $service->setUser($user); // get rate: $rate = $service->getRate($fromCurrency, $toCurrency, $date); diff --git a/app/Http/Controllers/Json/FrontpageController.php b/app/Http/Controllers/Json/FrontpageController.php index 422d2b4e75..c7bf29ec73 100644 --- a/app/Http/Controllers/Json/FrontpageController.php +++ b/app/Http/Controllers/Json/FrontpageController.php @@ -25,6 +25,7 @@ namespace FireflyIII\Http\Controllers\Json; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\PiggyBank; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; +use Illuminate\Http\JsonResponse; /** * Class FrontpageController. @@ -34,10 +35,10 @@ class FrontpageController extends Controller /** * @param PiggyBankRepositoryInterface $repository * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse * @throws \Throwable */ - public function piggyBanks(PiggyBankRepositoryInterface $repository) + public function piggyBanks(PiggyBankRepositoryInterface $repository): JsonResponse { $set = $repository->getPiggyBanks(); $info = []; diff --git a/app/Http/Controllers/Json/IntroController.php b/app/Http/Controllers/Json/IntroController.php index be974afb74..31ab70d523 100644 --- a/app/Http/Controllers/Json/IntroController.php +++ b/app/Http/Controllers/Json/IntroController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Json; use FireflyIII\Support\Facades\Preferences; +use Illuminate\Http\JsonResponse; use Log; /** @@ -31,16 +32,15 @@ use Log; class IntroController { /** - * Get the intro steps. There are currently no specific routes with an outro step. + * @param string $route + * @param string|null $specificPage * - * @param string $route - * @param string $specificPage - * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function getIntroSteps(string $route, string $specificPage = '') + public function getIntroSteps(string $route, string $specificPage = null): JsonResponse { Log::debug(sprintf('getIntroSteps for route "%s" and page "%s"', $route, $specificPage)); + $specificPage = $specificPage ?? ''; $steps = $this->getBasicSteps($route); $specificSteps = $this->getSpecificSteps($route, $specificPage); if (0 === \count($specificSteps)) { @@ -90,15 +90,16 @@ class IntroController } /** - * @param string $route - * @param string $specialPage + * @param string $route + * @param string|null $specialPage * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function postEnable(string $route, string $specialPage = '') + public function postEnable(string $route, string $specialPage = null): JsonResponse { - $route = str_replace('.', '_', $route); - $key = 'shown_demo_' . $route; + $specialPage = $specialPage ?? ''; + $route = str_replace('.', '_', $route); + $key = 'shown_demo_' . $route; if ('' !== $specialPage) { $key .= '_' . $specialPage; } @@ -109,14 +110,15 @@ class IntroController } /** - * @param string $route - * @param string $specialPage + * @param string $route + * @param string|null $specialPage * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse */ - public function postFinished(string $route, string $specialPage = '') + public function postFinished(string $route, string $specialPage = null): JsonResponse { - $key = 'shown_demo_' . $route; + $specialPage = $specialPage ?? ''; + $key = 'shown_demo_' . $route; if ('' !== $specialPage) { $key .= '_' . $specialPage; } diff --git a/app/Http/Controllers/Json/ReconcileController.php b/app/Http/Controllers/Json/ReconcileController.php new file mode 100644 index 0000000000..cfea152bea --- /dev/null +++ b/app/Http/Controllers/Json/ReconcileController.php @@ -0,0 +1,207 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers\Json; + + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Helpers\Collector\JournalCollectorInterface; +use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Transaction; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use FireflyIII\Services\Internal\Update\CurrencyUpdateService; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; +use Illuminate\Support\Collection; + +/** + * + * Class ReconcileController + */ +class ReconcileController extends Controller +{ + + /** @var CurrencyUpdateService */ + private $accountRepos; + /** @var AccountRepositoryInterface */ + private $currencyRepos; + /** @var JournalRepositoryInterface */ + private $repository; + + /** + * + */ + public function __construct() + { + parent::__construct(); + + // translations: + $this->middleware( + function ($request, $next) { + app('view')->share('mainTitleIcon', 'fa-credit-card'); + app('view')->share('title', trans('firefly.accounts')); + $this->repository = app(JournalRepositoryInterface::class); + $this->accountRepos = app(AccountRepositoryInterface::class); + $this->currencyRepos = app(CurrencyRepositoryInterface::class); + + return $next($request); + } + ); + } + + /** @noinspection MoreThanThreeArgumentsInspection */ + /** + * @param Request $request + * @param Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return JsonResponse + * + * @throws FireflyException + * @throws \Throwable + */ + public function overview(Request $request, Account $account, Carbon $start, Carbon $end): JsonResponse + { + if (AccountType::ASSET !== $account->accountType->type) { + throw new FireflyException(sprintf('Account %s is not an asset account.', $account->name)); + } + $startBalance = $request->get('startBalance'); + $endBalance = $request->get('endBalance'); + $transactionIds = $request->get('transactions') ?? []; + $clearedIds = $request->get('cleared') ?? []; + $amount = '0'; + $clearedAmount = '0'; + $route = route('accounts.reconcile.submit', [$account->id, $start->format('Ymd'), $end->format('Ymd')]); + // get sum of transaction amounts: + $transactions = $this->repository->getTransactionsById($transactionIds); + $cleared = $this->repository->getTransactionsById($clearedIds); + $countCleared = 0; + + /** @var Transaction $transaction */ + foreach ($transactions as $transaction) { + $amount = bcadd($amount, $transaction->amount); + } + + /** @var Transaction $transaction */ + foreach ($cleared as $transaction) { + if ($transaction->transactionJournal->date <= $end) { + $clearedAmount = bcadd($clearedAmount, $transaction->amount); + ++$countCleared; + } + } + $difference = bcadd(bcadd(bcsub($startBalance, $endBalance), $clearedAmount), $amount); + $diffCompare = bccomp($difference, '0'); + $return = [ + 'post_uri' => $route, + 'html' => view( + 'accounts.reconcile.overview', compact( + 'account', 'start', 'diffCompare', 'difference', 'end', 'clearedIds', 'transactionIds', 'clearedAmount', + 'startBalance', 'endBalance', 'amount', + 'route', 'countCleared' + ) + )->render(), + ]; + + return response()->json($return); + } + + + /** + * @param Account $account + * @param Carbon $start + * @param Carbon $end + * + * @return mixed + * + * @throws FireflyException + * @throws \Throwable + */ + public function transactions(Account $account, Carbon $start, Carbon $end) + { + if (AccountType::INITIAL_BALANCE === $account->accountType->type) { + return $this->redirectToOriginalAccount($account); + } + + $startDate = clone $start; + $startDate->subDays(1); + + $currencyId = (int)$this->accountRepos->getMetaValue($account, 'currency_id'); + $currency = $this->currencyRepos->findNull($currencyId); + if (0 === $currency) { + $currency = app('amount')->getDefaultCurrency(); // @codeCoverageIgnore + } + + $startBalance = round(app('steam')->balance($account, $startDate), $currency->decimal_places); + $endBalance = round(app('steam')->balance($account, $end), $currency->decimal_places); + + // get the transactions + $selectionStart = clone $start; + $selectionStart->subDays(3); + $selectionEnd = clone $end; + $selectionEnd->addDays(3); + + // grab transactions: + /** @var JournalCollectorInterface $collector */ + $collector = app(JournalCollectorInterface::class); + $collector->setAccounts(new Collection([$account])) + ->setRange($selectionStart, $selectionEnd)->withBudgetInformation()->withOpposingAccount()->withCategoryInformation(); + $transactions = $collector->getJournals(); + $html = view( + 'accounts.reconcile.transactions', compact('account', 'transactions', 'currency', 'start', 'end', 'selectionStart', 'selectionEnd') + )->render(); + + return response()->json(['html' => $html, 'startBalance' => $startBalance, 'endBalance' => $endBalance]); + } + + /** + * @param Account $account + * + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * + * @throws FireflyException + */ + private function redirectToOriginalAccount(Account $account) + { + /** @var Transaction $transaction */ + $transaction = $account->transactions()->first(); + if (null === $transaction) { + throw new FireflyException(sprintf('Expected a transaction. Account #%d has none. BEEP, error.', $account->id)); // @codeCoverageIgnore + } + + $journal = $transaction->transactionJournal; + /** @var Transaction $opposingTransaction */ + $opposingTransaction = $journal->transactions()->where('transactions.id', '!=', $transaction->id)->first(); + + if (null === $opposingTransaction) { + throw new FireflyException('Expected an opposing transaction. This account has none. BEEP, error.'); // @codeCoverageIgnore + } + + return redirect(route('accounts.show', [$opposingTransaction->account_id])); + } +} \ No newline at end of file diff --git a/app/Http/Controllers/JsonController.php b/app/Http/Controllers/JsonController.php index 2e5988d2c6..86340617f1 100644 --- a/app/Http/Controllers/JsonController.php +++ b/app/Http/Controllers/JsonController.php @@ -22,6 +22,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; /** @@ -32,10 +33,10 @@ class JsonController extends Controller /** * @param Request $request * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse * @throws \Throwable */ - public function action(Request $request) + public function action(Request $request): JsonResponse { $count = (int)$request->get('count') > 0 ? (int)$request->get('count') : 1; $keys = array_keys(config('firefly.rule-actions')); @@ -51,10 +52,10 @@ class JsonController extends Controller /** * @param Request $request * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse * @throws \Throwable */ - public function trigger(Request $request) + public function trigger(Request $request): JsonResponse { $count = (int)$request->get('count') > 0 ? (int)$request->get('count') : 1; $keys = array_keys(config('firefly.rule-triggers')); diff --git a/app/Http/Controllers/NewUserController.php b/app/Http/Controllers/NewUserController.php index cf3d0223e0..2ef441b1c2 100644 --- a/app/Http/Controllers/NewUserController.php +++ b/app/Http/Controllers/NewUserController.php @@ -109,7 +109,7 @@ class NewUserController extends Controller // store currency preference: Preferences::set('currencyPreference', $currency->code); - Preferences::mark(); + app('preferences')->mark(); // set default optional fields: $visibleFields = [ @@ -126,7 +126,7 @@ class NewUserController extends Controller Preferences::set('transaction_journal_optional_fields', $visibleFields); session()->flash('success', (string)trans('firefly.stored_new_accounts_new_user')); - Preferences::mark(); + app('preferences')->mark(); return redirect(route('index')); } diff --git a/app/Http/Controllers/PiggyBankController.php b/app/Http/Controllers/PiggyBankController.php index fbfbf94505..75365e9108 100644 --- a/app/Http/Controllers/PiggyBankController.php +++ b/app/Http/Controllers/PiggyBankController.php @@ -31,13 +31,13 @@ use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; use FireflyIII\Transformers\AccountTransformer; use FireflyIII\Transformers\PiggyBankTransformer; use Illuminate\Http\JsonResponse; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Log; use Preferences; use Symfony\Component\HttpFoundation\ParameterBag; -use View; /** * Class PiggyBankController. @@ -78,7 +78,7 @@ class PiggyBankController extends Controller * * @param PiggyBank $piggyBank * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function add(PiggyBank $piggyBank) { @@ -104,7 +104,7 @@ class PiggyBankController extends Controller * * @param PiggyBank $piggyBank * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function addMobile(PiggyBank $piggyBank) { @@ -145,7 +145,7 @@ class PiggyBankController extends Controller /** * @param PiggyBank $piggyBank * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(PiggyBank $piggyBank) { @@ -160,12 +160,12 @@ class PiggyBankController extends Controller /** * @param PiggyBank $piggyBank * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function destroy(PiggyBank $piggyBank) + public function destroy(PiggyBank $piggyBank): RedirectResponse { session()->flash('success', (string)trans('firefly.deleted_piggy_bank', ['name' => $piggyBank->name])); - Preferences::mark(); + app('preferences')->mark(); $this->piggyRepos->destroy($piggyBank); return redirect($this->getPreviousUri('piggy-banks.delete.uri')); @@ -174,7 +174,7 @@ class PiggyBankController extends Controller /** * @param PiggyBank $piggyBank * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(PiggyBank $piggyBank) { @@ -212,7 +212,7 @@ class PiggyBankController extends Controller /** * @param Request $request * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(Request $request) { @@ -267,9 +267,9 @@ class PiggyBankController extends Controller * @param Request $request * @param PiggyBank $piggyBank * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function postAdd(Request $request, PiggyBank $piggyBank) + public function postAdd(Request $request, PiggyBank $piggyBank): RedirectResponse { $amount = $request->get('amount') ?? '0'; $currency = app('amount')->getDefaultCurrency(); @@ -286,7 +286,7 @@ class PiggyBankController extends Controller ['amount' => app('amount')->formatAnything($currency, $amount, false), 'name' => $piggyBank->name] ) ); - Preferences::mark(); + app('preferences')->mark(); return redirect(route('piggy-banks.index')); } @@ -307,9 +307,9 @@ class PiggyBankController extends Controller * @param Request $request * @param PiggyBank $piggyBank * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function postRemove(Request $request, PiggyBank $piggyBank) + public function postRemove(Request $request, PiggyBank $piggyBank): RedirectResponse { $amount = $request->get('amount') ?? '0'; $currency = app('amount')->getDefaultCurrency(); @@ -326,7 +326,7 @@ class PiggyBankController extends Controller ['amount' => app('amount')->formatAnything($currency, $amount, false), 'name' => $piggyBank->name] ) ); - Preferences::mark(); + app('preferences')->mark(); return redirect(route('piggy-banks.index')); } @@ -347,7 +347,7 @@ class PiggyBankController extends Controller /** * @param PiggyBank $piggyBank * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function remove(PiggyBank $piggyBank) { @@ -367,7 +367,7 @@ class PiggyBankController extends Controller * * @param PiggyBank $piggyBank * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function removeMobile(PiggyBank $piggyBank) { @@ -400,7 +400,7 @@ class PiggyBankController extends Controller /** * @param PiggyBank $piggyBank * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function show(PiggyBank $piggyBank) { @@ -431,17 +431,19 @@ class PiggyBankController extends Controller $piggyBank = $this->piggyRepos->store($data); session()->flash('success', (string)trans('firefly.stored_piggy_bank', ['name' => $piggyBank->name])); - Preferences::mark(); + app('preferences')->mark(); + + $redirect = redirect($this->getPreviousUri('piggy-banks.create.uri')); if (1 === (int)$request->get('create_another')) { // @codeCoverageIgnoreStart session()->put('piggy-banks.create.fromStore', true); - return redirect(route('piggy-banks.create'))->withInput(); + $redirect = redirect(route('piggy-banks.create'))->withInput(); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('piggy-banks.create.uri')); + return $redirect; } /** @@ -456,16 +458,18 @@ class PiggyBankController extends Controller $piggyBank = $this->piggyRepos->update($piggyBank, $data); session()->flash('success', (string)trans('firefly.updated_piggy_bank', ['name' => $piggyBank->name])); - Preferences::mark(); + app('preferences')->mark(); + + $redirect = redirect($this->getPreviousUri('piggy-banks.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart session()->put('piggy-banks.edit.fromUpdate', true); - return redirect(route('piggy-banks.edit', [$piggyBank->id])); + $redirect = redirect(route('piggy-banks.edit', [$piggyBank->id])); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('piggy-banks.edit.uri')); + return $redirect; } } diff --git a/app/Http/Controllers/Popup/ReportController.php b/app/Http/Controllers/Popup/ReportController.php index 0f30b1c9d7..3473cf34c0 100644 --- a/app/Http/Controllers/Popup/ReportController.php +++ b/app/Http/Controllers/Popup/ReportController.php @@ -31,6 +31,7 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Support\Binder\AccountList; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Routing\Route; use InvalidArgumentException; @@ -78,11 +79,12 @@ class ReportController extends Controller /** * @param Request $request * - * @return \Illuminate\Http\JsonResponse + * @return JsonResponse * * @throws FireflyException + * @throws \Throwable */ - public function general(Request $request) + public function general(Request $request): JsonResponse { $attributes = $request->get('attributes') ?? []; $attributes = $this->parseAttributes($attributes); @@ -129,11 +131,11 @@ class ReportController extends Controller switch (true) { - case BalanceLine::ROLE_DEFAULTROLE === $role && null !== $budget->id: + case BalanceLine::ROLE_DEFAULTROLE === $role && null !== $budget && null !== $account: // normal row with a budget: $journals = $this->popupHelper->balanceForBudget($budget, $account, $attributes); break; - case BalanceLine::ROLE_DEFAULTROLE === $role && null === $budget->id: + case BalanceLine::ROLE_DEFAULTROLE === $role && null === $budget && null !== $account: // normal row without a budget: $journals = $this->popupHelper->balanceForNoBudget($account, $attributes); $budget->name = (string)trans('firefly.no_budget'); @@ -157,7 +159,10 @@ class ReportController extends Controller */ private function budgetSpentAmount(array $attributes): string { - $budget = $this->budgetRepository->findNull((int)$attributes['budgetId']); + $budget = $this->budgetRepository->findNull((int)$attributes['budgetId']); + if (null === $budget) { + throw new FireflyException('This is an unknown budget. Apologies.'); + } $journals = $this->popupHelper->byBudget($budget, $attributes); $view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render(); @@ -175,6 +180,11 @@ class ReportController extends Controller 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.'); + } + $journals = $this->popupHelper->byCategory($category, $attributes); $view = view('popup.report.category-entry', compact('journals', 'category'))->render(); @@ -191,7 +201,12 @@ class ReportController extends Controller */ private function expenseEntry(array $attributes): string { - $account = $this->accountRepository->findNull((int)$attributes['accountId']); + $account = $this->accountRepository->findNull((int)$attributes['accountId']); + + if (null === $account) { + throw new FireflyException('This is an unknown account. Apologies.'); + } + $journals = $this->popupHelper->byExpenses($account, $attributes); $view = view('popup.report.expense-entry', compact('journals', 'account'))->render(); @@ -208,7 +223,12 @@ class ReportController extends Controller */ private function incomeEntry(array $attributes): string { - $account = $this->accountRepository->findNull((int)$attributes['accountId']); + $account = $this->accountRepository->findNull((int)$attributes['accountId']); + + if (null === $account) { + throw new FireflyException('This is an unknown category. Apologies.'); + } + $journals = $this->popupHelper->byIncome($account, $attributes); $view = view('popup.report.income-entry', compact('journals', 'account'))->render(); @@ -229,13 +249,13 @@ class ReportController extends Controller try { $attributes['startDate'] = Carbon::createFromFormat('Ymd', $attributes['startDate']); } catch (InvalidArgumentException $e) { - throw new FireflyException('Could not parse start date "' . e($attributes['startDate']) . '".'); + throw new FireflyException(sprintf('Could not parse start date "%s": %s', $attributes['startDate'], $e->getMessage())); } try { $attributes['endDate'] = Carbon::createFromFormat('Ymd', $attributes['endDate']); } catch (InvalidArgumentException $e) { - throw new FireflyException('Could not parse start date "' . e($attributes['endDate']) . '".'); + throw new FireflyException(sprintf('Could not parse end date "%s": %s', $attributes['endDate'], $e->getMessage())); } return $attributes; diff --git a/app/Http/Controllers/PreferencesController.php b/app/Http/Controllers/PreferencesController.php index 52d3c79ffc..7a2f461bfe 100644 --- a/app/Http/Controllers/PreferencesController.php +++ b/app/Http/Controllers/PreferencesController.php @@ -24,10 +24,8 @@ namespace FireflyIII\Http\Controllers; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\User\UserRepositoryInterface; use Illuminate\Http\Request; use Preferences; -use View; /** * Class PreferencesController. @@ -54,12 +52,13 @@ class PreferencesController extends Controller /** * @param AccountRepositoryInterface $repository * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(AccountRepositoryInterface $repository) { - $accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); - $viewRangePref = Preferences::get('viewRange', '1M'); + $accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); + $viewRangePref = Preferences::get('viewRange', '1M'); + /** @noinspection NullPointerExceptionInspection */ $viewRange = $viewRangePref->data; $frontPageAccounts = Preferences::get('frontPageAccounts', []); $language = Preferences::get('language', config('firefly.default_language', 'en_US'))->data; @@ -85,12 +84,11 @@ class PreferencesController extends Controller } /** - * @param Request $request - * @param UserRepositoryInterface $repository + * @param Request $request * * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector */ - public function postIndex(Request $request, UserRepositoryInterface $repository) + public function postIndex(Request $request) { // front page accounts $frontPageAccounts = []; @@ -143,7 +141,7 @@ class PreferencesController extends Controller Preferences::set('transaction_journal_optional_fields', $optionalTj); session()->flash('success', (string)trans('firefly.saved_preferences')); - Preferences::mark(); + app('preferences')->mark(); return redirect(route('preferences.index')); } diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index fc02ea3c55..b77631646e 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -39,12 +39,12 @@ use FireflyIII\User; use Google2FA; use Hash; use Illuminate\Contracts\Auth\Guard; +use Illuminate\Support\Collection; use Laravel\Passport\ClientRepository; use Laravel\Passport\Passport; use Log; use phpseclib\Crypt\RSA; use Preferences; -use View; /** * Class ProfileController. @@ -73,7 +73,7 @@ class ProfileController extends Controller } /** - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function changeEmail() { @@ -86,7 +86,7 @@ class ProfileController extends Controller } /** - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function changePassword() { @@ -100,7 +100,7 @@ class ProfileController extends Controller /** * View that generates a 2FA code for the user. * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function code() { @@ -124,6 +124,7 @@ class ProfileController extends Controller public function confirmEmailChange(UserRepositoryInterface $repository, string $token) { // find preference with this token value. + /** @var Collection $set */ $set = Preferences::findByName('email_change_confirm_token'); $user = null; Log::debug(sprintf('Found %d preferences', $set->count())); @@ -149,7 +150,7 @@ class ProfileController extends Controller } /** - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function deleteAccount() { @@ -180,7 +181,9 @@ class ProfileController extends Controller */ public function enable2FA(UserRepositoryInterface $repository) { - if ($repository->hasRole(auth()->user(), 'demo')) { + /** @var User $user */ + $user = auth()->user(); + if ($repository->hasRole($user, 'demo')) { return redirect(route('profile.index')); } $hasTwoFactorAuthSecret = (null !== Preferences::get('twoFactorAuthSecret')); @@ -199,7 +202,7 @@ class ProfileController extends Controller } /** - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index() { @@ -210,19 +213,21 @@ class ProfileController extends Controller $this->createOAuthKeys(); - if ($count === 0) { + if (0 === $count) { /** @var ClientRepository $repository */ $repository = app(ClientRepository::class); $repository->createPersonalAccessClient(null, config('app.name') . ' Personal Access Client', 'http://localhost'); } $subTitle = auth()->user()->email; $userId = auth()->user()->id; - $enabled2FA = (int)Preferences::get('twoFactorAuthEnabled', 0)->data === 1; + $enabled2FA = 1 === (int)Preferences::get('twoFactorAuthEnabled', 0)->data; + /** @var User $user */ + $user = auth()->user(); // get access token or create one. $accessToken = Preferences::get('access_token', null); if (null === $accessToken) { - $token = auth()->user()->generateAccessToken(); + $token = $user->generateAccessToken(); $accessToken = Preferences::set('access_token', $token); } @@ -283,26 +288,27 @@ class ProfileController extends Controller // the request has already validated both new passwords must be equal. $current = $request->get('current_password'); $new = $request->get('new_password'); - + /** @var User $user */ + $user = auth()->user(); try { - $this->validatePassword(auth()->user(), $current, $new); + $this->validatePassword($user, $current, $new); } catch (ValidationException $e) { session()->flash('error', $e->getMessage()); return redirect(route('profile.change-password')); } - $repository->changePassword(auth()->user(), $request->get('new_password')); + $repository->changePassword($user, $request->get('new_password')); session()->flash('success', (string)trans('firefly.password_changed')); return redirect(route('profile.index')); } + /** @noinspection PhpUnusedParameterInspection */ /** * @param TokenFormRequest $request * * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector - * @SuppressWarnings(PHPMD.UnusedFormalParameter) // it's unused but the class does some validation. */ public function postCode(TokenFormRequest $request) { @@ -310,7 +316,7 @@ class ProfileController extends Controller Preferences::set('twoFactorAuthSecret', session()->get('two-factor-secret')); session()->flash('success', (string)trans('firefly.saved_preferences')); - Preferences::mark(); + app('preferences')->mark(); return redirect(route('profile.index')); } @@ -328,6 +334,7 @@ class ProfileController extends Controller return redirect(route('profile.delete-account')); } + /** @var User $user */ $user = auth()->user(); Log::info(sprintf('User #%d has opted to delete their account', auth()->user()->id)); // make repository delete user: @@ -343,7 +350,9 @@ class ProfileController extends Controller */ public function regenerate() { - $token = auth()->user()->generateAccessToken(); + /** @var User $user */ + $user = auth()->user(); + $token = $user->generateAccessToken(); Preferences::set('access_token', $token); session()->flash('success', (string)trans('firefly.token_regenerated')); diff --git a/app/Http/Controllers/Recurring/CreateController.php b/app/Http/Controllers/Recurring/CreateController.php index 817f6f73dd..559ad1b444 100644 --- a/app/Http/Controllers/Recurring/CreateController.php +++ b/app/Http/Controllers/Recurring/CreateController.php @@ -113,6 +113,7 @@ class CreateController extends Controller ); } + /** * @param RecurrenceFormRequest $request * @@ -126,16 +127,16 @@ class CreateController extends Controller $request->session()->flash('success', (string)trans('firefly.stored_new_recurrence', ['title' => $recurrence->title])); app('preferences')->mark(); - + $redirect = redirect($this->getPreviousUri('recurring.create.uri')); if (1 === (int)$request->get('create_another')) { // set value so create routine will not overwrite URL: $request->session()->put('recurring.create.fromStore', true); - return redirect(route('recurring.create'))->withInput(); + $redirect = redirect(route('recurring.create'))->withInput(); } // redirect to previous URL. - return redirect($this->getPreviousUri('recurring.create.uri')); + return $redirect; } diff --git a/app/Http/Controllers/Recurring/EditController.php b/app/Http/Controllers/Recurring/EditController.php index e78b8a820f..6438361472 100644 --- a/app/Http/Controllers/Recurring/EditController.php +++ b/app/Http/Controllers/Recurring/EditController.php @@ -153,16 +153,16 @@ class EditController extends Controller $request->session()->flash('success', (string)trans('firefly.updated_recurrence', ['title' => $recurrence->title])); app('preferences')->mark(); - + $redirect = redirect($this->getPreviousUri('recurrences.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // set value so edit routine will not overwrite URL: $request->session()->put('recurrences.edit.fromUpdate', true); - return redirect(route('recurring.edit', [$recurrence->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('recurring.edit', [$recurrence->id]))->withInput(['return_to_edit' => 1]); } // redirect to previous URL. - return redirect($this->getPreviousUri('recurrences.edit.uri')); + return $redirect; } diff --git a/app/Http/Controllers/Recurring/IndexController.php b/app/Http/Controllers/Recurring/IndexController.php index d7f02b5071..e2c75c1e8a 100644 --- a/app/Http/Controllers/Recurring/IndexController.php +++ b/app/Http/Controllers/Recurring/IndexController.php @@ -18,7 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ - +/** @noinspection PhpMethodParametersCountMismatchInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Recurring; @@ -64,13 +64,14 @@ class IndexController extends Controller ); } + /** * @param Request $request * * @throws FireflyException * @return JsonResponse */ - function events(Request $request): JsonResponse + public function events(Request $request): JsonResponse { $return = []; $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); @@ -187,8 +188,8 @@ class IndexController extends Controller */ public function show(Request $request, Recurrence $recurrence) { - $transformer = new RecurrenceTransformer(new ParameterBag); - $array = $transformer->transform($recurrence); + $transformer = new RecurrenceTransformer(new ParameterBag); + $array = $transformer->transform($recurrence); $page = (int)$request->get('page'); $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $transactions = $this->recurring->getTransactions($recurrence, $page, $pageSize); @@ -202,7 +203,7 @@ class IndexController extends Controller $subTitle = trans('firefly.overview_for_recurrence', ['title' => $recurrence->title]); - return view('recurring.show', compact('recurrence', 'subTitle', 'array','transactions')); + return view('recurring.show', compact('recurrence', 'subTitle', 'array', 'transactions')); } /** @@ -216,7 +217,7 @@ class IndexController extends Controller $date = Carbon::createFromFormat('Y-m-d', $request->get('date')); $preSelected = (string)$request->get('pre_select'); $result = []; - if ($date > $today || (string)$request->get('past') === 'true') { + 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)); diff --git a/app/Http/Controllers/Report/AccountController.php b/app/Http/Controllers/Report/AccountController.php index c7c8ff447f..8e29812af5 100644 --- a/app/Http/Controllers/Report/AccountController.php +++ b/app/Http/Controllers/Report/AccountController.php @@ -33,6 +33,7 @@ use Illuminate\Support\Collection; */ class AccountController extends Controller { + /** * @param Collection $accounts * @param Carbon $start diff --git a/app/Http/Controllers/Report/BalanceController.php b/app/Http/Controllers/Report/BalanceController.php index 3b31be87de..992845aa09 100644 --- a/app/Http/Controllers/Report/BalanceController.php +++ b/app/Http/Controllers/Report/BalanceController.php @@ -33,17 +33,18 @@ use Illuminate\Support\Collection; */ class BalanceController extends Controller { + /** - * @param BalanceReportHelperInterface $helper - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string * @throws \Throwable */ - public function general(BalanceReportHelperInterface $helper, Collection $accounts, Carbon $start, Carbon $end) + public function general(Collection $accounts, Carbon $start, Carbon $end) { + // chart properties for cache: $cache = new CacheProperties; $cache->addProperty($start); @@ -53,7 +54,7 @@ class BalanceController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - + $helper = app(BalanceReportHelperInterface::class); $balance = $helper->getBalanceReport($accounts, $start, $end); $result = view('reports.partials.balance', compact('balance'))->render(); diff --git a/app/Http/Controllers/Report/BudgetController.php b/app/Http/Controllers/Report/BudgetController.php index 7a129f3fa7..44ba71d683 100644 --- a/app/Http/Controllers/Report/BudgetController.php +++ b/app/Http/Controllers/Report/BudgetController.php @@ -34,16 +34,16 @@ use Illuminate\Support\Collection; */ class BudgetController extends Controller { + /** - * @param BudgetReportHelperInterface $helper - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string * @throws \Throwable */ - public function general(BudgetReportHelperInterface $helper, Collection $accounts, Carbon $start, Carbon $end) + public function general(Collection $accounts, Carbon $start, Carbon $end) { // chart properties for cache: $cache = new CacheProperties; @@ -54,7 +54,7 @@ class BudgetController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - + $helper = app(BudgetReportHelperInterface::class); $budgets = $helper->getBudgetReport($start, $end, $accounts); $result = view('reports.partials.budgets', compact('budgets'))->render(); @@ -63,6 +63,7 @@ class BudgetController extends Controller return $result; } + /** * @param Collection $accounts * @param Carbon $start diff --git a/app/Http/Controllers/Report/CategoryController.php b/app/Http/Controllers/Report/CategoryController.php index 5b182a8e7e..a37336b0fc 100644 --- a/app/Http/Controllers/Report/CategoryController.php +++ b/app/Http/Controllers/Report/CategoryController.php @@ -34,6 +34,7 @@ use Illuminate\Support\Collection; */ class CategoryController extends Controller { + /** * @param Collection $accounts * @param Carbon $start @@ -66,6 +67,7 @@ class CategoryController extends Controller return $result; } + /** * @param Collection $accounts * @@ -75,7 +77,7 @@ class CategoryController extends Controller * @return string * @throws \Throwable */ - public function income(Collection $accounts, Carbon $start, Carbon $end) + public function income(Collection $accounts, Carbon $start, Carbon $end): string { $cache = new CacheProperties; $cache->addProperty($start); @@ -99,6 +101,7 @@ class CategoryController extends Controller return $result; } + /** * @param Collection $accounts * @param Carbon $start diff --git a/app/Http/Controllers/Report/ExpenseController.php b/app/Http/Controllers/Report/ExpenseController.php index 485b0d6842..9d5b7276ae 100644 --- a/app/Http/Controllers/Report/ExpenseController.php +++ b/app/Http/Controllers/Report/ExpenseController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection MoreThanThreeArgumentsInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Report; @@ -58,6 +59,7 @@ class ExpenseController extends Controller ); } + /** * Generates the overview per budget. * @@ -69,7 +71,7 @@ class ExpenseController extends Controller * @return string * @throws \Throwable */ - public function budget(Collection $accounts, Collection $expense, Carbon $start, Carbon $end) + public function budget(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): string { // Properties for cache: $cache = new CacheProperties; @@ -98,13 +100,13 @@ class ExpenseController extends Controller } $together[$categoryId]['grand_total'] = bcadd($spentInfo['grand_total'], $together[$categoryId]['grand_total']); } - unset($spentInfo); $result = view('reports.partials.exp-budgets', compact('together'))->render(); $cache->store($result); return $result; } + /** * Generates the overview per category (spent and earned). * @@ -116,7 +118,7 @@ class ExpenseController extends Controller * @return string * @throws \Throwable */ - public function category(Collection $accounts, Collection $expense, Carbon $start, Carbon $end) + public function category(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): string { // Properties for cache: $cache = new CacheProperties; @@ -146,7 +148,6 @@ class ExpenseController extends Controller } $together[$categoryId]['grand_total'] = bcadd($spentInfo['grand_total'], $together[$categoryId]['grand_total']); } - unset($spentInfo); foreach ($earned as $categoryId => $earnedInfo) { if (!isset($together[$categoryId])) { $together[$categoryId]['earned'] = $earnedInfo; @@ -162,6 +163,7 @@ class ExpenseController extends Controller return $result; } + /** * Overview of spending * @@ -208,6 +210,7 @@ class ExpenseController extends Controller // for period, get spent and earned for each account (by name) } + /** * @param Collection $accounts * @param Collection $expense @@ -217,7 +220,7 @@ class ExpenseController extends Controller * @return string * @throws \Throwable */ - public function topExpense(Collection $accounts, Collection $expense, Carbon $start, Carbon $end) + public function topExpense(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): string { // Properties for cache: $cache = new CacheProperties; diff --git a/app/Http/Controllers/Report/OperationsController.php b/app/Http/Controllers/Report/OperationsController.php index 2164c57749..a13eaa8593 100644 --- a/app/Http/Controllers/Report/OperationsController.php +++ b/app/Http/Controllers/Report/OperationsController.php @@ -33,16 +33,37 @@ use Illuminate\Support\Collection; */ class OperationsController extends Controller { + + /** @var AccountTaskerInterface */ + private $tasker; + /** - * @param AccountTaskerInterface $tasker - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * + */ + public function __construct() + { + parent::__construct(); + + // translations: + $this->middleware( + function ($request, $next) { + $this->tasker = app(AccountTaskerInterface::class); + + return $next($request); + } + ); + } + + + /** + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string * @throws \Throwable */ - public function expenses(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end) + public function expenses(Collection $accounts, Carbon $start, Carbon $end) { // chart properties for cache: $cache = new CacheProperties; @@ -53,7 +74,7 @@ class OperationsController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - $entries = $tasker->getExpenseReport($start, $end, $accounts); + $entries = $this->tasker->getExpenseReport($start, $end, $accounts); $type = 'expense-entry'; $result = view('reports.partials.income-expenses', compact('entries', 'type'))->render(); $cache->store($result); @@ -62,15 +83,14 @@ class OperationsController extends Controller } /** - * @param AccountTaskerInterface $tasker - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return string * @throws \Throwable */ - public function income(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end) + public function income(Collection $accounts, Carbon $start, Carbon $end): string { // chart properties for cache: $cache = new CacheProperties; @@ -81,7 +101,7 @@ class OperationsController extends Controller if ($cache->has()) { return $cache->get(); // @codeCoverageIgnore } - $entries = $tasker->getIncomeReport($start, $end, $accounts); + $entries = $this->tasker->getIncomeReport($start, $end, $accounts); $type = 'income-entry'; $result = view('reports.partials.income-expenses', compact('entries', 'type'))->render(); @@ -91,15 +111,14 @@ class OperationsController extends Controller } /** - * @param AccountTaskerInterface $tasker - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string * @throws \Throwable */ - public function operations(AccountTaskerInterface $tasker, Collection $accounts, Carbon $start, Carbon $end) + public function operations(Collection $accounts, Carbon $start, Carbon $end) { // chart properties for cache: $cache = new CacheProperties; @@ -111,8 +130,8 @@ class OperationsController extends Controller return $cache->get(); // @codeCoverageIgnore } - $incomes = $tasker->getIncomeReport($start, $end, $accounts); - $expenses = $tasker->getExpenseReport($start, $end, $accounts); + $incomes = $this->tasker->getIncomeReport($start, $end, $accounts); + $expenses = $this->tasker->getExpenseReport($start, $end, $accounts); $incomeSum = array_sum( array_map( function ($item) { diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index 2b4bff068d..a912daf83b 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -18,6 +18,8 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection CallableParameterUseCaseInTypeContextInspection */ +/** @noinspection MoreThanThreeArgumentsInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers; @@ -75,8 +77,7 @@ class ReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return string - * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string * @throws \FireflyIII\Exceptions\FireflyException */ public function accountReport(Collection $accounts, Collection $expense, Carbon $start, Carbon $end) @@ -109,7 +110,7 @@ class ReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return string + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string * * @throws \FireflyIII\Exceptions\FireflyException */ @@ -146,7 +147,7 @@ class ReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return string + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string * * @throws \FireflyIII\Exceptions\FireflyException */ @@ -184,7 +185,7 @@ class ReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return string + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string * * @throws \FireflyIII\Exceptions\FireflyException */ @@ -221,7 +222,7 @@ class ReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return string + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string * * @throws \FireflyIII\Exceptions\FireflyException */ @@ -256,7 +257,7 @@ class ReportController extends Controller /** * @param AccountRepositoryInterface $repository * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(AccountRepositoryInterface $repository) { @@ -276,7 +277,7 @@ class ReportController extends Controller * * @return mixed * - + * @throws \Throwable */ public function options(string $reportType) { @@ -307,7 +308,6 @@ class ReportController extends Controller * @return RedirectResponse|\Illuminate\Routing\Redirector * * @throws \FireflyIII\Exceptions\FireflyException - * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function postIndex(ReportFormRequest $request) { @@ -329,19 +329,19 @@ class ReportController extends Controller return redirect(route('reports.index')); } - if (0 === $request->getCategoryList()->count() && 'category' === $reportType) { + if ('category' === $reportType && 0 === $request->getCategoryList()->count()) { session()->flash('error', trans('firefly.select_more_than_one_category')); return redirect(route('reports.index')); } - if (0 === $request->getBudgetList()->count() && 'budget' === $reportType) { + if ('budget' === $reportType && 0 === $request->getBudgetList()->count()) { session()->flash('error', trans('firefly.select_more_than_one_budget')); return redirect(route('reports.index')); } - if (0 === $request->getTagList()->count() && 'tag' === $reportType) { + if ('tag' === $reportType && 0 === $request->getTagList()->count()) { session()->flash('error', trans('firefly.select_more_than_one_tag')); return redirect(route('reports.index')); @@ -381,7 +381,7 @@ class ReportController extends Controller * @param Carbon $start * @param Carbon $end * - * @return string + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View|string * * @throws \FireflyIII\Exceptions\FireflyException */ @@ -426,7 +426,7 @@ class ReportController extends Controller $set = new Collection; $names = $revenue->pluck('name')->toArray(); foreach ($expense as $exp) { - if (\in_array($exp->name, $names)) { + if (\in_array($exp->name, $names, true)) { $set->push($exp); } } diff --git a/app/Http/Controllers/RuleController.php b/app/Http/Controllers/RuleController.php index 4ec76ebee9..24ca0a01de 100644 --- a/app/Http/Controllers/RuleController.php +++ b/app/Http/Controllers/RuleController.php @@ -38,13 +38,13 @@ 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 Preferences; use Throwable; -use View; /** * Class RuleController. @@ -88,8 +88,7 @@ class RuleController extends Controller * @param Request $request * @param RuleGroup $ruleGroup * - * @return View - * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function create(Request $request, RuleGroup $ruleGroup) { @@ -104,7 +103,7 @@ class RuleController extends Controller $oldActions = []; $returnToBill = false; - if ($request->get('return') === 'true') { + if ('true' === $request->get('return')) { $returnToBill = true; } @@ -158,7 +157,7 @@ class RuleController extends Controller * * @param Rule $rule * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(Rule $rule) { @@ -175,15 +174,15 @@ class RuleController extends Controller * * @param Rule $rule * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function destroy(Rule $rule) + public function destroy(Rule $rule): RedirectResponse { $title = $rule->title; $this->ruleRepos->destroy($rule); session()->flash('success', trans('firefly.deleted_rule', ['title' => $title])); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('rules.delete.uri')); } @@ -191,7 +190,7 @@ class RuleController extends Controller /** * @param Rule $rule * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|\Illuminate\Routing\Redirector */ public function down(Rule $rule) { @@ -204,8 +203,7 @@ class RuleController extends Controller * @param Request $request * @param Rule $rule * - * @return View - * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Request $request, Rule $rule) { @@ -258,13 +256,15 @@ class RuleController extends Controller * @param SelectTransactionsRequest $request * @param Rule $rule * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse * * @internal param RuleGroup $ruleGroup */ - public function execute(SelectTransactionsRequest $request, Rule $rule) + 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')); @@ -273,7 +273,7 @@ class RuleController extends Controller $job = new ExecuteRuleOnExistingTransactions($rule); // Apply parameters to the job - $job->setUser(auth()->user()); + $job->setUser($user); $job->setAccounts($accounts); $job->setStartDate($startDate); $job->setEndDate($endDate); @@ -288,13 +288,15 @@ class RuleController extends Controller } /** - * @return View + * @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(auth()->user()); + $ruleGroups = $this->ruleGroupRepos->getRuleGroupsWithRules($user); return view('rules.index', compact('ruleGroups')); } @@ -349,17 +351,17 @@ class RuleController extends Controller /** * @param RuleFormRequest $request * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|\Illuminate\Routing\Redirector */ public function store(RuleFormRequest $request) { $data = $request->getRuleData(); $rule = $this->ruleRepos->store($data); session()->flash('success', trans('firefly.stored_new_rule', ['title' => $rule->title])); - Preferences::mark(); + app('preferences')->mark(); // redirect to show bill. - if ($request->get('return_to_bill') === 'true' && (int)$request->get('bill_id') > 0) { + if ('true' === $request->get('return_to_bill') && (int)$request->get('bill_id') > 0) { return redirect(route('bills.show', [(int)$request->get('bill_id')])); // @codeCoverageIgnore } @@ -368,16 +370,16 @@ class RuleController extends Controller 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); - - return redirect(route('rules.create', [$data['rule_group_id']]))->withInput(); + $redirect = redirect(route('rules.create', [$data['rule_group_id']]))->withInput(); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('rules.create.uri')); + return $redirect; } /** @@ -508,7 +510,7 @@ class RuleController extends Controller /** * @param Rule $rule * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|\Illuminate\Routing\Redirector */ public function up(Rule $rule) { @@ -521,7 +523,7 @@ class RuleController extends Controller * @param RuleFormRequest $request * @param Rule $rule * - * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + * @return RedirectResponse|\Illuminate\Routing\Redirector */ public function update(RuleFormRequest $request, Rule $rule) { @@ -529,17 +531,17 @@ class RuleController extends Controller $this->ruleRepos->update($rule, $data); session()->flash('success', trans('firefly.updated_rule', ['title' => $rule->title])); - Preferences::mark(); - + 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); - return redirect(route('rules.edit', [$rule->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('rules.edit', [$rule->id]))->withInput(['return_to_edit' => 1]); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('rules.edit.uri')); + return $redirect; } /** @@ -792,6 +794,7 @@ class RuleController extends Controller private function getTriggersForBill(Bill $bill): array { $triggers = []; + /** @noinspection BadExceptionsProcessingInspection */ try { $triggers[] = view( 'rules.partials.trigger', @@ -822,6 +825,7 @@ class RuleController extends Controller 'count' => 3, ] )->render(); + $triggers[] = view( 'rules.partials.trigger', [ diff --git a/app/Http/Controllers/RuleGroupController.php b/app/Http/Controllers/RuleGroupController.php index 27d3005ee5..50e4e2833f 100644 --- a/app/Http/Controllers/RuleGroupController.php +++ b/app/Http/Controllers/RuleGroupController.php @@ -29,9 +29,9 @@ use FireflyIII\Jobs\ExecuteRuleGroupOnExistingTransactions; use FireflyIII\Models\RuleGroup; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; +use FireflyIII\User; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; -use Preferences; -use View; /** * Class RuleGroupController. @@ -56,7 +56,7 @@ class RuleGroupController extends Controller } /** - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function create() { @@ -75,7 +75,7 @@ class RuleGroupController extends Controller /** * @param RuleGroup $ruleGroup * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(RuleGroup $ruleGroup) { @@ -96,13 +96,17 @@ class RuleGroupController extends Controller */ public function destroy(Request $request, RuleGroupRepositoryInterface $repository, RuleGroup $ruleGroup) { - $title = $ruleGroup->title; - $moveTo = auth()->user()->ruleGroups()->find((int)$request->get('move_rules_before_delete')); + /** @var User $user */ + $user = auth()->user(); + $title = $ruleGroup->title; + + /** @var RuleGroup $moveTo */ + $moveTo = $user->ruleGroups()->find((int)$request->get('move_rules_before_delete')); $repository->destroy($ruleGroup, $moveTo); session()->flash('success', (string)trans('firefly.deleted_rule_group', ['title' => $title])); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('rule-groups.delete.uri')); } @@ -153,11 +157,13 @@ class RuleGroupController extends Controller * @param AccountRepositoryInterface $repository * @param RuleGroup $ruleGroup * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function execute(SelectTransactionsRequest $request, AccountRepositoryInterface $repository, RuleGroup $ruleGroup) + public function execute(SelectTransactionsRequest $request, AccountRepositoryInterface $repository, RuleGroup $ruleGroup): RedirectResponse { // Get parameters specified by the user + /** @var User $user */ + $user = auth()->user(); $accounts = $repository->getAccountsById($request->get('accounts')); $startDate = new Carbon($request->get('start_date')); $endDate = new Carbon($request->get('end_date')); @@ -166,7 +172,7 @@ class RuleGroupController extends Controller $job = new ExecuteRuleGroupOnExistingTransactions($ruleGroup); // Apply parameters to the job - $job->setUser(auth()->user()); + $job->setUser($user); $job->setAccounts($accounts); $job->setStartDate($startDate); $job->setEndDate($endDate); @@ -183,7 +189,7 @@ class RuleGroupController extends Controller /** * @param RuleGroup $ruleGroup * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function selectTransactions(RuleGroup $ruleGroup) { @@ -206,17 +212,18 @@ class RuleGroupController extends Controller $ruleGroup = $repository->store($data); session()->flash('success', (string)trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])); - Preferences::mark(); + app('preferences')->mark(); + $redirect = redirect($this->getPreviousUri('rule-groups.create.uri')); if (1 === (int)$request->get('create_another')) { // @codeCoverageIgnoreStart session()->put('rule-groups.create.fromStore', true); - return redirect(route('rule-groups.create'))->withInput(); + $redirect = redirect(route('rule-groups.create'))->withInput(); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('rule-groups.create.uri')); + return $redirect; } /** @@ -250,17 +257,17 @@ class RuleGroupController extends Controller $repository->update($ruleGroup, $data); session()->flash('success', (string)trans('firefly.updated_rule_group', ['title' => $ruleGroup->title])); - Preferences::mark(); - + app('preferences')->mark(); + $redirect = redirect($this->getPreviousUri('rule-groups.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart session()->put('rule-groups.edit.fromUpdate', true); - return redirect(route('rule-groups.edit', [$ruleGroup->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('rule-groups.edit', [$ruleGroup->id]))->withInput(['return_to_edit' => 1]); // @codeCoverageIgnoreEnd } // redirect to previous URL. - return redirect($this->getPreviousUri('rule-groups.edit.uri')); + return $redirect; } } diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 4baf91f083..9e97fae2a2 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -24,9 +24,9 @@ namespace FireflyIII\Http\Controllers; use FireflyIII\Support\CacheProperties; use FireflyIII\Support\Search\SearchInterface; +use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Collection; -use View; /** * Class SearchController. @@ -54,7 +54,7 @@ class SearchController extends Controller * @param Request $request * @param SearchInterface $searcher * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(Request $request, SearchInterface $searcher) { @@ -75,7 +75,7 @@ class SearchController extends Controller * @return \Illuminate\Http\JsonResponse * @throws \Throwable */ - public function search(Request $request, SearchInterface $searcher) + public function search(Request $request, SearchInterface $searcher): JsonResponse { $fullQuery = (string)$request->get('query'); $transactions = new Collection; diff --git a/app/Http/Controllers/System/InstallController.php b/app/Http/Controllers/System/InstallController.php index 9945f9d4d9..8e345e7084 100644 --- a/app/Http/Controllers/System/InstallController.php +++ b/app/Http/Controllers/System/InstallController.php @@ -145,7 +145,7 @@ class InstallController extends Controller /** * @return \Illuminate\Http\JsonResponse */ - public function verify() + public function verify(): JsonResponse { if ($this->hasForbiddenFunctions()) { return response()->json(['error' => true, 'message' => self::FORBIDDEN_ERROR]); diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index 26074416c4..9027432d6e 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpMethodParametersCountMismatchInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers; @@ -29,6 +30,7 @@ use FireflyIII\Http\Requests\TagFormRequest; use FireflyIII\Models\Tag; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Support\CacheProperties; +use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Collection; use View; @@ -62,9 +64,7 @@ class TagController extends Controller } /** - * Create a new tag. - * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function create() { @@ -85,7 +85,7 @@ class TagController extends Controller * * @param Tag $tag * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function delete(Tag $tag) { @@ -100,9 +100,9 @@ class TagController extends Controller /** * @param Tag $tag * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function destroy(Tag $tag) + public function destroy(Tag $tag): RedirectResponse { $tagName = $tag->tag; $this->repository->destroy($tag); @@ -118,7 +118,7 @@ class TagController extends Controller * * @param Tag $tag * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Tag $tag) { @@ -135,11 +135,11 @@ class TagController extends Controller } /** - * View all tags. + * Edit a tag. * * @param TagRepositoryInterface $repository * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(TagRepositoryInterface $repository) { @@ -163,16 +163,16 @@ class TagController extends Controller } /** - * @param Request $request - * @param TagRepositoryInterface $repository - * @param Tag $tag - * @param string $moment + * @param Request $request + * @param Tag $tag + * @param string|null $moment * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function show(Request $request, TagRepositoryInterface $repository, Tag $tag, string $moment = '') + public function show(Request $request, Tag $tag, string $moment = null) { // default values: + $moment = $moment ?? ''; $subTitle = $tag->tag; $subTitleIcon = 'fa-tag'; $page = (int)$request->get('page'); @@ -186,14 +186,15 @@ class TagController extends Controller // prep for "all" view. if ('all' === $moment) { $subTitle = trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]); - $start = $repository->firstUseDate($tag); + $start = $this->repository->firstUseDate($tag); $end = new Carbon; $path = route('tags.show', [$tag->id, 'all']); } // prep for "specific date" view. if ('all' !== $moment && \strlen($moment) > 0) { - $start = new Carbon($moment); + $start = new Carbon($moment); + /** @var Carbon $end */ $end = app('navigation')->endOfPeriod($start, $range); $subTitle = trans( 'firefly.journals_in_period_for_tag', @@ -224,17 +225,17 @@ class TagController extends Controller $transactions = $collector->getPaginatedJournals(); $transactions->setPath($path); - $sums = $repository->sumsOfTag($tag, $start, $end); + $sums = $this->repository->sumsOfTag($tag, $start, $end); - return view('tags.show', compact('apiKey', 'tag', 'sums', 'periods', 'subTitle', 'subTitleIcon', 'transactions', 'start', 'end', 'moment')); + return view('tags.show', compact('tag', 'sums', 'periods', 'subTitle', 'subTitleIcon', 'transactions', 'start', 'end', 'moment')); } /** * @param TagFormRequest $request * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function store(TagFormRequest $request) + public function store(TagFormRequest $request): RedirectResponse { $data = $request->collectTagData(); $this->repository->store($data); @@ -242,24 +243,26 @@ class TagController extends Controller session()->flash('success', (string)trans('firefly.created_tag', ['tag' => $data['tag']])); app('preferences')->mark(); + $redirect = redirect($this->getPreviousUri('tags.create.uri')); if (1 === (int)$request->get('create_another')) { // @codeCoverageIgnoreStart session()->put('tags.create.fromStore', true); - return redirect(route('tags.create'))->withInput(); + $redirect = redirect(route('tags.create'))->withInput(); // @codeCoverageIgnoreEnd } - return redirect($this->getPreviousUri('tags.create.uri')); + return $redirect; + } /** * @param TagFormRequest $request * @param Tag $tag * - * @return \Illuminate\Http\RedirectResponse + * @return RedirectResponse */ - public function update(TagFormRequest $request, Tag $tag) + public function update(TagFormRequest $request, Tag $tag): RedirectResponse { $data = $request->collectTagData(); $this->repository->update($tag, $data); @@ -267,16 +270,17 @@ class TagController extends Controller session()->flash('success', (string)trans('firefly.updated_tag', ['tag' => $data['tag']])); app('preferences')->mark(); + $redirect = redirect($this->getPreviousUri('tags.edit.uri')); if (1 === (int)$request->get('return_to_edit')) { // @codeCoverageIgnoreStart session()->put('tags.edit.fromUpdate', true); - return redirect(route('tags.edit', [$tag->id]))->withInput(['return_to_edit' => 1]); + $redirect = redirect(route('tags.edit', [$tag->id]))->withInput(['return_to_edit' => 1]); // @codeCoverageIgnoreEnd } // redirect to previous URL. - return redirect($this->getPreviousUri('tags.edit.uri')); + return $redirect; } /** @@ -288,6 +292,7 @@ class TagController extends Controller { // get first and last tag date from tag: $range = app('preferences')->get('viewRange', '1M')->data; + /** @var Carbon $end */ $end = app('navigation')->endOfX($this->repository->lastUseDate($tag), $range, null); $start = $this->repository->firstUseDate($tag); @@ -319,6 +324,7 @@ class TagController extends Controller ]; $collection->push($arr); + /** @var Carbon $currentEnd */ $currentEnd = clone $currentStart; $currentEnd->subDay(); } diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php index aeac8035ea..a2648b35e1 100644 --- a/app/Http/Controllers/Transaction/BulkController.php +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -32,8 +32,6 @@ use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Illuminate\Support\Collection; use Log; -use Preferences; -use View; /** * Class BulkController @@ -45,7 +43,7 @@ class BulkController extends Controller /** - * + * BulkController constructor. */ public function __construct() { @@ -65,7 +63,7 @@ class BulkController extends Controller /** * @param Collection $journals * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function edit(Collection $journals) { @@ -95,9 +93,9 @@ class BulkController extends Controller { $journalIds = $request->get('journals'); $journalIds = \is_array($journalIds) ? $journalIds : []; - $ignoreCategory = (int)$request->get('ignore_category') === 1; - $ignoreBudget = (int)$request->get('ignore_budget') === 1; - $ignoreTags = (int)$request->get('ignore_tags') === 1; + $ignoreCategory = 1 === (int)$request->get('ignore_category'); + $ignoreBudget = 1 === (int)$request->get('ignore_budget'); + $ignoreTags = 1 === (int)$request->get('ignore_tags'); $count = 0; foreach ($journalIds as $journalId) { @@ -110,26 +108,26 @@ class BulkController extends Controller Log::debug(sprintf('Found journal #%d', $journal->id)); // update category if not told to ignore - if ($ignoreCategory === false) { + if (false === $ignoreCategory) { Log::debug(sprintf('Set category to %s', $request->string('category'))); $this->repository->updateCategory($journal, $request->string('category')); } // update budget if not told to ignore (and is withdrawal) - if ($ignoreBudget === false) { + if (false === $ignoreBudget) { Log::debug(sprintf('Set budget to %d', $request->integer('budget_id'))); $this->repository->updateBudget($journal, $request->integer('budget_id')); } // update tags: - if ($ignoreTags === false) { + if (false === $ignoreTags) { Log::debug(sprintf('Set tags to %s', $request->string('budget_id'))); $this->repository->updateTags($journal, ['tags' => explode(',', $request->string('tags'))]); } } - Preferences::mark(); + app('preferences')->mark(); $request->session()->flash('success', trans('firefly.mass_edited_transactions_success', ['amount' => $count])); // redirect to previous URL: diff --git a/app/Http/Controllers/Transaction/ConvertController.php b/app/Http/Controllers/Transaction/ConvertController.php index 6a4b644244..c6f45d7790 100644 --- a/app/Http/Controllers/Transaction/ConvertController.php +++ b/app/Http/Controllers/Transaction/ConvertController.php @@ -61,6 +61,7 @@ class ConvertController extends Controller ); } + /** * @param TransactionType $destinationType * @param TransactionJournal $journal @@ -109,6 +110,7 @@ class ConvertController extends Controller ); } + /** * @param Request $request * @param TransactionType $destinationType @@ -124,6 +126,7 @@ class ConvertController extends Controller // @codeCoverageIgnoreStart if ($this->isOpeningBalance($journal)) { Log::debug('Journal is opening balance, return to account.'); + return $this->redirectToAccount($journal); } // @codeCoverageIgnoreEnd @@ -160,6 +163,7 @@ class ConvertController extends Controller return redirect(route('transactions.show', [$journal->id])); } + /** * @param TransactionJournal $journal * @param TransactionType $destinationType @@ -215,6 +219,7 @@ class ConvertController extends Controller return $destination; } + /** * @param TransactionJournal $journal * @param TransactionType $destinationType diff --git a/app/Http/Controllers/Transaction/LinkController.php b/app/Http/Controllers/Transaction/LinkController.php index 686b73c082..0d5a3d4998 100644 --- a/app/Http/Controllers/Transaction/LinkController.php +++ b/app/Http/Controllers/Transaction/LinkController.php @@ -29,7 +29,6 @@ use FireflyIII\Models\TransactionJournalLink; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Repositories\LinkType\LinkTypeRepositoryInterface; use Log; -use Preferences; use URL; /** @@ -86,7 +85,7 @@ class LinkController extends Controller $this->repository->destroyLink($link); session()->flash('success', (string)trans('firefly.deleted_link')); - Preferences::mark(); + app('preferences')->mark(); return redirect((string)session('journal_links.delete.uri')); } @@ -107,7 +106,14 @@ class LinkController extends Controller 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', trans('firefly.invalid_link_selection')); + + return redirect(route('transactions.show', [$journal->id])); + } + $alreadyLinked = $this->repository->findLink($journal, $other); if ($other->id === $journal->id) { diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index cd08cf2435..77063142f0 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -35,9 +35,9 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Transformers\TransactionTransformer; +use FireflyIII\User; use Illuminate\Support\Collection; use Illuminate\View\View as IlluminateView; -use Preferences; use Symfony\Component\HttpFoundation\ParameterBag; /** @@ -109,7 +109,7 @@ class MassController extends Controller ++$count; } - Preferences::mark(); + app('preferences')->mark(); session()->flash('success', trans('firefly.mass_deleted_transactions_success', ['amount' => $count])); // redirect to previous URL: @@ -123,8 +123,11 @@ class MassController extends Controller */ public function edit(Collection $journals): IlluminateView { + /** @var User $user */ + $user = auth()->user(); $subTitle = trans('firefly.mass_edit_journals'); + /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $accounts = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET]); @@ -141,7 +144,7 @@ class MassController extends Controller $transformer = new TransactionTransformer(new ParameterBag); /** @var JournalCollectorInterface $collector */ $collector = app(JournalCollectorInterface::class); - $collector->setUser(auth()->user()); + $collector->setUser($user); $collector->withOpposingAccount()->withCategoryInformation()->withBudgetInformation(); $collector->setJournals($journals); $collector->addFilter(TransactionViewFilter::class); @@ -153,12 +156,12 @@ class MassController extends Controller // transform to array $transactions = $collection->map( function (Transaction $transaction) use ($transformer) { - $transaction = $transformer->transform($transaction); + $transformed = $transformer->transform($transaction); // make sure amount is positive: - $transaction['amount'] = app('steam')->positive((string)$transaction['amount']); - $transaction['foreign_amount'] = app('steam')->positive((string)$transaction['foreign_amount']); + $transformed['amount'] = app('steam')->positive((string)$transformed['amount']); + $transformed['foreign_amount'] = app('steam')->positive((string)$transformed['foreign_amount']); - return $transaction; + return $transformed; } ); @@ -177,7 +180,7 @@ class MassController extends Controller $count = 0; if (\is_array($journalIds)) { foreach ($journalIds as $journalId) { - $journal = $repository->find((int)$journalId); + $journal = $repository->findNull((int)$journalId); if (null !== $journal) { // get optional fields: $what = strtolower($this->repository->getTransactionType($journal)); @@ -206,7 +209,7 @@ class MassController extends Controller 'category_id' => null, 'category_name' => $category, - 'budget_id' => (int)$budgetId, + 'budget_id' => $budgetId, 'budget_name' => null, 'source_id' => (int)$sourceAccountId, 'source_name' => $sourceAccountName, @@ -221,11 +224,6 @@ class MassController extends Controller 'foreign_amount' => $foreignAmount, 'foreign_currency_id' => $foreignCurrencyId, 'foreign_currency_code' => null, - //'native_amount' => $amount, - //'source_amount' => $amount, - //'foreign_amount' => $foreignAmount, - //'destination_amount' => $foreignAmount, - //'amount' => $foreignAmount, ]], 'currency_id' => $foreignCurrencyId, 'tags' => $tags, @@ -241,7 +239,7 @@ class MassController extends Controller } } } - Preferences::mark(); + app('preferences')->mark(); session()->flash('success', trans('firefly.mass_edited_transactions_success', ['amount' => $count])); // redirect to previous URL: diff --git a/app/Http/Controllers/Transaction/SingleController.php b/app/Http/Controllers/Transaction/SingleController.php index 17da1e6fb5..261119e15b 100644 --- a/app/Http/Controllers/Transaction/SingleController.php +++ b/app/Http/Controllers/Transaction/SingleController.php @@ -113,13 +113,13 @@ class SingleController extends Controller 'budget_id' => $budgetId, 'category' => $categoryName, 'tags' => $tags, - 'interest_date' => $journal->getMeta('interest_date'), - 'book_date' => $journal->getMeta('book_date'), - 'process_date' => $journal->getMeta('process_date'), - 'due_date' => $journal->getMeta('due_date'), - 'payment_date' => $journal->getMeta('payment_date'), - 'invoice_date' => $journal->getMeta('invoice_date'), - 'internal_reference' => $journal->getMeta('internal_reference'), + 'interest_date' => $this->repository->getMetaField($journal, 'interest_date'), + 'book_date' => $this->repository->getMetaField($journal, 'book_date'), + 'process_date' => $this->repository->getMetaField($journal, 'process_date'), + 'due_date' => $this->repository->getMetaField($journal, 'due_date'), + 'payment_date' => $this->repository->getMetaField($journal, 'payment_date'), + 'invoice_date' => $this->repository->getMetaField($journal, 'invoice_date'), + 'internal_reference' => $this->repository->getMetaField($journal, 'internal_reference'), 'notes' => '', ]; @@ -135,15 +135,15 @@ class SingleController extends Controller } /** - * @param Request $request - * @param string $what + * @param Request $request + * @param string|null $what * - * @return View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ - public function create(Request $request, string $what = TransactionType::DEPOSIT) + public function create(Request $request, string $what = null) { - $what = strtolower($what); - $what = $request->old('what') ?? $what; + $what = strtolower($what ?? TransactionType::DEPOSIT); + $what = (string)($request->old('what') ?? $what); $budgets = ExpandedForm::makeSelectListWithEmpty($this->budgets->getActiveBudgets()); $preFilled = session()->has('preFilled') ? session('preFilled') : []; $subTitle = trans('form.add_new_' . $what); @@ -152,13 +152,13 @@ class SingleController extends Controller $source = (int)$request->get('source'); // grab old currency ID from old data: - $currencyID = (int)$request->old('amount_currency_id_amount'); + $currencyID = (int)$request->old('amount_currency_id_amount'); $preFilled['amount_currency_id_amount'] = $currencyID; - if (($what === 'withdrawal' || $what === 'transfer') && $source > 0) { + if (('withdrawal' === $what || 'transfer' === $what) && $source > 0) { $preFilled['source_id'] = $source; } - if ($what === 'deposit' && $source > 0) { + if ('deposit' === $what && $source > 0) { $preFilled['destination_id'] = $source; } @@ -220,7 +220,7 @@ class SingleController extends Controller $this->repository->destroy($transactionJournal); - Preferences::mark(); + app('preferences')->mark(); return redirect($this->getPreviousUri('transactions.delete.uri')); } @@ -296,7 +296,7 @@ class SingleController extends Controller // amounts for withdrawals and deposits: // amount, native_amount, source_amount, destination_amount - if (($journal->isWithdrawal() || $journal->isDeposit()) && null !== $pTransaction->foreign_amount) { + if (null !== $pTransaction->foreign_amount && ($journal->isWithdrawal() || $journal->isDeposit())) { $preFilled['amount'] = $pTransaction->foreign_amount; $preFilled['currency'] = $pTransaction->foreignCurrency; } @@ -355,7 +355,7 @@ class SingleController extends Controller event(new StoredTransactionJournal($journal, $data['piggy_bank_id'])); session()->flash('success', (string)trans('firefly.stored_journal', ['description' => $journal->description])); - Preferences::mark(); + app('preferences')->mark(); // @codeCoverageIgnoreStart if (true === $createAnother) { @@ -412,7 +412,7 @@ class SingleController extends Controller $type = strtolower($this->repository->getTransactionType($journal)); session()->flash('success', (string)trans('firefly.updated_' . $type, ['description' => $data['description']])); - Preferences::mark(); + app('preferences')->mark(); // @codeCoverageIgnoreStart if (1 === (int)$request->get('return_to_edit')) { diff --git a/app/Http/Controllers/Transaction/SplitController.php b/app/Http/Controllers/Transaction/SplitController.php index a0b0014576..43d8056620 100644 --- a/app/Http/Controllers/Transaction/SplitController.php +++ b/app/Http/Controllers/Transaction/SplitController.php @@ -32,7 +32,6 @@ use FireflyIII\Http\Requests\SplitJournalFormRequest; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; @@ -40,7 +39,6 @@ use FireflyIII\Transformers\TransactionTransformer; use Illuminate\Http\Request; use Illuminate\Support\Collection; use Preferences; -use Steam; use Symfony\Component\HttpFoundation\ParameterBag; use View; @@ -49,9 +47,6 @@ use View; */ class SplitController extends Controller { - /** @var AccountRepositoryInterface */ - private $accounts; - /** @var AttachmentHelperInterface */ private $attachments; @@ -73,7 +68,6 @@ class SplitController extends Controller // some useful repositories: $this->middleware( function ($request, $next) { - $this->accounts = app(AccountRepositoryInterface::class); $this->budgets = app(BudgetRepositoryInterface::class); $this->attachments = app(AttachmentHelperInterface::class); $this->currencies = app(CurrencyRepositoryInterface::class); @@ -99,7 +93,7 @@ class SplitController extends Controller return $this->redirectToAccount($journal); // @codeCoverageIgnore } // basic fields: - $uploadSize = min(Steam::phpBytes(ini_get('upload_max_filesize')), Steam::phpBytes(ini_get('post_max_size'))); + $uploadSize = min(app('steam')->phpBytes(ini_get('upload_max_filesize')), app('steam')->phpBytes(ini_get('post_max_size'))); $subTitle = trans('breadcrumbs.edit_journal', ['description' => $journal->description]); $subTitleIcon = 'fa-pencil'; @@ -271,6 +265,7 @@ class SplitController extends Controller foreach ($old as $index => $row) { if (isset($array[$index])) { + /** @noinspection SlowArrayOperationsInLoopInspection */ $array[$index] = array_merge($array[$index], $row); continue; } diff --git a/app/Http/Controllers/TransactionController.php b/app/Http/Controllers/TransactionController.php index 7ad5d34f99..0a59b0c28c 100644 --- a/app/Http/Controllers/TransactionController.php +++ b/app/Http/Controllers/TransactionController.php @@ -18,6 +18,8 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection CallableParameterUseCaseInTypeContextInspection */ +/** @noinspection MoreThanThreeArgumentsInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers; @@ -71,13 +73,12 @@ class TransactionController extends Controller /** * Index for a range of transactions. * - * @param Request $request - * @param string $what - * @param Carbon $start - * @param Carbon $end - * - * @return View + * @param Request $request + * @param string $what + * @param Carbon|null $start + * @param Carbon|null $end * + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View */ public function index(Request $request, string $what, Carbon $start = null, Carbon $end = null) { @@ -85,7 +86,6 @@ class TransactionController extends Controller $types = config('firefly.transactionTypesByWhat.' . $what); $page = (int)$request->get('page'); $pageSize = (int)Preferences::get('listPageSize', 50)->data; - $path = route('transactions.index', [$what]); if (null === $start) { $start = session('start'); $end = session('end'); @@ -162,9 +162,10 @@ class TransactionController extends Controller foreach ($transactionIds as $transactionId) { $transactionId = (int)$transactionId; $transaction = $this->repository->findTransaction($transactionId); - Log::debug(sprintf('Transaction ID is %d', $transaction->id)); - - $this->repository->reconcile($transaction); + if (null !== $transaction) { + Log::debug(sprintf('Transaction ID is %d', $transaction->id)); + $this->repository->reconcile($transaction); + } } return response()->json(['ok' => 'reconciled']); @@ -175,7 +176,7 @@ class TransactionController extends Controller * * @return \Illuminate\Http\JsonResponse */ - public function reorder(Request $request) + public function reorder(Request $request): JsonResponse { $ids = $request->get('items'); $date = new Carbon($request->get('date')); @@ -183,14 +184,14 @@ class TransactionController extends Controller $order = 0; $ids = array_unique($ids); foreach ($ids as $id) { - $journal = $this->repository->find((int)$id); - if ($journal && $journal->date->isSameDay($date)) { + $journal = $this->repository->findNull((int)$id); + if (null !== $journal && $journal->date->isSameDay($date)) { $this->repository->setOrder($journal, $order); ++$order; } } } - Preferences::mark(); + app('preferences')->mark(); return response()->json([true]); } @@ -271,11 +272,13 @@ class TransactionController extends Controller $sums = $this->sumPerCurrency($journals); $dateName = app('navigation')->periodShow($currentDate['start'], $currentDate['period']); $sum = $journals->sum('transaction_amount'); + /** @noinspection PhpUndefinedMethodInspection */ $entries->push( [ - 'name' => $dateName, - 'sums' => $sums, - 'sum' => $sum, + 'name' => $dateName, + 'sums' => $sums, + 'sum' => $sum, + 'start' => $currentDate['start']->format('Y-m-d'), 'end' => $currentDate['end']->format('Y-m-d'), ] diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index 9c2b7f0131..d3ca0e6c55 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -73,6 +73,7 @@ class Authenticate return $next($request); } + /** * Determine if the user is logged in to any of the given guards. * @@ -88,9 +89,11 @@ class Authenticate if (empty($guards)) { try { // go for default guard: + /** @noinspection PhpUndefinedMethodInspection */ if ($this->auth->check()) { // do an extra check on user object. + /** @noinspection PhpUndefinedMethodInspection */ $user = $this->auth->authenticate(); if (1 === (int)$user->blocked) { $message = (string)trans('firefly.block_account_logout'); @@ -98,6 +101,7 @@ class Authenticate $message = (string)trans('firefly.email_changed_logout'); } app('session')->flash('logoutMessage', $message); + /** @noinspection PhpUndefinedMethodInspection */ $this->auth->logout(); throw new AuthenticationException('Blocked account.', $guards); @@ -105,16 +109,23 @@ class Authenticate } } catch (QueryException $e) { // @codeCoverageIgnoreStart - throw new FireflyException('It seems the database has not yet been initialized. Did you run the correct upgrade or installation commands?'); + throw new FireflyException( + sprintf( + 'It seems the database has not yet been initialized. Did you run the correct upgrade or installation commands? Error: %s', + $e->getMessage() + ) + ); // @codeCoverageIgnoreEnd } + /** @noinspection PhpUndefinedMethodInspection */ return $this->auth->authenticate(); } // @codeCoverageIgnoreStart foreach ($guards as $guard) { if ($this->auth->guard($guard)->check()) { + /** @noinspection PhpVoidFunctionResultUsedInspection */ return $this->auth->shouldUse($guard); } } diff --git a/app/Http/Middleware/AuthenticateTwoFactor.php b/app/Http/Middleware/AuthenticateTwoFactor.php index 61e747bd02..b47affcf0f 100644 --- a/app/Http/Middleware/AuthenticateTwoFactor.php +++ b/app/Http/Middleware/AuthenticateTwoFactor.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpMethodParametersCountMismatchInspection */ declare(strict_types=1); namespace FireflyIII\Http\Middleware; @@ -50,6 +51,8 @@ class AuthenticateTwoFactor $this->auth = $auth; } + + /** @noinspection PhpUnusedParameterInspection */ /** * @param $request * @param Closure $next @@ -61,13 +64,16 @@ class AuthenticateTwoFactor */ public function handle($request, Closure $next, ...$guards) { + /** @noinspection PhpUndefinedMethodInspection */ if ($this->auth->guest()) { return response()->redirectTo(route('login')); } + $is2faEnabled = app('preferences')->get('twoFactorAuthEnabled', false)->data; $has2faSecret = null !== app('preferences')->get('twoFactorAuthSecret'); - $is2faAuthed = 'true' === $request->cookie('twoFactorAuthenticated'); + /** @noinspection PhpUndefinedMethodInspection */ + $is2faAuthed = 'true' === $request->cookie('twoFactorAuthenticated'); if ($is2faEnabled && $has2faSecret && !$is2faAuthed) { Log::debug('Does not seem to be 2 factor authed, redirect.'); diff --git a/app/Http/Middleware/Binder.php b/app/Http/Middleware/Binder.php index fd321892fa..e6e702a564 100644 --- a/app/Http/Middleware/Binder.php +++ b/app/Http/Middleware/Binder.php @@ -54,6 +54,7 @@ class Binder $this->auth = $auth; } + /** @noinspection PhpUnusedParameterInspection */ /** * Handle an incoming request. * @@ -63,7 +64,6 @@ class Binder * * @return mixed * - */ public function handle($request, Closure $next, ...$guards) { diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php index 05f06173fb..6ed1ae7c4f 100644 --- a/app/Http/Middleware/EncryptCookies.php +++ b/app/Http/Middleware/EncryptCookies.php @@ -30,12 +30,4 @@ use Illuminate\Cookie\Middleware\EncryptCookies as Middleware; */ class EncryptCookies extends Middleware { - /** - * The names of the cookies that should not be encrypted. - * - * @var array - */ - protected $except - = [ - ]; } diff --git a/app/Http/Middleware/Installer.php b/app/Http/Middleware/Installer.php index 2f8f73a654..11dfbae057 100644 --- a/app/Http/Middleware/Installer.php +++ b/app/Http/Middleware/Installer.php @@ -48,12 +48,12 @@ class Installer */ public function handle($request, Closure $next) { - if (env('APP_ENV') === 'testing') { + if ('testing' === env('APP_ENV')) { return $next($request); } $url = $request->url(); $strpos = stripos($url, '/install'); - if (!($strpos === false)) { + if (!(false === $strpos)) { Log::debug(sprintf('URL is %s, will NOT run installer middleware', $url)); return $next($request); @@ -102,7 +102,7 @@ class Installer */ protected function isAccessDenied(string $message): bool { - return !(stripos($message, 'Access denied') === false); + return !(false === stripos($message, 'Access denied')); } /** @@ -112,6 +112,6 @@ class Installer */ protected function noTablesExist(string $message): bool { - return !(stripos($message, 'Base table or view not found') === false); + return !(false === stripos($message, 'Base table or view not found')); } } diff --git a/app/Http/Middleware/IsAdmin.php b/app/Http/Middleware/IsAdmin.php index 539cf378fe..2ac5804051 100644 --- a/app/Http/Middleware/IsAdmin.php +++ b/app/Http/Middleware/IsAdmin.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Middleware; use Closure; +use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -52,7 +53,9 @@ class IsAdmin } /** @var User $user */ $user = auth()->user(); - if (!$user->hasRole('owner')) { + /** @var UserRepositoryInterface $repository */ + $repository = app(UserRepositoryInterface::class); + if (!$repository->hasRole($user, 'owner')) { return response()->redirectTo(route('home')); } diff --git a/app/Http/Middleware/IsDemoUser.php b/app/Http/Middleware/IsDemoUser.php index f89e05cc30..adf759708e 100644 --- a/app/Http/Middleware/IsDemoUser.php +++ b/app/Http/Middleware/IsDemoUser.php @@ -23,9 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Http\Middleware; use Closure; -use FireflyIII\Exceptions\IsDemoUserException; +use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Illuminate\Http\Request; +use Log; /** * Class IsDemoUser. @@ -48,7 +49,10 @@ class IsDemoUser return $next($request); } - if ($user->hasRole('demo')) { + /** @var UserRepositoryInterface $repository */ + $repository = app(UserRepositoryInterface::class); + if ($repository->hasRole($user, 'demo')) { + Log::info('User is a demo user.'); $request->session()->flash('info', (string)trans('firefly.not_available_demo_user')); $current = $request->url(); $previous = $request->session()->previousUrl(); diff --git a/app/Http/Middleware/Range.php b/app/Http/Middleware/Range.php index baf2ec0b08..b51d3ec59b 100644 --- a/app/Http/Middleware/Range.php +++ b/app/Http/Middleware/Range.php @@ -66,7 +66,7 @@ class Range /** * */ - private function configureList() + private function configureList(): void { $pref = Preferences::get('list-length', config('firefly.list_length', 10))->data; View::share('listLength', $pref); @@ -75,9 +75,10 @@ class Range /** * */ - private function configureView() + private function configureView(): void { $pref = Preferences::get('language', config('firefly.default_language', 'en_US')); + /** @noinspection NullPointerExceptionInspection */ $lang = $pref->data; App::setLocale($lang); Carbon::setLocale(substr($lang, 0, 2)); @@ -105,9 +106,9 @@ class Range /** * @param Request $request */ - private function loseItAll(Request $request) + private function loseItAll(Request $request): void { - if (getenv('DB_CONNECTION') === 'sqlite' && getenv('IS_DOCKER') === true) { + if ('sqlite' === getenv('DB_CONNECTION') && true === getenv('IS_DOCKER')) { $request->session()->flash( 'error', 'You seem to be using SQLite in a Docker container. Don\'t do this. If the container restarts all your data will be gone.' ); @@ -117,7 +118,7 @@ class Range /** * */ - private function setRange() + private function setRange(): void { // ignore preference. set the range to be the current month: if (!Session::has('start') && !Session::has('end')) { diff --git a/app/Http/Middleware/Sandstorm.php b/app/Http/Middleware/Sandstorm.php index ecbc4b6ac5..34a60b8c16 100644 --- a/app/Http/Middleware/Sandstorm.php +++ b/app/Http/Middleware/Sandstorm.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ declare(strict_types=1); namespace FireflyIII\Http\Middleware; @@ -47,7 +48,6 @@ class Sandstorm * @return mixed * * @throws FireflyException - * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function handle(Request $request, Closure $next, $guard = null) { @@ -74,6 +74,7 @@ class Sandstorm if (1 === $count && \strlen($userId) > 0) { // login as first user user. $user = $repository->first(); + /** @noinspection NullPointerExceptionInspection */ Auth::guard($guard)->login($user); View::share('SANDSTORM_ANON', false); @@ -83,6 +84,7 @@ class Sandstorm if (1 === $count && '' === $userId) { // login but indicate anonymous $user = User::first(); + /** @noinspection NullPointerExceptionInspection */ Auth::guard($guard)->login($user); View::share('SANDSTORM_ANON', true); diff --git a/app/Http/Middleware/StartFireflySession.php b/app/Http/Middleware/StartFireflySession.php index 4cb809999a..4197d6d285 100644 --- a/app/Http/Middleware/StartFireflySession.php +++ b/app/Http/Middleware/StartFireflySession.php @@ -37,11 +37,11 @@ class StartFireflySession extends StartSession * @param \Illuminate\Http\Request $request * @param \Illuminate\Contracts\Session\Session $session */ - protected function storeCurrentUrl(Request $request, $session) + protected function storeCurrentUrl(Request $request, $session): void { $uri = $request->fullUrl(); $strpos = strpos($uri, 'jscript'); - if ('GET' === $request->method() && $request->route() && !$request->ajax() && false === $strpos) { + if (false === $strpos && 'GET' === $request->method() && $request->route() && !$request->ajax()) { $session->setPreviousUrl($uri); } } diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php index 6dc4ee301b..f14b84141d 100644 --- a/app/Http/Middleware/TrustProxies.php +++ b/app/Http/Middleware/TrustProxies.php @@ -51,11 +51,11 @@ class TrustProxies extends Middleware { $trustedProxies = env('TRUSTED_PROXIES', null); if (false !== $trustedProxies && null !== $trustedProxies && \strlen($trustedProxies) > 0) { - if ($trustedProxies === '*' || $trustedProxies === '**') { - $this->proxies = (string)$trustedProxies; + if ('*' === $trustedProxies || '**' === $trustedProxies) { + $this->proxies = $trustedProxies; } - if ($trustedProxies !== '*' && $trustedProxies !== '**') { + if ('*' !== $trustedProxies && '**' !== $trustedProxies) { $this->proxies = explode(',', $trustedProxies); } } diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index f35cb11c61..16a542dff5 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -30,12 +30,4 @@ use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken as Middleware; */ class VerifyCsrfToken extends Middleware { - /** - * The URIs that should be excluded from CSRF verification. - * - * @var array - */ - protected $except - = [ - ]; } diff --git a/app/Http/Requests/AccountFormRequest.php b/app/Http/Requests/AccountFormRequest.php index 289be2b07b..85d717990a 100644 --- a/app/Http/Requests/AccountFormRequest.php +++ b/app/Http/Requests/AccountFormRequest.php @@ -33,7 +33,7 @@ class AccountFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -66,7 +66,7 @@ class AccountFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { $accountRoles = implode(',', config('firefly.accountRoles')); $types = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); diff --git a/app/Http/Requests/AttachmentFormRequest.php b/app/Http/Requests/AttachmentFormRequest.php index 58b70356a4..96086b0433 100644 --- a/app/Http/Requests/AttachmentFormRequest.php +++ b/app/Http/Requests/AttachmentFormRequest.php @@ -31,7 +31,7 @@ class AttachmentFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -51,7 +51,7 @@ class AttachmentFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Http/Requests/BillFormRequest.php b/app/Http/Requests/BillFormRequest.php index dc2d35cf94..e053e4c09c 100644 --- a/app/Http/Requests/BillFormRequest.php +++ b/app/Http/Requests/BillFormRequest.php @@ -30,7 +30,7 @@ class BillFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -39,7 +39,7 @@ class BillFormRequest extends Request /** * @return array */ - public function getBillData() + public function getBillData(): array { return [ 'name' => $this->string('name'), diff --git a/app/Http/Requests/BudgetFormRequest.php b/app/Http/Requests/BudgetFormRequest.php index 90cd932635..94e870e9dd 100644 --- a/app/Http/Requests/BudgetFormRequest.php +++ b/app/Http/Requests/BudgetFormRequest.php @@ -33,7 +33,7 @@ class BudgetFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { return auth()->check(); } @@ -52,7 +52,7 @@ class BudgetFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed /** @var BudgetRepositoryInterface $repository */ diff --git a/app/Http/Requests/BudgetIncomeRequest.php b/app/Http/Requests/BudgetIncomeRequest.php index 8fbb7a5ed2..859b758f6d 100644 --- a/app/Http/Requests/BudgetIncomeRequest.php +++ b/app/Http/Requests/BudgetIncomeRequest.php @@ -31,7 +31,7 @@ class BudgetIncomeRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class BudgetIncomeRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Http/Requests/BulkEditJournalRequest.php b/app/Http/Requests/BulkEditJournalRequest.php index 4aefd85029..84d037aab5 100644 --- a/app/Http/Requests/BulkEditJournalRequest.php +++ b/app/Http/Requests/BulkEditJournalRequest.php @@ -30,7 +30,7 @@ class BulkEditJournalRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -39,7 +39,7 @@ class BulkEditJournalRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed diff --git a/app/Http/Requests/CategoryFormRequest.php b/app/Http/Requests/CategoryFormRequest.php index 38b2b872e6..e51aa818db 100644 --- a/app/Http/Requests/CategoryFormRequest.php +++ b/app/Http/Requests/CategoryFormRequest.php @@ -32,7 +32,7 @@ class CategoryFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -51,7 +51,7 @@ class CategoryFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { /** @var CategoryRepositoryInterface $repository */ $repository = app(CategoryRepositoryInterface::class); diff --git a/app/Http/Requests/ConfigurationRequest.php b/app/Http/Requests/ConfigurationRequest.php index d6dbe9a490..74ec996eca 100644 --- a/app/Http/Requests/ConfigurationRequest.php +++ b/app/Http/Requests/ConfigurationRequest.php @@ -31,10 +31,10 @@ class ConfigurationRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users and admins - return auth()->check() && auth()->user()->hasRole('owner'); + return auth()->check(); } /** @@ -51,7 +51,7 @@ class ConfigurationRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed $rules = [ diff --git a/app/Http/Requests/CurrencyFormRequest.php b/app/Http/Requests/CurrencyFormRequest.php index 5e1249bddf..9e0b143e92 100644 --- a/app/Http/Requests/CurrencyFormRequest.php +++ b/app/Http/Requests/CurrencyFormRequest.php @@ -30,7 +30,7 @@ class CurrencyFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -39,7 +39,7 @@ class CurrencyFormRequest extends Request /** * @return array */ - public function getCurrencyData() + public function getCurrencyData(): array { return [ 'name' => $this->string('name'), @@ -52,7 +52,7 @@ class CurrencyFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed $rules = [ diff --git a/app/Http/Requests/DeleteAccountFormRequest.php b/app/Http/Requests/DeleteAccountFormRequest.php index 34e7494289..d4109b0063 100644 --- a/app/Http/Requests/DeleteAccountFormRequest.php +++ b/app/Http/Requests/DeleteAccountFormRequest.php @@ -31,7 +31,7 @@ class DeleteAccountFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class DeleteAccountFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Http/Requests/EmailFormRequest.php b/app/Http/Requests/EmailFormRequest.php index 6ad6d66fa0..a64b72e8e9 100644 --- a/app/Http/Requests/EmailFormRequest.php +++ b/app/Http/Requests/EmailFormRequest.php @@ -31,7 +31,7 @@ class EmailFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class EmailFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Http/Requests/ExportFormRequest.php b/app/Http/Requests/ExportFormRequest.php index d57207f05c..4897c6dbaa 100644 --- a/app/Http/Requests/ExportFormRequest.php +++ b/app/Http/Requests/ExportFormRequest.php @@ -32,7 +32,7 @@ class ExportFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -41,7 +41,7 @@ class ExportFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { $sessionFirst = clone session('first'); $first = $sessionFirst->subDay()->format('Y-m-d'); diff --git a/app/Http/Requests/JournalFormRequest.php b/app/Http/Requests/JournalFormRequest.php index 24e450fbb1..ac2068bbea 100644 --- a/app/Http/Requests/JournalFormRequest.php +++ b/app/Http/Requests/JournalFormRequest.php @@ -35,7 +35,7 @@ class JournalFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -46,7 +46,7 @@ class JournalFormRequest extends Request * * @return array */ - public function getJournalData() + public function getJournalData(): array { $currencyId = $this->integer('amount_currency_id_amount'); $data = [ @@ -142,7 +142,7 @@ class JournalFormRequest extends Request * * @throws FireflyException */ - public function rules() + public function rules(): array { $what = $this->get('what'); $rules = [ @@ -239,15 +239,15 @@ class JournalFormRequest extends Request $data = $validator->getData(); $type = $data['what'] ?? 'invalid'; Log::debug(sprintf('Type is %s', $type)); - if ($type === 'withdrawal') { + 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 - && $selectedCurrency !== 0 - && $accountCurrency !== 0 + && 0 !== $selectedCurrency + && 0 !== $accountCurrency ) { Log::debug('ADD validation error on native_amount'); $validator->errors()->add('native_amount', trans('validation.numeric_native')); @@ -257,13 +257,13 @@ class JournalFormRequest extends Request } // same thing for deposits: - if ($type === 'deposit') { + 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 - && $selectedCurrency !== 0 - && $accountCurrency !== 0 + && 0 !== $selectedCurrency + && 0 !== $accountCurrency ) { $validator->errors()->add('native_amount', trans('validation.numeric_native')); @@ -272,7 +272,7 @@ class JournalFormRequest extends Request } // and for transfers - if ($type === 'transfer') { + if ('transfer' === $type) { $sourceCurrency = (int)($data['source_account_currency'] ?? 0); $destinationCurrency = (int)($data['destination_account_currency'] ?? 0); @@ -282,15 +282,15 @@ class JournalFormRequest extends Request Log::debug(sprintf('Source currency is %d, destination currency is %d', $sourceCurrency, $destinationCurrency)); if ($sourceCurrency !== $destinationCurrency && '' === $sourceAmount - && $sourceCurrency !== 0 - && $destinationCurrency !== 0 + && 0 !== $sourceCurrency + && 0 !== $destinationCurrency ) { $validator->errors()->add('source_amount', trans('validation.numeric_source')); } if ($sourceCurrency !== $destinationCurrency && '' === $destinationAmount - && $sourceCurrency !== 0 - && $destinationCurrency !== 0 + && 0 !== $sourceCurrency + && 0 !== $destinationCurrency ) { $validator->errors()->add('destination_amount', trans('validation.numeric_destination')); $validator->errors()->add('destination_amount', trans('validation.numeric', ['attribute' => 'destination_amount'])); diff --git a/app/Http/Requests/JournalLinkRequest.php b/app/Http/Requests/JournalLinkRequest.php index ace48c5032..6cebe3a4de 100644 --- a/app/Http/Requests/JournalLinkRequest.php +++ b/app/Http/Requests/JournalLinkRequest.php @@ -18,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with Firefly III. If not, see . */ +/** @noinspection PhpDynamicAsStaticMethodCallInspection */ declare(strict_types=1); namespace FireflyIII\Http\Requests; @@ -32,7 +33,7 @@ class JournalLinkRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -60,7 +61,7 @@ class JournalLinkRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // all possible combinations of link types and inward / outward: $combinations = []; diff --git a/app/Http/Requests/LinkTypeFormRequest.php b/app/Http/Requests/LinkTypeFormRequest.php index 82fa430801..77cae53114 100644 --- a/app/Http/Requests/LinkTypeFormRequest.php +++ b/app/Http/Requests/LinkTypeFormRequest.php @@ -30,16 +30,16 @@ class LinkTypeFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged and admins - return auth()->check() && auth()->user()->hasRole('owner'); + return auth()->check(); } /** * @return array */ - public function rules() + public function rules(): array { // fixed $nameRule = 'required|min:1|unique:link_types,name'; diff --git a/app/Http/Requests/MassDeleteJournalRequest.php b/app/Http/Requests/MassDeleteJournalRequest.php index 3a52580288..5e7a423dec 100644 --- a/app/Http/Requests/MassDeleteJournalRequest.php +++ b/app/Http/Requests/MassDeleteJournalRequest.php @@ -31,7 +31,7 @@ class MassDeleteJournalRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class MassDeleteJournalRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Http/Requests/MassEditJournalRequest.php b/app/Http/Requests/MassEditJournalRequest.php index cd82765c6e..91bc871e33 100644 --- a/app/Http/Requests/MassEditJournalRequest.php +++ b/app/Http/Requests/MassEditJournalRequest.php @@ -31,7 +31,7 @@ class MassEditJournalRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class MassEditJournalRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed diff --git a/app/Http/Requests/NewUserFormRequest.php b/app/Http/Requests/NewUserFormRequest.php index 30289dd69c..27c7042a2f 100644 --- a/app/Http/Requests/NewUserFormRequest.php +++ b/app/Http/Requests/NewUserFormRequest.php @@ -31,7 +31,7 @@ class NewUserFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class NewUserFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Http/Requests/PiggyBankFormRequest.php b/app/Http/Requests/PiggyBankFormRequest.php index bd6488edd5..fadcaad5c7 100644 --- a/app/Http/Requests/PiggyBankFormRequest.php +++ b/app/Http/Requests/PiggyBankFormRequest.php @@ -30,7 +30,7 @@ class PiggyBankFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -54,7 +54,7 @@ class PiggyBankFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { $nameRule = 'required|between:1,255|uniquePiggyBankForUser'; if ($this->integer('id')) { diff --git a/app/Http/Requests/ProfileFormRequest.php b/app/Http/Requests/ProfileFormRequest.php index cfa825f247..c03c865ed9 100644 --- a/app/Http/Requests/ProfileFormRequest.php +++ b/app/Http/Requests/ProfileFormRequest.php @@ -31,7 +31,7 @@ class ProfileFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class ProfileFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Http/Requests/ReconciliationUpdateRequest.php b/app/Http/Requests/ReconciliationUpdateRequest.php index 7e98b79186..e100866214 100644 --- a/app/Http/Requests/ReconciliationUpdateRequest.php +++ b/app/Http/Requests/ReconciliationUpdateRequest.php @@ -30,7 +30,7 @@ class ReconciliationUpdateRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -41,7 +41,7 @@ class ReconciliationUpdateRequest extends Request * * @return array */ - public function getJournalData() + public function getJournalData(): array { $data = [ 'tags' => explode(',', $this->string('tags')), @@ -55,7 +55,7 @@ class ReconciliationUpdateRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { $rules = [ 'amount' => 'numeric|required', diff --git a/app/Http/Requests/RecurrenceFormRequest.php b/app/Http/Requests/RecurrenceFormRequest.php index 7bebfacbce..d1ba493c5b 100644 --- a/app/Http/Requests/RecurrenceFormRequest.php +++ b/app/Http/Requests/RecurrenceFormRequest.php @@ -174,16 +174,16 @@ class RecurrenceFormRequest extends Request } // if ends after X repetitions, set another rule - if ($this->string('repetition_end') === 'times') { + if ('times' === $this->string('repetition_end')) { $rules['repetitions'] = 'required|numeric|between:0,254'; } // if foreign amount, currency must be different. - if ($this->float('foreign_amount') !== 0.0) { + if (0.0 !== $this->float('foreign_amount')) { $rules['foreign_currency_id'] = 'exists:transaction_currencies,id|different:transaction_currency_id'; } // if ends at date X, set another rule. - if ($this->string('repetition_end') === 'until_date') { + if ('until_date' === $this->string('repetition_end')) { $rules['repeat_until'] = 'required|date|after:' . $tomorrow->format('Y-m-d'); } @@ -231,7 +231,7 @@ class RecurrenceFormRequest extends Request 'moment' => '', ]; - if ($value === 'daily') { + if ('daily' === $value) { $return['type'] = $value; } //monthly,17 diff --git a/app/Http/Requests/ReportFormRequest.php b/app/Http/Requests/ReportFormRequest.php index edd58743ea..f07049ebc1 100644 --- a/app/Http/Requests/ReportFormRequest.php +++ b/app/Http/Requests/ReportFormRequest.php @@ -40,7 +40,7 @@ class ReportFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -125,8 +125,9 @@ class ReportFormRequest extends Request $date = new Carbon($parts[1]); // @codeCoverageIgnoreStart } catch (Exception $e) { - Log::error(sprintf('"%s" is not a valid date range.', $range)); - throw new FireflyException(sprintf('"%s" is not a valid date range.', $range)); + $error = sprintf('"%s" is not a valid date range: %s', $range, $e->getMessage()); + Log::error($error); + throw new FireflyException($error); // @codeCoverageIgnoreEnd } @@ -172,8 +173,9 @@ class ReportFormRequest extends Request $date = new Carbon($parts[0]); // @codeCoverageIgnoreStart } catch (Exception $e) { - Log::error(sprintf('"%s" is not a valid date range.', $range)); - throw new FireflyException(sprintf('"%s" is not a valid date range.', $range)); + $error = sprintf('"%s" is not a valid date range: %s', $range, $e->getMessage()); + Log::error($error); + throw new FireflyException($error); // @codeCoverageIgnoreEnd } } diff --git a/app/Http/Requests/Request.php b/app/Http/Requests/Request.php index c293b6237e..50a8b5f8fe 100644 --- a/app/Http/Requests/Request.php +++ b/app/Http/Requests/Request.php @@ -37,10 +37,10 @@ class Request extends FormRequest */ public function boolean(string $field): bool { - if ((string)$this->input($field) === 'true') { + if ('true' === (string)$this->input($field)) { return true; } - if ((string)$this->input($field) === 'false') { + if ('false' === (string)$this->input($field)) { return false; } @@ -133,7 +133,7 @@ class Request extends FormRequest * * @return Carbon|null */ - protected function date(string $field) + protected function date(string $field): ?Carbon { return $this->get($field) ? new Carbon($this->get($field)) : null; } diff --git a/app/Http/Requests/RuleFormRequest.php b/app/Http/Requests/RuleFormRequest.php index 9ef8d49a60..7e35f4016a 100644 --- a/app/Http/Requests/RuleFormRequest.php +++ b/app/Http/Requests/RuleFormRequest.php @@ -67,7 +67,7 @@ class RuleFormRequest extends Request $data['rule-triggers'][] = [ 'name' => $value, 'value' => $triggerValues[$index] ?? '', - 'stop-processing' => (int)($triggerStop[$index] ?? 0) === 1, + 'stop-processing' => 1 === (int)($triggerStop[$index] ?? 0), ]; } } @@ -77,7 +77,7 @@ class RuleFormRequest extends Request $data['rule-actions'][] = [ 'name' => $value, 'value' => $actionValues[$index] ?? '', - 'stop-processing' => (int)($actionStop[$index] ?? 0) === 1, + 'stop-processing' => 1 === (int)($actionStop[$index] ?? 0), ]; } } diff --git a/app/Http/Requests/RuleGroupFormRequest.php b/app/Http/Requests/RuleGroupFormRequest.php index dc2dc06ffd..dfe36c4514 100644 --- a/app/Http/Requests/RuleGroupFormRequest.php +++ b/app/Http/Requests/RuleGroupFormRequest.php @@ -32,7 +32,7 @@ class RuleGroupFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -52,7 +52,7 @@ class RuleGroupFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed /** @var RuleGroupRepositoryInterface $repository */ diff --git a/app/Http/Requests/SelectTransactionsRequest.php b/app/Http/Requests/SelectTransactionsRequest.php index 249613892a..8473d0d465 100644 --- a/app/Http/Requests/SelectTransactionsRequest.php +++ b/app/Http/Requests/SelectTransactionsRequest.php @@ -33,7 +33,7 @@ class SelectTransactionsRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -42,7 +42,7 @@ class SelectTransactionsRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed $sessionFirst = clone session('first'); diff --git a/app/Http/Requests/SplitJournalFormRequest.php b/app/Http/Requests/SplitJournalFormRequest.php index 5e1a4d062f..ec7b6316a3 100644 --- a/app/Http/Requests/SplitJournalFormRequest.php +++ b/app/Http/Requests/SplitJournalFormRequest.php @@ -154,7 +154,7 @@ class SplitJournalFormRequest extends Request $transactions = $data['transactions'] ?? []; /** @var array $array */ foreach ($transactions as $array) { - if ($array['destination_id'] !== null && $array['source_id'] !== null && $array['destination_id'] === $array['source_id']) { + if (null !== $array['destination_id'] && null !== $array['source_id'] && $array['destination_id'] === $array['source_id']) { $validator->errors()->add('journal_source_id', trans('validation.source_equals_destination')); $validator->errors()->add('journal_destination_id', trans('validation.source_equals_destination')); } diff --git a/app/Http/Requests/TagFormRequest.php b/app/Http/Requests/TagFormRequest.php index 85a7acdb0c..7254280d65 100644 --- a/app/Http/Requests/TagFormRequest.php +++ b/app/Http/Requests/TagFormRequest.php @@ -32,7 +32,7 @@ class TagFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -68,13 +68,13 @@ class TagFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { /** @var TagRepositoryInterface $repository */ $repository = app(TagRepositoryInterface::class); $idRule = ''; $tagRule = 'required|min:1|uniqueObjectForUser:tags,tag'; - if (null !== $repository->find((int)$this->get('id'))->id) { + if (null !== $repository->findNull((int)$this->get('id'))) { $idRule = 'belongsToUser:tags'; $tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,' . $this->get('id'); } diff --git a/app/Http/Requests/TestRuleFormRequest.php b/app/Http/Requests/TestRuleFormRequest.php index c0f90fcd98..e8dadd3e00 100644 --- a/app/Http/Requests/TestRuleFormRequest.php +++ b/app/Http/Requests/TestRuleFormRequest.php @@ -31,7 +31,7 @@ class TestRuleFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class TestRuleFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed $validTriggers = array_keys(config('firefly.rule-triggers')); diff --git a/app/Http/Requests/TokenFormRequest.php b/app/Http/Requests/TokenFormRequest.php index fd247f593e..25909b3e7b 100644 --- a/app/Http/Requests/TokenFormRequest.php +++ b/app/Http/Requests/TokenFormRequest.php @@ -31,7 +31,7 @@ class TokenFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -40,7 +40,7 @@ class TokenFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Http/Requests/UserFormRequest.php b/app/Http/Requests/UserFormRequest.php index a8aea7bc69..c5827f6db3 100644 --- a/app/Http/Requests/UserFormRequest.php +++ b/app/Http/Requests/UserFormRequest.php @@ -31,7 +31,7 @@ class UserFormRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only allow logged in users return auth()->check(); @@ -53,7 +53,7 @@ class UserFormRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { return [ 'id' => 'required|exists:users,id', diff --git a/app/Http/Requests/UserRegistrationRequest.php b/app/Http/Requests/UserRegistrationRequest.php index c02a04f481..1095c434b2 100644 --- a/app/Http/Requests/UserRegistrationRequest.php +++ b/app/Http/Requests/UserRegistrationRequest.php @@ -31,7 +31,7 @@ class UserRegistrationRequest extends Request /** * @return bool */ - public function authorize() + public function authorize(): bool { // Only everybody return true; @@ -40,7 +40,7 @@ class UserRegistrationRequest extends Request /** * @return array */ - public function rules() + public function rules(): array { // fixed return [ diff --git a/app/Import/JobConfiguration/FakeJobConfiguration.php b/app/Import/JobConfiguration/FakeJobConfiguration.php index 3812a78d59..5408b030ad 100644 --- a/app/Import/JobConfiguration/FakeJobConfiguration.php +++ b/app/Import/JobConfiguration/FakeJobConfiguration.php @@ -73,9 +73,9 @@ class FakeJobConfiguration implements JobConfigurationInterface $artist = strtolower($data['artist'] ?? ''); $song = strtolower($data['song'] ?? ''); $album = strtolower($data['album'] ?? ''); - $applyRules = isset($data['apply_rules']) ? (int)$data['apply_rules'] === 1 : null; + $applyRules = isset($data['apply_rules']) ? 1 === (int)$data['apply_rules'] : null; $configuration = $this->importJob->configuration; - if ($artist === 'david bowie') { + if ('david bowie' === $artist) { // store artist $configuration['artist'] = $artist; } diff --git a/app/Import/Object/ImportAccount.php b/app/Import/Object/ImportAccount.php deleted file mode 100644 index fdfef58293..0000000000 --- a/app/Import/Object/ImportAccount.php +++ /dev/null @@ -1,479 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Import\Object; - -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; -use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\User; -use Log; - -/** - * @deprecated - * @codeCoverageIgnore - * Class ImportAccount. - */ -class ImportAccount -{ - /** @var Account */ - private $account; - /** @var array */ - private $accountBic = []; - /** @var array */ - private $accountIban = []; - /** @var array */ - private $accountId = []; - /** @var array */ - private $accountName = []; - /** @var array */ - private $accountNumber = []; - /** @var int */ - private $defaultAccountId = 0; - /** @var string */ - private $expectedType; - /** - * This value is used to indicate the other account ID (the opposing transaction's account), - * if it is know. If so, this particular import account may never return an Account with this ID. - * If it would, this would result in a transaction from-to the same account. - * - * @var int - */ - private $forbiddenAccountId = 0; - /** @var AccountRepositoryInterface */ - private $repository; - /** @var User */ - private $user; - - /** - * ImportAccount constructor. - */ - public function __construct() - { - $this->expectedType = AccountType::ASSET; - $this->repository = app(AccountRepositoryInterface::class); - Log::debug('Created ImportAccount.'); - } - - /** - * @return Account - * - * @throws FireflyException - */ - public function getAccount(): Account - { - if (null === $this->account) { - $this->store(); - } - - return $this->account; - } - - /** - * @codeCoverageIgnore - * - * @return string - */ - public function getExpectedType(): string - { - return $this->expectedType; - } - - /** - * @codeCoverageIgnore - * - * @param string $expectedType - */ - public function setExpectedType(string $expectedType) - { - $this->expectedType = $expectedType; - } - - /** - * @param array $accountBic - */ - public function setAccountBic(array $accountBic): void - { - $this->accountBic = $accountBic; - } - - /** - * @codeCoverageIgnore - * - * @param array $accountIban - */ - public function setAccountIban(array $accountIban) - { - $this->accountIban = $accountIban; - } - - /** - * @codeCoverageIgnore - * - * @param array $value - */ - public function setAccountId(array $value) - { - $this->accountId = $value; - } - - /** - * @codeCoverageIgnore - * - * @param array $accountName - */ - public function setAccountName(array $accountName) - { - $this->accountName = $accountName; - } - - /** - * @codeCoverageIgnore - * - * @param array $accountNumber - */ - public function setAccountNumber(array $accountNumber) - { - $this->accountNumber = $accountNumber; - } - - /** - * @codeCoverageIgnore - * - * @param int $defaultAccountId - */ - public function setDefaultAccountId(int $defaultAccountId) - { - $this->defaultAccountId = $defaultAccountId; - } - - /** - * @codeCoverageIgnore - * - * @param int $forbiddenAccountId - */ - public function setForbiddenAccountId(int $forbiddenAccountId) - { - $this->forbiddenAccountId = $forbiddenAccountId; - } - - /** - * @codeCoverageIgnore - * - * @param User $user - */ - public function setUser(User $user) - { - $this->user = $user; - $this->repository->setUser($user); - } - - /** - * Find account by IBAN and type. - * - * @param AccountType $type - * - * @return Account|null - */ - private function findByIBAN(AccountType $type): ?Account - { - if (3 === \count($this->accountIban)) { - $accounts = $this->repository->getAccountsByType([$type->type]); - $iban = $this->accountIban['value']; - Log::debug(sprintf('Finding account of type %d and IBAN %s', $type->id, $iban)); - $filtered = $accounts->filter( - function (Account $account) use ($iban) { - if ($account->iban === $iban && $account->id !== $this->forbiddenAccountId) { - Log::debug( - sprintf( - 'Found unmapped %s account by IBAN (#%d): %s (%s)', - $this->expectedType, $account->id, $account->name, $account->iban - ) - ); - - return $account; - } - - return null; - } - ); - if (1 === $filtered->count()) { - return $filtered->first(); - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * Find account of type X by its ID. - * - * @param AccountType $type - * - * @return Account|null - */ - private function findById(AccountType $type): ?Account - { - if (3 === \count($this->accountId)) { - Log::debug(sprintf('Finding account of type %d and ID %d', $type->id, $this->accountId['value'])); - /** @var Account $account */ - $account = $this->user->accounts() - ->where('id', '!=', $this->forbiddenAccountId) - ->where('account_type_id', $type->id) - ->where('id', $this->accountId['value']) - ->first(); - - if (null !== $account) { - Log::debug(sprintf('Found unmapped %s account by ID (#%d): %s', $this->expectedType, $account->id, $account->name)); - - return $account; - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * Find account by account type and name. - * - * @param AccountType $type - * - * @return Account|null - */ - private function findByName(AccountType $type): ?Account - { - // Three: find by name (and type): - if (3 === \count($this->accountName)) { - $accounts = $this->repository->getAccountsByType([$type->type]); - $name = $this->accountName['value']; - Log::debug(sprintf('Finding account of type %d and name %s', $type->id, $name)); - $filtered = $accounts->filter( - function (Account $account) use ($name) { - if ($account->name === $name && $account->id !== $this->forbiddenAccountId) { - Log::debug(sprintf('Found unmapped %s account by name (#%d): %s', $this->expectedType, $account->id, $account->name)); - - return $account; - } - - return null; - } - ); - - if (1 === $filtered->count()) { - return $filtered->first(); - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * Determin account type to find, then use fields in object to try and find it. - * - * @return Account|null - */ - private function findExistingObject(): ?Account - { - Log::debug('In findExistingObject() for Account'); - /** @var AccountType $accountType */ - $accountType = $this->repository->getAccountType($this->expectedType); - $result = $this->findById($accountType); - if (null !== $result) { - return $result; - } - - $result = $this->findByIBAN($accountType); - - if (null !== $result) { - return $result; - } - - $result = $this->findByName($accountType); - - if (null !== $result) { - return $result; - } - - Log::debug('Found NO existing accounts.'); - - return null; - } - - /** - * @return Account|null - */ - private function findMappedObject(): ?Account - { - Log::debug('In findMappedObject() for Account'); - $fields = ['accountId', 'accountIban', 'accountNumber', 'accountName']; - foreach ($fields as $field) { - $array = $this->$field; - Log::debug(sprintf('Find mapped account based on field "%s" with value', $field), $array); - // check if a pre-mapped object exists. - $mapped = $this->getMappedObject($array); - if (null !== $mapped) { - Log::debug(sprintf('Found account #%d!', $mapped->id)); - - return $mapped; - } - } - Log::debug('Found no account on mapped data or no map present.'); - - return null; - } - - /** - * @param array $array - * - * @return Account|null - */ - private function getMappedObject(array $array): ?Account - { - Log::debug('In getMappedObject() for Account'); - if (0 === \count($array)) { - Log::debug('Array is empty, nothing will come of this.'); - - return null; - } - - if (array_key_exists('mapped', $array) && null === $array['mapped']) { - Log::debug(sprintf('No map present for value "%s". Return NULL.', $array['value'])); - - return null; - } - - Log::debug('Finding a mapped account based on', $array); - - $search = (int)($array['mapped'] ?? 0.0); - $account = $this->repository->findNull($search); - - if (null === $account) { - Log::error(sprintf('There is no account with id #%d. Invalid mapping will be ignored!', $search)); - - return null; - } - // must be of the same type - // except when mapped is an asset, then it's fair game. - // which only shows that user must map very carefully. - if ($account->accountType->type !== $this->expectedType && AccountType::ASSET !== $account->accountType->type) { - Log::error( - sprintf( - 'Mapped account #%d is of type "%s" but we expect a "%s"-account. Mapping will be ignored.', - $account->id, - $account->accountType->type, - $this->expectedType - ) - ); - - return null; - } - - Log::debug(sprintf('Found account! #%d ("%s"). Return it', $account->id, $account->name)); - - return $account; - } - - /** - * @return bool - * - * @throws FireflyException - */ - private function store(): bool - { - if (null === $this->user) { - throw new FireflyException('ImportAccount cannot continue without user.'); - } - if ((null === $this->defaultAccountId || 0 === (int)$this->defaultAccountId) && AccountType::ASSET === $this->expectedType) { - throw new FireflyException('ImportAccount cannot continue without a default account to fall back on.'); - } - // 1: find mapped object: - $mapped = $this->findMappedObject(); - if (null !== $mapped) { - $this->account = $mapped; - - return true; - } - // 2: find existing by given values: - $found = $this->findExistingObject(); - if (null !== $found) { - $this->account = $found; - - return true; - } - - // 3: if found nothing, retry the search with an asset account: - Log::debug('Will try to find an asset account just in case.'); - $oldExpectedType = $this->expectedType; - $this->expectedType = AccountType::ASSET; - $found = $this->findExistingObject(); - if (null !== $found) { - Log::debug('Found asset account!'); - $this->account = $found; - - return true; - } - $this->expectedType = $oldExpectedType; - - // 4: if search for an asset account, fall back to given "default account" (mandatory) - if (AccountType::ASSET === $this->expectedType) { - $this->account = $this->repository->findNull($this->defaultAccountId); - Log::debug(sprintf('Fall back to default account #%d "%s"', $this->account->id, $this->account->name)); - - return true; - } - - // 5: then maybe, create one: - Log::debug(sprintf('Found no account of type %s so must create one ourselves.', $this->expectedType)); - - // make sure name field is sensible. - $name = '(no name)'; - if (isset($this->accountNumber['value'])) { - $name = $this->accountNumber['value']; - } - if (isset($this->accountIban['value'])) { - $name = $this->accountIban['value']; - } - if (isset($this->accountName['value'])) { - $name = $this->accountName['value']; - } - - $data = [ - 'accountType' => config('firefly.shortNamesByFullName.' . $this->expectedType), - 'name' => $name, - 'iban' => $this->accountIban['value'] ?? null, - 'active' => true, - 'accountNumber' => $this->accountNumber['value'] ?? null, - 'virtualBalance' => '0', - 'account_type_id' => null, - 'BIC' => $this->accountBic['value'] ?? null, - ]; - - $this->account = $this->repository->store($data); - Log::debug(sprintf('Successfully stored new account #%d: %s', $this->account->id, $this->account->name)); - - return true; - } -} diff --git a/app/Import/Object/ImportBill.php b/app/Import/Object/ImportBill.php deleted file mode 100644 index 5222334aa6..0000000000 --- a/app/Import/Object/ImportBill.php +++ /dev/null @@ -1,290 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Import\Object; - -use FireflyIII\Models\Bill; -use FireflyIII\Repositories\Bill\BillRepositoryInterface; -use FireflyIII\User; -use Log; -use Steam; - -/** - * @deprecated - * @codeCoverageIgnore - * Class ImportBill. - */ -class ImportBill -{ - /** @var string */ - private $amount = '1'; - /** @var Bill */ - private $bill; - /** @var array */ - private $id = []; - /** @var array */ - private $name = []; - /** @var BillRepositoryInterface */ - private $repository; - /** @var User */ - private $user; - - /** - * ImportBill constructor. - */ - public function __construct() - { - $this->repository = app(BillRepositoryInterface::class); - Log::debug('Created ImportBill.'); - } - - /** - * @return Bill|null - */ - public function getBill(): ?Bill - { - if (null === $this->bill) { - $this->store(); - } - - return $this->bill; - } - - /** - * @param string $amount - */ - public function setAmount(string $amount) - { - $this->amount = Steam::positive($amount); - } - - /** - * @param array $id - */ - public function setId(array $id) - { - $this->id = $id; - } - - /** - * @param array $name - */ - public function setName(array $name) - { - $this->name = $name; - } - - /** - * @param User $user - */ - public function setUser(User $user) - { - $this->user = $user; - $this->repository->setUser($user); - } - - /** - * @return Bill|null - */ - private function findById(): ?Bill - { - if (3 === \count($this->id)) { - Log::debug(sprintf('Finding bill with ID #%d', $this->id['value'])); - /** @var Bill $bill */ - $bill = $this->repository->find((int)$this->id['value']); - if (null !== $bill) { - Log::debug(sprintf('Found unmapped bill by ID (#%d): %s', $bill->id, $bill->name)); - - return $bill; - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * @return Bill|null - */ - private function findByName(): ?Bill - { - if (3 === \count($this->name)) { - $bills = $this->repository->getBills(); - $name = $this->name['value']; - Log::debug(sprintf('Finding bill with name %s', $name)); - $filtered = $bills->filter( - function (Bill $bill) use ($name) { - if ($bill->name === $name) { - Log::debug(sprintf('Found unmapped bill by name (#%d): %s', $bill->id, $bill->name)); - - return $bill; - } - - return null; - } - ); - - if (1 === $filtered->count()) { - return $filtered->first(); - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * @return Bill|null - */ - private function findExistingObject(): ?Bill - { - Log::debug('In findExistingObject() for Bill'); - $result = $this->findById(); - if (null !== $result) { - return $result; - } - $result = $this->findByName(); - if (null !== $result) { - return $result; - } - - Log::debug('Found NO existing bills.'); - - return null; - } - - /** - * @return Bill|null - */ - private function findMappedObject(): ?Bill - { - Log::debug('In findMappedObject() for Bill'); - $fields = ['id', 'name']; - foreach ($fields as $field) { - $array = $this->$field; - Log::debug(sprintf('Find mapped bill based on field "%s" with value', $field), $array); - // check if a pre-mapped object exists. - $mapped = $this->getMappedObject($array); - if (null !== $mapped) { - Log::debug(sprintf('Found bill #%d!', $mapped->id)); - - return $mapped; - } - } - Log::debug('Found no bill on mapped data or no map present.'); - - return null; - } - - /** - * @param array $array - * - * @return Bill - */ - private function getMappedObject(array $array): ?Bill - { - Log::debug('In getMappedObject() for Bill'); - if (0 === \count($array)) { - Log::debug('Array is empty, nothing will come of this.'); - - return null; - } - - if (array_key_exists('mapped', $array) && null === $array['mapped']) { - Log::debug(sprintf('No map present for value "%s". Return NULL.', $array['value'])); - - return null; - } - - Log::debug('Finding a mapped bill based on', $array); - - $search = (int)$array['mapped']; - $bill = $this->repository->find($search); - - if (null === $bill) { - Log::error(sprintf('There is no bill with id #%d. Invalid mapping will be ignored!', $search)); - - return null; - } - - Log::debug(sprintf('Found bill! #%d ("%s"). Return it', $bill->id, $bill->name)); - - return $bill; - } - - /** - * @return bool - */ - private function store(): bool - { - // 1: find mapped object: - $mapped = $this->findMappedObject(); - if (null !== $mapped) { - $this->bill = $mapped; - - return true; - } - // 2: find existing by given values: - $found = $this->findExistingObject(); - if (null !== $found) { - $this->bill = $found; - - return true; - } - $name = $this->name['value'] ?? ''; - - if (0 === \strlen($name)) { - return true; - } - - $data = [ - 'name' => $name, - 'match' => $name, - 'amount_min' => bcmul($this->amount, '0.9'), - 'amount_max' => bcmul($this->amount, '1.1'), - 'user_id' => $this->user->id, - 'date' => date('Y-m-d'), - 'repeat_freq' => 'monthly', - 'skip' => '0', - 'transaction_currency_id' => 1, - 'automatch' => '0', - 'active' => '1', - ]; - - $currency = app('amount')->getDefaultCurrencyByUser($this->user); - if (null !== $currency) { - $data['transaction_currency_id'] = $currency->id; - } - - Log::debug('Found no bill so must create one ourselves. Assume default values.', $data); - $result = $this->repository->store($data); - if (null !== $result) { - $this->bill = $result; - Log::debug(sprintf('Successfully stored new bill #%d: %s', $this->bill->id, $this->bill->name)); - } - if (null === $result) { - Log::error('Could not store new bill.'); - } - - return true; - } -} diff --git a/app/Import/Object/ImportBudget.php b/app/Import/Object/ImportBudget.php deleted file mode 100644 index 55f4e6e559..0000000000 --- a/app/Import/Object/ImportBudget.php +++ /dev/null @@ -1,259 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Import\Object; - -use FireflyIII\Models\Budget; -use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\User; -use Log; - -/** - * @deprecated - * @codeCoverageIgnore - * Class ImportBudget. - */ -class ImportBudget -{ - /** @var Budget */ - private $budget; - /** @var array */ - private $id = []; - /** @var array */ - private $name = []; - /** @var BudgetRepositoryInterface */ - private $repository; - /** @var User */ - private $user; - - /** - * ImportBudget constructor. - */ - public function __construct() - { - $this->repository = app(BudgetRepositoryInterface::class); - Log::debug('Created ImportBudget.'); - } - - /** - * @return Budget|null - */ - public function getBudget(): ?Budget - { - if (null === $this->budget) { - $this->store(); - } - - return $this->budget; - } - - /** - * @param array $id - */ - public function setId(array $id) - { - $this->id = $id; - } - - /** - * @param array $name - */ - public function setName(array $name) - { - $this->name = $name; - } - - /** - * @param User $user - */ - public function setUser(User $user) - { - $this->user = $user; - $this->repository->setUser($user); - } - - /** - * @return Budget|null - */ - private function findById(): ?Budget - { - if (3 === \count($this->id)) { - Log::debug(sprintf('Finding budget with ID #%d', $this->id['value'])); - /** @var Budget $budget */ - $budget = $this->repository->findNull((int)$this->id['value']); - if (null !== $budget) { - Log::debug(sprintf('Found unmapped budget by ID (#%d): %s', $budget->id, $budget->name)); - - return $budget; - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * @return Budget|null - */ - private function findByName(): ?Budget - { - if (3 === \count($this->name)) { - $budgets = $this->repository->getBudgets(); - $name = $this->name['value']; - Log::debug(sprintf('Finding budget with name %s', $name)); - $filtered = $budgets->filter( - function (Budget $budget) use ($name) { - if ($budget->name === $name) { - Log::debug(sprintf('Found unmapped budget by name (#%d): %s', $budget->id, $budget->name)); - - return $budget; - } - - return null; - } - ); - - if (1 === $filtered->count()) { - return $filtered->first(); - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * @return Budget - */ - private function findExistingObject(): ?Budget - { - Log::debug('In findExistingObject() for Budget'); - $result = $this->findById(); - if (null !== $result) { - return $result; - } - $result = $this->findByName(); - if (null !== $result) { - return $result; - } - - Log::debug('Found NO existing budgets.'); - - return null; - } - - /** - * @return Budget - */ - private function findMappedObject(): ?Budget - { - Log::debug('In findMappedObject() for Budget'); - $fields = ['id', 'name']; - foreach ($fields as $field) { - $array = $this->$field; - Log::debug(sprintf('Find mapped budget based on field "%s" with value', $field), $array); - // check if a pre-mapped object exists. - $mapped = $this->getMappedObject($array); - if (null !== $mapped) { - Log::debug(sprintf('Found budget #%d!', $mapped->id)); - - return $mapped; - } - } - Log::debug('Found no budget on mapped data or no map present.'); - - return null; - } - - /** - * @param array $array - * - * @return Budget - */ - private function getMappedObject(array $array): ?Budget - { - Log::debug('In getMappedObject() for Budget'); - if (0 === \count($array)) { - Log::debug('Array is empty, nothing will come of this.'); - - return null; - } - - if (array_key_exists('mapped', $array) && null === $array['mapped']) { - Log::debug(sprintf('No map present for value "%s". Return NULL.', $array['value'])); - - return null; - } - - Log::debug('Finding a mapped budget based on', $array); - - $search = (int)$array['mapped']; - $budget = $this->repository->find($search); - - if (null === $budget->id) { - Log::error(sprintf('There is no budget with id #%d. Invalid mapping will be ignored!', $search)); - - return null; - } - - Log::debug(sprintf('Found budget! #%d ("%s"). Return it', $budget->id, $budget->name)); - - return $budget; - } - - /** - * @return bool - */ - private function store(): bool - { - // 1: find mapped object: - $mapped = $this->findMappedObject(); - if (null !== $mapped) { - $this->budget = $mapped; - - return true; - } - // 2: find existing by given values: - $found = $this->findExistingObject(); - if (null !== $found) { - $this->budget = $found; - - return true; - } - $name = $this->name['value'] ?? ''; - - if (0 === \strlen($name)) { - return true; - } - - Log::debug('Found no budget so must create one ourselves.'); - - $data = [ - 'name' => $name, - ]; - - $this->budget = $this->repository->store($data); - Log::debug(sprintf('Successfully stored new budget #%d: %s', $this->budget->id, $this->budget->name)); - - return true; - } -} diff --git a/app/Import/Object/ImportCategory.php b/app/Import/Object/ImportCategory.php deleted file mode 100644 index bcdf0a9477..0000000000 --- a/app/Import/Object/ImportCategory.php +++ /dev/null @@ -1,260 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Import\Object; - -use FireflyIII\Models\Category; -use FireflyIII\Repositories\Category\CategoryRepositoryInterface; -use FireflyIII\User; -use Log; - -/** - * @deprecated - * @codeCoverageIgnore - * Class ImportCategory - */ -class ImportCategory -{ - /** @var Category */ - private $category; - /** @var array */ - private $id = []; - /** @var array */ - private $name = []; - /** @var CategoryRepositoryInterface */ - private $repository; - /** @var User */ - private $user; - - /** - * ImportCategory constructor. - */ - public function __construct() - { - $this->repository = app(CategoryRepositoryInterface::class); - Log::debug('Created ImportCategory.'); - } - - /** - * @return null|Category - */ - public function getCategory(): ?Category - { - if (null === $this->category) { - $this->store(); - } - - return $this->category; - } - - /** - * @param array $id - */ - public function setId(array $id) - { - $this->id = $id; - } - - /** - * @param array $name - */ - public function setName(array $name) - { - $this->name = $name; - } - - /** - * @param User $user - */ - public function setUser(User $user) - { - $this->user = $user; - $this->repository->setUser($user); - } - - /** - * Find category by ID. - * - * @return Category|null - */ - private function findById(): ?Category - { - if (3 === \count($this->id)) { - Log::debug(sprintf('Finding category with ID #%d', $this->id['value'])); - /** @var Category $category */ - $category = $this->repository->findNull((int)$this->id['value']); - if (null !== $category) { - Log::debug(sprintf('Found unmapped category by ID (#%d): %s', $category->id, $category->name)); - - return $category; - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * Find category by name. - * - * @return Category|null - */ - private function findByName(): ?Category - { - if (3 === \count($this->name)) { - $categories = $this->repository->getCategories(); - $name = $this->name['value']; - Log::debug(sprintf('Finding category with name %s', $name)); - $filtered = $categories->filter( - function (Category $category) use ($name) { - if ($category->name === $name) { - Log::debug(sprintf('Found unmapped category by name (#%d): %s', $category->id, $category->name)); - - return $category; - } - - return null; - } - ); - - if (1 === $filtered->count()) { - return $filtered->first(); - } - Log::debug('Found nothing.'); - } - - return null; - } - - /** - * @return Category - */ - private function findExistingObject(): ?Category - { - Log::debug('In findExistingObject() for Category'); - $result = $this->findById(); - if (null !== $result) { - return $result; - } - - $result = $this->findByName(); - if (null !== $result) { - return $result; - } - - Log::debug('Found NO existing categories.'); - - return null; - } - - /** - * @return Category - */ - private function findMappedObject(): ?Category - { - Log::debug('In findMappedObject() for Category'); - $fields = ['id', 'name']; - foreach ($fields as $field) { - $array = $this->$field; - Log::debug(sprintf('Find mapped category based on field "%s" with value', $field), $array); - // check if a pre-mapped object exists. - $mapped = $this->getMappedObject($array); - if (null !== $mapped) { - Log::debug(sprintf('Found category #%d!', $mapped->id)); - - return $mapped; - } - } - Log::debug('Found no category on mapped data or no map present.'); - - return null; - } - - /** - * @param array $array - * - * @return Category - */ - private function getMappedObject(array $array): ?Category - { - Log::debug('In getMappedObject() for Category'); - if (0 === \count($array)) { - Log::debug('Array is empty, nothing will come of this.'); - - return null; - } - - if (array_key_exists('mapped', $array) && null === $array['mapped']) { - Log::debug(sprintf('No map present for value "%s". Return NULL.', $array['value'])); - - return null; - } - - Log::debug('Finding a mapped category based on', $array); - - $search = (int)$array['mapped']; - $category = $this->repository->findNull($search); - - if (null === $category) { - Log::error(sprintf('There is no category with id #%d. Invalid mapping will be ignored!', $search)); - - return null; - } - - Log::debug(sprintf('Found category! #%d ("%s"). Return it', $category->id, $category->name)); - - return $category; - } - - /** - * @return bool - */ - private function store(): bool - { - // 1: find mapped object: - $mapped = $this->findMappedObject(); - if (null !== $mapped) { - $this->category = $mapped; - - return true; - } - // 2: find existing by given values: - $found = $this->findExistingObject(); - if (null !== $found) { - $this->category = $found; - - return true; - } - $name = $this->name['value'] ?? ''; - - if (0 === \strlen($name)) { - return true; - } - - Log::debug('Found no category so must create one ourselves.'); - - $this->category = $this->repository->store(['name' => $name]); - Log::debug(sprintf('Successfully stored new category #%d: %s', $this->category->id, $this->category->name)); - - return true; - } -} diff --git a/app/Import/Object/ImportCurrency.php b/app/Import/Object/ImportCurrency.php deleted file mode 100644 index b570632064..0000000000 --- a/app/Import/Object/ImportCurrency.php +++ /dev/null @@ -1,233 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Import\Object; - -use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use FireflyIII\User; -use Log; - -/** - * @deprecated - * @codeCoverageIgnore - * Class ImportCurrency - */ -class ImportCurrency -{ - /** @var array */ - private $code = []; - /** @var TransactionCurrency */ - private $currency; - /** @var array */ - private $id = []; - /** @var array */ - private $name = []; - /** @var CurrencyRepositoryInterface */ - private $repository; - /** @var array */ - private $symbol = []; - /** @var User */ - private $user; - - /** - * ImportCurrency constructor. - */ - public function __construct() - { - $this->repository = app(CurrencyRepositoryInterface::class); - } - - /** - * @return TransactionCurrency - */ - public function getTransactionCurrency(): ?TransactionCurrency - { - if (null !== $this->currency) { - return $this->currency; - } - Log::debug('In createCurrency()'); - // check if any of them is mapped: - $mapped = $this->findMappedObject(); - - if (null !== $mapped) { - Log::debug('Mapped existing currency.', ['new' => $mapped->toArray()]); - $this->currency = $mapped; - - return $mapped; - } - - $searched = $this->findExistingObject(); - if (null !== $searched) { - Log::debug('Found existing currency.', ['found' => $searched->toArray()]); - $this->currency = $searched; - - return $searched; - } - $data = [ - 'code' => $this->code['value'] ?? null, - 'symbol' => $this->symbol['value'] ?? null, - 'name' => $this->name['value'] ?? null, - 'decimal_places' => 2, - ]; - if (null === $data['code']) { - Log::debug('Need at least a code to create currency, return nothing.'); - - return null; - } - - Log::debug('Search for maps resulted in nothing, create new one based on', $data); - $currency = $this->repository->store($data); - $this->currency = $currency; - Log::info('Made new currency.', ['input' => $data, 'new' => $currency->toArray()]); - - return $currency; - } - - /** - * @param array $code - */ - public function setCode(array $code) - { - $this->code = $code; - } - - /** - * @param array $id - */ - public function setId(array $id) - { - $id['value'] = (int)$id['value']; - $this->id = $id; - } - - /** - * @param array $name - */ - public function setName(array $name) - { - $this->name = $name; - } - - /** - * @param array $symbol - */ - public function setSymbol(array $symbol) - { - $this->symbol = $symbol; - } - - /** - * @param User $user - */ - public function setUser(User $user) - { - $this->user = $user; - $this->repository->setUser($user); - } - - /** - * @return TransactionCurrency - */ - private function findExistingObject(): ?TransactionCurrency - { - $search = [ - 'id' => 'findNull', - 'code' => 'findByCodeNull', - 'symbol' => 'findBySymbolNull', - 'name' => 'findByNameNull', - ]; - foreach ($search as $field => $function) { - $value = $this->$field['value'] ?? null; - if (null !== $value) { - Log::debug(sprintf('Searching for %s using function %s and value %s', $field, $function, $value)); - /** @var TransactionCurrency|null $currency */ - $currency = $this->repository->$function($value); - - if (null !== $currency) { - return $currency; - } - } - } - - return null; - } - - /** - * @return TransactionCurrency - */ - private function findMappedObject(): ?TransactionCurrency - { - Log::debug('In findMappedObject()'); - $fields = ['id', 'code', 'name', 'symbol']; - foreach ($fields as $field) { - $array = $this->$field; - Log::debug(sprintf('Find mapped currency based on field "%s" with value', $field), $array); - // check if a pre-mapped object exists. - $mapped = $this->getMappedObject($array); - if (null !== $mapped) { - Log::debug(sprintf('Found currency #%d!', $mapped->id)); - - return $mapped; - } - } - Log::debug('Found no currency on mapped data or no map present.'); - - return null; - } - - /** - * @param array $array - * - * @return TransactionCurrency - */ - private function getMappedObject(array $array): ?TransactionCurrency - { - Log::debug('In getMappedObject()'); - if (0 === \count($array)) { - Log::debug('Array is empty, nothing will come of this.'); - - return null; - } - - if (array_key_exists('mapped', $array) && null === $array['mapped']) { - Log::debug(sprintf('No map present for value "%s". Return NULL.', $array['value'])); - - return null; - } - - Log::debug('Finding a mapped object based on', $array); - - $search = (int)$array['mapped']; - $currency = $this->repository->findNull($search); - - if (null === $currency) { - Log::error(sprintf('There is no currency with id #%d. Invalid mapping will be ignored!', $search)); - - return null; - } - - Log::debug(sprintf('Found currency! #%d ("%s"). Return it', $currency->id, $currency->name)); - - return $currency; - } -} diff --git a/app/Import/Object/ImportJournal.php b/app/Import/Object/ImportJournal.php deleted file mode 100644 index c4e96db676..0000000000 --- a/app/Import/Object/ImportJournal.php +++ /dev/null @@ -1,491 +0,0 @@ -. - */ -declare(strict_types=1); - -namespace FireflyIII\Import\Object; - -use Carbon\Carbon; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Import\Converter\Amount; -use FireflyIII\Import\Converter\ConverterInterface; -use FireflyIII\Import\MapperPreProcess\PreProcessorInterface; -use FireflyIII\User; -use InvalidArgumentException; -use Log; -use Steam; - -/** - * @deprecated - * @codeCoverageIgnore - * Class ImportJournal. - */ -class ImportJournal -{ - - /** @var ImportAccount */ - public $asset; - /** @var ImportBill */ - public $bill; - /** @var ImportBudget */ - public $budget; - /** @var ImportCategory */ - public $category; - /** @var ImportCurrency */ - public $currency; - /** @var string */ - public $description = ''; - /** @var ImportCurrency */ - public $foreignCurrency; - /** @var string */ - public $hash; - /** @var array */ - public $metaDates = []; - /** @var array */ - public $metaFields = []; - /** @var string */ - public $notes = ''; - /** @var ImportAccount */ - public $opposing; - /** @var array */ - public $tags = []; - /** @var array */ - private $amount; - /** @var array */ - private $amountCredit; - /** @var array */ - private $amountDebit; - /** @var string */ - private $convertedAmount; - /** @var string */ - private $date = ''; - /** @var string */ - private $externalId = ''; - /** @var array */ - private $foreignAmount; - /** @var array */ - private $modifiers = []; - /** @var User */ - private $user; - - /** - * ImportEntry constructor. - */ - public function __construct() - { - $this->asset = new ImportAccount; - $this->opposing = new ImportAccount; - $this->bill = new ImportBill; - $this->category = new ImportCategory; - $this->budget = new ImportBudget; - $this->currency = new ImportCurrency; - $this->foreignCurrency = new ImportCurrency; - } - - /** - * @param array $modifier - */ - public function addToModifier(array $modifier) - { - $this->modifiers[] = $modifier; - } - - /** - * @return string - * - * @throws FireflyException - */ - public function getAmount(): string - { - Log::debug('Now in getAmount()'); - Log::debug(sprintf('amount is %s', var_export($this->amount, true))); - Log::debug(sprintf('debit amount is %s', var_export($this->amountDebit, true))); - Log::debug(sprintf('credit amount is %s', var_export($this->amountCredit, true))); - - if (null === $this->convertedAmount) { - $this->calculateAmount(); - } - Log::debug(sprintf('convertedAmount is: "%s"', $this->convertedAmount)); - if (0 === bccomp($this->convertedAmount, '0')) { - throw new FireflyException('Amount is zero.'); - } - - return $this->convertedAmount; - } - - /** - * @param string $format - * - * @return Carbon - */ - public function getDate(string $format): Carbon - { - $date = new Carbon; - try { - $date = Carbon::createFromFormat($format, $this->date); - } catch (InvalidArgumentException $e) { - // don't care, just log. - Log::error(sprintf('Import journal cannot parse date "%s" from value "%s" so will return current date instead.', $format, $this->date)); - } - - return $date; - } - - /** - * @return string - */ - public function getDescription(): string - { - if ('' === $this->description) { - return '(no description)'; - } - - return $this->description; - } - - /** - * @return string - */ - public function getExternalId(): string - { - return $this->externalId; - } - - /** - * @return string|null - */ - public function getForeignAmount(): ?string - { - Log::debug('Now in getForeignAmount()'); - Log::debug(sprintf('foreign amount is %s', var_export($this->foreignAmount, true))); - - // no foreign amount? return null - if (null === $this->foreignAmount) { - Log::debug('Return NULL for foreign amount'); - - return null; - } - // converter is default amount converter: no special stuff - $converter = app(Amount::class); - $amount = $converter->convert($this->foreignAmount['value']); - Log::debug(sprintf('First attempt to convert foreign gives "%s"', $amount)); - // modify - foreach ($this->modifiers as $modifier) { - $class = sprintf('FireflyIII\Import\Converter\%s', config(sprintf('csv.import_roles.%s.converter', $modifier['role']))); - /** @var ConverterInterface $converter */ - $converter = app($class); - Log::debug(sprintf('Now launching converter %s', $class)); - if ($converter->convert($modifier['value']) === -1) { - $amount = Steam::negative($amount); - } - Log::debug(sprintf('Foreign amount after conversion is %s', $amount)); - } - - Log::debug(sprintf('After modifiers the result is: "%s"', $amount)); - - - Log::debug(sprintf('converted foreign amount is: "%s"', $amount)); - if (0 === bccomp($amount, '0')) { - return null; - } - - return $amount; - } - - /** - * Get date field or NULL - * - * @param string $field - * - * @return Carbon|null - */ - public function getMetaDate(string $field): ?Carbon - { - if (isset($this->metaDates[$field])) { - return new Carbon($this->metaDates[$field]); - } - - return null; - } - - /** - * Get string field or NULL - * - * @param string $field - * - * @return string|null - */ - public function getMetaString(string $field): ?string - { - if (isset($this->metaFields[$field]) && \strlen($this->metaFields[$field]) > 0) { - return (string)$this->metaFields[$field]; - } - - return null; - } - - /** - * @param string $hash - */ - public function setHash(string $hash) - { - $this->hash = $hash; - } - - /** - * @param User $user - */ - public function setUser(User $user) - { - $this->user = $user; - - // set user for related objects: - $this->asset->setUser($user); - $this->opposing->setUser($user); - $this->budget->setUser($user); - $this->category->setUser($user); - $this->bill->setUser($user); - } - - /** - * @param array $array - * - * @throws FireflyException - */ - public function setValue(array $array) - { - $array['mapped'] = $array['mapped'] ?? null; - $array['value'] = $array['value'] ?? null; - switch ($array['role']) { - default: - throw new FireflyException(sprintf('ImportJournal cannot handle "%s" with value "%s".', $array['role'], $array['value'])); - case 'account-id': - $this->asset->setAccountId($array); - break; - case 'sepa-cc': - case 'sepa-ct-op': - case 'sepa-ct-id': - case 'sepa-db': - case 'sepa-country': - case 'sepa-ep': - case 'sepa-ci': - $value = trim((string)$array['value']); - if (\strlen($value) > 0) { - $this->metaFields[$array['role']] = $value; - } - break; - case 'amount': - $this->amount = $array; - break; - case 'amount_foreign': - $this->foreignAmount = $array; - break; - case 'foreign-currency-code': - $this->foreignCurrency->setCode($array); - break; - case 'amount_debit': - $this->amountDebit = $array; - break; - case 'amount_credit': - $this->amountCredit = $array; - break; - case 'account-iban': - $this->asset->setAccountIban($array); - break; - case 'account-name': - $this->asset->setAccountName($array); - break; - case 'account-number': - $this->asset->setAccountNumber($array); - break; - case 'bill-id': - $this->bill->setId($array); - break; - case 'bill-name': - $this->bill->setName($array); - break; - case 'budget-id': - $this->budget->setId($array); - break; - case 'budget-name': - $this->budget->setName($array); - break; - case 'category-id': - $this->category->setId($array); - break; - case 'category-name': - $this->category->setName($array); - break; - case 'currency-code': - $this->currency->setCode($array); - break; - case 'currency-id': - $this->currency->setId($array); - break; - case 'currency-name': - $this->currency->setName($array); - break; - case 'currency-symbol': - $this->currency->setSymbol($array); - break; - case 'date-transaction': - $this->date = $array['value']; - break; - case 'description': - $this->description .= $array['value']; - break; - case 'note': - $this->notes .= ' ' . $array['value']; - $this->notes = trim($this->notes); - break; - case 'external-id': - $this->externalId = $array['value']; - break; - case 'internal-reference': - $this->metaFields['internal_reference'] = $array['value']; - break; - case '_ignore': - break; - case 'ing-debit-credit': - case 'rabo-debit-credit': - $this->addToModifier($array); - break; - case 'opposing-iban': - $this->opposing->setAccountIban($array); - break; - case 'opposing-name': - $this->opposing->setAccountName($array); - break; - case 'opposing-number': - $this->opposing->setAccountNumber($array); - break; - case 'opposing-id': - $this->opposing->setAccountId($array); - break; - case 'opposing-bic': - $this->opposing->setAccountBic($array); - break; - case 'tags-comma': - case 'tags-space': - $this->setTags($array); - break; - case 'date-interest': - $this->metaDates['interest_date'] = $array['value']; - break; - case 'date-book': - $this->metaDates['book_date'] = $array['value']; - break; - case 'date-process': - $this->metaDates['process_date'] = $array['value']; - break; - case 'date-due': - $this->metaDates['due_date'] = $array['value']; - break; - case 'date-payment': - $this->metaDates['payment_date'] = $array['value']; - break; - case 'date-invoice': - $this->metaDates['invoice_date'] = $array['value']; - break; - } - } - - /** - * If convertedAmount is NULL, this method will try to calculate the correct amount. - * It starts with amount, but can be overruled by debit and credit amounts. - * - * @throws FireflyException - */ - private function calculateAmount() - { - // first check if the amount is set: - Log::debug('convertedAmount is NULL'); - - $info = $this->selectAmountInput(); - - if (0 === \count($info)) { - throw new FireflyException('No amount information for this row.'); - } - $class = $info['class'] ?? ''; - if (0 === \strlen($class)) { - throw new FireflyException('No amount information (conversion class) for this row.'); - } - - Log::debug(sprintf('Converter class is %s', $info['class'])); - /** @var ConverterInterface $amountConverter */ - $amountConverter = app($info['class']); - $this->convertedAmount = $amountConverter->convert($info['value']); - Log::debug(sprintf('First attempt to convert gives "%s"', $this->convertedAmount)); - // modify - foreach ($this->modifiers as $modifier) { - $class = sprintf('FireflyIII\Import\Converter\%s', config(sprintf('csv.import_roles.%s.converter', $modifier['role']))); - /** @var ConverterInterface $converter */ - $converter = app($class); - Log::debug(sprintf('Now launching converter %s', $class)); - if ($converter->convert($modifier['value']) === -1) { - $this->convertedAmount = Steam::negative($this->convertedAmount); - } - Log::debug(sprintf('convertedAmount after conversion is %s', $this->convertedAmount)); - } - - Log::debug(sprintf('After modifiers the result is: "%s"', $this->convertedAmount)); - } - - /** - * This methods decides which input to use for the amount calculation. - * - * @return array - */ - private function selectAmountInput() - { - $info = []; - $converterClass = ''; - if (null !== $this->amount) { - Log::debug('Amount value is not NULL, assume this is the correct value.'); - $converterClass = sprintf('FireflyIII\Import\Converter\%s', config(sprintf('csv.import_roles.%s.converter', $this->amount['role']))); - $info = $this->amount; - } - if (null !== $this->amountDebit) { - Log::debug('Amount DEBIT value is not NULL, assume this is the correct value (overrules Amount).'); - $converterClass = sprintf('FireflyIII\Import\Converter\%s', config(sprintf('csv.import_roles.%s.converter', $this->amountDebit['role']))); - $info = $this->amountDebit; - } - if (null !== $this->amountCredit) { - Log::debug('Amount CREDIT value is not NULL, assume this is the correct value (overrules Amount and AmountDebit).'); - $converterClass = sprintf('FireflyIII\Import\Converter\%s', config(sprintf('csv.import_roles.%s.converter', $this->amountCredit['role']))); - $info = $this->amountCredit; - } - $info['class'] = $converterClass; - - return $info; - } - - /** - * @param array $array - */ - private function setTags(array $array): void - { - $preProcessorClass = config(sprintf('csv.import_roles.%s.pre-process-mapper', $array['role'])); - /** @var PreProcessorInterface $preProcessor */ - $preProcessor = app(sprintf('\FireflyIII\Import\MapperPreProcess\%s', $preProcessorClass)); - $tags = $preProcessor->run($array['value']); - $this->tags = array_merge($this->tags, $tags); - } -} diff --git a/app/Import/Routine/FileRoutine.php b/app/Import/Routine/FileRoutine.php index db228ac494..e88fe64456 100644 --- a/app/Import/Routine/FileRoutine.php +++ b/app/Import/Routine/FileRoutine.php @@ -48,7 +48,7 @@ class FileRoutine implements RoutineInterface public function run(): void { Log::debug(sprintf('Now in run() for file routine with status: %s', $this->importJob->status)); - if ($this->importJob->status === 'ready_to_run') { + if ('ready_to_run' === $this->importJob->status) { $this->repository->setStatus($this->importJob, 'running'); // get processor, depending on file type // is just CSV for now. diff --git a/app/Models/Account.php b/app/Models/Account.php index adcfb61dc7..81093d68c5 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -45,6 +45,12 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property bool $active * @property string $virtual_balance * @property User $user + * @property mixed|null startBalance + * @property mixed|null endBalance + * @property string difference + * @property mixed|null endBalance + * @property mixed|null startBalance + * @property mixed|null lastActivityDate */ class Account extends Model { diff --git a/app/Models/AccountMeta.php b/app/Models/AccountMeta.php index 7635b179dc..2dde72aa88 100644 --- a/app/Models/AccountMeta.php +++ b/app/Models/AccountMeta.php @@ -27,7 +27,10 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; /** * Class AccountMeta. + * * @property string $data + * @property string $name + * @property int $account_id */ class AccountMeta extends Model { diff --git a/app/Models/AccountType.php b/app/Models/AccountType.php index de1d5794cd..c4a1c4d19e 100644 --- a/app/Models/AccountType.php +++ b/app/Models/AccountType.php @@ -29,6 +29,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany; * Class AccountType. * * @property string $type + * @method whereType(string $type) + * @property int $id * */ class AccountType extends Model diff --git a/app/Models/Attachment.php b/app/Models/Attachment.php index c0d71a8fa7..913585ab8a 100644 --- a/app/Models/Attachment.php +++ b/app/Models/Attachment.php @@ -47,6 +47,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property int $size * @property User $user * @property bool $uploaded + * @property bool file_exists */ class Attachment extends Model { diff --git a/app/Models/Bill.php b/app/Models/Bill.php index 6693972b20..668f8f0d2d 100644 --- a/app/Models/Bill.php +++ b/app/Models/Bill.php @@ -50,6 +50,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property int $skip * @property bool $automatch * @property User $user + * @property string $match */ class Bill extends Model { diff --git a/app/Models/Budget.php b/app/Models/Budget.php index d3c0ff820d..eb46d21f79 100644 --- a/app/Models/Budget.php +++ b/app/Models/Budget.php @@ -35,6 +35,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property int $id * @property string $name * @property bool $active + * @property int $user_id + * @property-read string $email */ class Budget extends Model { diff --git a/app/Models/BudgetLimit.php b/app/Models/BudgetLimit.php index 7559c258b2..15f11689a2 100644 --- a/app/Models/BudgetLimit.php +++ b/app/Models/BudgetLimit.php @@ -37,6 +37,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property Carbon $start_date * @property Carbon $end_date * @property string $amount + * @property int $budget_id + * @property string spent */ class BudgetLimit extends Model { @@ -46,7 +48,7 @@ class BudgetLimit extends Model * @var array */ protected $casts - = [ + = [ 'created_at' => 'datetime', 'updated_at' => 'datetime', 'start_date' => 'date', diff --git a/app/Models/Category.php b/app/Models/Category.php index 5f06f91fbe..dd3a3fb818 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -32,8 +32,10 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class Category. * - * @property string $name - * @property int $id + * @property string $name + * @property int $id + * @property float $spent // used in category reports + * @property Carbon|null lastActivity */ class Category extends Model { diff --git a/app/Models/ExportJob.php b/app/Models/ExportJob.php index 5e671cc1f0..8b16e88730 100644 --- a/app/Models/ExportJob.php +++ b/app/Models/ExportJob.php @@ -31,6 +31,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * * @property User $user * @property string $key + * @property int $user_id + * @property mixed status */ class ExportJob extends Model { diff --git a/app/Models/ImportJob.php b/app/Models/ImportJob.php index 7a9759f263..58256cd9a5 100644 --- a/app/Models/ImportJob.php +++ b/app/Models/ImportJob.php @@ -40,6 +40,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property string $file_type * @property int $tag_id * @property Tag $tag + * @property array $errors */ class ImportJob extends Model { diff --git a/app/Models/Note.php b/app/Models/Note.php index 81ebc4a9ff..59d786d642 100644 --- a/app/Models/Note.php +++ b/app/Models/Note.php @@ -34,6 +34,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property Carbon $updated_at * @property string $text * @property string $title + * @property int $noteable_id */ class Note extends Model { diff --git a/app/Models/PiggyBank.php b/app/Models/PiggyBank.php index e6cc263d3e..3b4422cdd4 100644 --- a/app/Models/PiggyBank.php +++ b/app/Models/PiggyBank.php @@ -27,7 +27,6 @@ use Crypt; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\SoftDeletes; -use Steam; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** @@ -149,7 +148,7 @@ class PiggyBank extends Model */ public function leftOnAccount(Carbon $date): string { - $balance = Steam::balanceIgnoreVirtual($this->account, $date); + $balance = app('steam')->balanceIgnoreVirtual($this->account, $date); /** @var PiggyBank $piggyBank */ foreach ($this->account->piggyBanks as $piggyBank) { $currentAmount = $piggyBank->currentRelevantRep()->currentamount ?? '0'; diff --git a/app/Models/PiggyBankEvent.php b/app/Models/PiggyBankEvent.php index 0f9f364766..4410010937 100644 --- a/app/Models/PiggyBankEvent.php +++ b/app/Models/PiggyBankEvent.php @@ -27,7 +27,11 @@ use Illuminate\Database\Eloquent\Model; /** * Class PiggyBankEvent. * - * @property $piggyBank + * @property PiggyBank $piggyBank + * @property int $transaction_journal_id + * @property int $piggy_bank_id + * @property int $id + * @property mixed date */ class PiggyBankEvent extends Model { diff --git a/app/Models/Preference.php b/app/Models/Preference.php index 19a337bb5c..fab0037bfc 100644 --- a/app/Models/Preference.php +++ b/app/Models/Preference.php @@ -40,6 +40,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property Carbon $updated_at * @property Carbon $created_at * @property int $id + * @property mixed user + * @property mixed user */ class Preference extends Model { diff --git a/app/Models/Role.php b/app/Models/Role.php index ee735d4605..c262631e60 100644 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -28,6 +28,9 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany; /** * Class Role. + * + * @property int $id + * @property string $name */ class Role extends Model { diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 5d4721becb..58b3ac5e9a 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -32,52 +32,62 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class Transaction. * - * @property int $journal_id - * @property Carbon $date - * @property string $transaction_description - * @property string $transaction_amount - * @property string $transaction_foreign_amount - * @property string $transaction_type_type - * @property string $foreign_currency_symbol - * @property int $foreign_currency_dp - * @property int $account_id - * @property string $account_name - * @property string $account_iban - * @property string $account_number - * @property string $account_bic - * @property string $account_type - * @property string $account_currency_code - * @property int $opposing_account_id - * @property string $opposing_account_name - * @property string $opposing_account_iban - * @property string $opposing_account_number - * @property string $opposing_account_bic - * @property string $opposing_account_type - * @property string $opposing_currency_code - * @property int $transaction_budget_id - * @property string $transaction_budget_name - * @property int $transaction_journal_budget_id - * @property string $transaction_journal_budget_name - * @property int $transaction_category_id - * @property string $transaction_category_name - * @property int $transaction_journal_category_id - * @property string $transaction_journal_category_name - * @property int $bill_id - * @property string $bill_name - * @property string $notes - * @property string $tags - * @property string $transaction_currency_symbol - * @property int $transaction_currency_dp - * @property string $transaction_currency_code - * @property string $description - * @property bool $is_split - * @property int $attachmentCount - * @property int $transaction_currency_id - * @property int $foreign_currency_id - * @property string $amount - * @property string $foreign_amount - * @property TransactionJournal $transactionJournal - * @property Account $account + * @property int $journal_id + * @property Carbon $date + * @property string $transaction_description + * @property string $transaction_amount + * @property string $transaction_foreign_amount + * @property string $transaction_type_type + * @property string $foreign_currency_symbol + * @property int $foreign_currency_dp + * @property int $account_id + * @property string $account_name + * @property string $account_iban + * @property string $account_number + * @property string $account_bic + * @property string $account_type + * @property string $account_currency_code + * @property int $opposing_account_id + * @property string $opposing_account_name + * @property string $opposing_account_iban + * @property string $opposing_account_number + * @property string $opposing_account_bic + * @property string $opposing_account_type + * @property string $opposing_currency_code + * @property int $transaction_budget_id + * @property string $transaction_budget_name + * @property int $transaction_journal_budget_id + * @property string $transaction_journal_budget_name + * @property int $transaction_category_id + * @property string $transaction_category_name + * @property int $transaction_journal_category_id + * @property string $transaction_journal_category_name + * @property int $bill_id + * @property string $bill_name + * @property string $notes + * @property string $tags + * @property string $transaction_currency_symbol + * @property int $transaction_currency_dp + * @property string $transaction_currency_code + * @property string $description + * @property bool $is_split + * @property int $attachmentCount + * @property int $transaction_currency_id + * @property int $foreign_currency_id + * @property string $amount + * @property string $foreign_amount + * @property TransactionJournal $transactionJournal + * @property Account $account + * @property int $identifier + * @property int $id + * @property TransactionCurrency $transactionCurrency + * @property int $transaction_journal_id + * @property TransactionCurrency $foreignCurrency + * @property string $before // used in audit reports. + * @property string $after // used in audit reports. + * @property int $opposing_id // ID of the opposing transaction, used in collector + * @property bool $encrypted // is the journal encrypted + * @property $bill_name_encrypted */ class Transaction extends Model { diff --git a/app/Models/TransactionCurrency.php b/app/Models/TransactionCurrency.php index 26e7d9fa0c..ef577f839e 100644 --- a/app/Models/TransactionCurrency.php +++ b/app/Models/TransactionCurrency.php @@ -33,6 +33,14 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @property string $symbol * @property int $decimal_places * @property int $id + * @property mixed name + * @property mixed name + * @property mixed name + * @property mixed name + * @property mixed name + * @property mixed name + * @property mixed name + * @property mixed name * */ class TransactionCurrency extends Model diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php index e6be30af6a..25df6439cc 100644 --- a/app/Models/TransactionJournal.php +++ b/app/Models/TransactionJournal.php @@ -40,12 +40,21 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class TransactionJournal. * - * @property User $user - * @property int $bill_id - * @property Collection $categories - * @property bool $completed - * @property string $description - * @property string $transaction_type_id + * @property User $user + * @property int $bill_id + * @property Collection $categories + * @property bool $completed + * @property string $description + * @property int $transaction_type_id + * @property int transaction_currency_id + * @property TransactionCurrency $transactionCurrency + * @property Collection $tags + * @property mixed user_id + * @property mixed transactions + * @property int transaction_count + * @property Carbon interest_date + * @property Carbon book_date + * @property Carbon process_date */ class TransactionJournal extends Model { diff --git a/app/Models/TransactionJournalMeta.php b/app/Models/TransactionJournalMeta.php index e6acea708f..5f12ed1567 100644 --- a/app/Models/TransactionJournalMeta.php +++ b/app/Models/TransactionJournalMeta.php @@ -29,8 +29,11 @@ use Illuminate\Database\Eloquent\SoftDeletes; /** * Class TransactionJournalMeta. * - * @property string $name - * @property int $transaction_journal_id + * @property string $name + * @property int $transaction_journal_id + * @property TransactionJournal $transactionJournal + * @property string $data + * @property int $id */ class TransactionJournalMeta extends Model { diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 2ffb23d88b..ed5c39efca 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -135,7 +135,7 @@ class EventServiceProvider extends ServiceProvider $repository = app(UserRepositoryInterface::class); $user = $repository->findNull((int)$oauthClient->user_id); if (null === $user) { - Log::error('OAuth client generated but no user associated.'); + Log::info('OAuth client generated but no user associated.'); return; } diff --git a/app/Repositories/Account/AccountTasker.php b/app/Repositories/Account/AccountTasker.php index 2c7b14259e..944d846847 100644 --- a/app/Repositories/Account/AccountTasker.php +++ b/app/Repositories/Account/AccountTasker.php @@ -29,7 +29,6 @@ use FireflyIII\Models\TransactionType; use FireflyIII\User; use Illuminate\Support\Collection; use Log; -use Steam; /** * Class AccountTasker. @@ -50,8 +49,8 @@ class AccountTasker implements AccountTaskerInterface { $yesterday = clone $start; $yesterday->subDay(); - $startSet = Steam::balancesByAccounts($accounts, $yesterday); - $endSet = Steam::balancesByAccounts($accounts, $end); + $startSet = app('steam')->balancesByAccounts($accounts, $yesterday); + $endSet = app('steam')->balancesByAccounts($accounts, $end); Log::debug('Start of accountreport'); diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 443a117405..6cc8bd41eb 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -269,12 +269,16 @@ class BudgetRepository implements BudgetRepositoryInterface /** * Find a budget or return NULL * - * @param int $budgetId + * @param int $budgetId |null * * @return Budget|null */ - public function findNull(int $budgetId): ?Budget + public function findNull(int $budgetId = null): ?Budget { + if (null === $budgetId) { + return null; + } + return $this->user->budgets()->find($budgetId); } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index d8e69f2fef..229bee793a 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -114,13 +114,11 @@ interface BudgetRepositoryInterface public function findByName(string $name): ?Budget; /** - * Find a budget or return NULL - * - * @param int $budgetId + * @param int|null $budgetId * * @return Budget|null */ - public function findNull(int $budgetId): ?Budget; + public function findNull(int $budgetId = null): ?Budget; /** * This method returns the oldest journal or transaction date known to this budget. diff --git a/app/Services/Github/Request/UpdateRequest.php b/app/Services/Github/Request/UpdateRequest.php index fd2d173049..d208e8c06c 100644 --- a/app/Services/Github/Request/UpdateRequest.php +++ b/app/Services/Github/Request/UpdateRequest.php @@ -54,7 +54,7 @@ class UpdateRequest implements GithubRequest throw new FireflyException(sprintf('Response error from Github: %s', $e->getMessage())); } - if ($res->getStatusCode() !== 200) { + if (200 !== $res->getStatusCode()) { throw new FireflyException(sprintf('Returned code %d, error: %s', $res->getStatusCode(), $res->getBody()->getContents())); } diff --git a/app/Support/Import/JobConfiguration/Spectre/ChooseAccountsHandler.php b/app/Support/Import/JobConfiguration/Spectre/ChooseAccountsHandler.php index 9797acd428..8dcabdf64b 100644 --- a/app/Support/Import/JobConfiguration/Spectre/ChooseAccountsHandler.php +++ b/app/Support/Import/JobConfiguration/Spectre/ChooseAccountsHandler.php @@ -86,7 +86,7 @@ class ChooseAccountsHandler implements SpectreJobConfigurationInterface $config = $this->importJob->configuration; $mapping = $data['account_mapping'] ?? []; $final = []; - $applyRules = (int)$data['apply_rules'] === 1; + $applyRules = 1 === (int)($data['apply_rules'] ?? 0); foreach ($mapping as $spectreId => $localId) { // validate each $spectreId = $this->validSpectreAccount((int)$spectreId); diff --git a/app/Support/Import/Placeholder/ImportTransaction.php b/app/Support/Import/Placeholder/ImportTransaction.php index bdda187930..ccc64a7a57 100644 --- a/app/Support/Import/Placeholder/ImportTransaction.php +++ b/app/Support/Import/Placeholder/ImportTransaction.php @@ -139,8 +139,10 @@ class ImportTransaction ); // @codeCoverageIgnoreEnd case 'account-id': + $mappedValue = $this->getMappedValue($columnValue); // could be the result of a mapping? - $this->accountId = $this->getMappedValue($columnValue); + $this->accountId = $mappedValue; + Log::debug(sprintf('Going to set the account-id. Original value is "%s", mapped value is "%s".', $columnValue->getValue(), $mappedValue)); break; case 'account-iban': $this->accountIban = $columnValue->getValue(); @@ -233,7 +235,9 @@ class ImportTransaction $this->note = trim($this->note . ' ' . $columnValue->getValue()); break; case 'opposing-id': - $this->opposingId = $this->getMappedValue($columnValue); + $mappedValue = $this->getMappedValue($columnValue); + $this->opposingId = $mappedValue; + Log::debug(sprintf('Going to set the OPPOSING-id. Original value is "%s", mapped value is "%s".', $columnValue->getValue(), $mappedValue)); break; case 'opposing-iban': $this->opposingIban = $columnValue->getValue(); diff --git a/app/Support/Import/Routine/File/CurrencyMapper.php b/app/Support/Import/Routine/File/CurrencyMapper.php index b2a45500f3..bf7c5ec4b5 100644 --- a/app/Support/Import/Routine/File/CurrencyMapper.php +++ b/app/Support/Import/Routine/File/CurrencyMapper.php @@ -71,15 +71,15 @@ class CurrencyMapper return $result; } } - if (!isset($data['code']) || $data['code'] === null) { + if (!isset($data['code']) || null === $data['code']) { return null; } // if still nothing, and fields not null, try to create it $creation = [ 'code' => $data['code'], - 'name' => $data['name'] ?? $code, - 'symbol' => $data['symbol'] ?? $code, + 'name' => $data['name'] ?? $data['code'], + 'symbol' => $data['symbol'] ?? $data['code'], 'decimal_places' => 2, ]; diff --git a/app/Support/Import/Routine/File/ImportableConverter.php b/app/Support/Import/Routine/File/ImportableConverter.php index bb851e24e4..00cc33d789 100644 --- a/app/Support/Import/Routine/File/ImportableConverter.php +++ b/app/Support/Import/Routine/File/ImportableConverter.php @@ -169,19 +169,11 @@ class ImportableConverter throw new FireflyException('No transaction amount information.'); } - $transactionType = 'unknown'; - $accountId = $this->verifyObjectId('account-id', $importable->accountId); - $billId = $this->verifyObjectId('bill-id', $importable->billId); - $budgetId = $this->verifyObjectId('budget-id', $importable->budgetId); - $currencyId = $this->verifyObjectId('currency-id', $importable->currencyId); - $categoryId = $this->verifyObjectId('category-id', $importable->categoryId); - $foreignCurrencyId = $this->verifyObjectId('foreign-currency-id', $importable->foreignCurrencyId); - $opposingId = $this->verifyObjectId('opposing-id', $importable->opposingId); - - $source = $this->assetMapper->map($accountId, $importable->getAccountData()); - $destination = $this->opposingMapper->map($opposingId, $amount, $importable->getOpposingAccountData()); - $currency = $this->currencyMapper->map($currencyId, $importable->getCurrencyData()); - $foreignCurrency = $this->currencyMapper->map($foreignCurrencyId, $importable->getForeignCurrencyData()); + $transactionType = 'unknown'; + $source = $this->assetMapper->map($importable->accountId, $importable->getAccountData()); + $destination = $this->opposingMapper->map($importable->opposingId, $amount, $importable->getOpposingAccountData()); + $currency = $this->currencyMapper->map($importable->currencyId, $importable->getCurrencyData()); + $foreignCurrency = $this->currencyMapper->map($importable->foreignCurrencyId, $importable->getForeignCurrencyData()); Log::debug(sprintf('"%s" (#%d) is source and "%s" (#%d) is destination.', $source->name, $source->id, $destination->name, $destination->id)); @@ -296,7 +288,7 @@ class ImportableConverter 'description' => $importable->description, 'piggy_bank_id' => null, 'piggy_bank_name' => null, - 'bill_id' => $billId, + 'bill_id' => $importable->billId, 'bill_name' => $importable->billName, // transaction data: @@ -306,15 +298,15 @@ class ImportableConverter 'currency_code' => null, 'description' => null, 'amount' => $amount, - 'budget_id' => $budgetId, - 'budget_name' => null === $budgetId ? $importable->budgetName : null, - 'category_id' => $categoryId, - 'category_name' => null === $categoryId ? $importable->categoryName : null, + 'budget_id' => $importable->budgetId, + 'budget_name' => $importable->budgetName, + 'category_id' => $importable->categoryId, + 'category_name' => $importable->categoryName, 'source_id' => $source->id, 'source_name' => null, 'destination_id' => $destination->id, 'destination_name' => null, - 'foreign_currency_id' => $foreignCurrencyId, + 'foreign_currency_id' => $importable->foreignCurrencyId, 'foreign_currency_code' => null === $foreignCurrency ? null : $foreignCurrency->code, 'foreign_amount' => $foreignAmount, 'reconciled' => false, @@ -335,7 +327,6 @@ class ImportableConverter */ private function verifyObjectId(string $key, int $objectId): ?int { - if (isset($this->mappedValues[$key]) && \in_array($objectId, $this->mappedValues[$key], true)) { Log::debug(sprintf('verifyObjectId(%s, %d) is valid!', $key, $objectId)); diff --git a/app/Support/Import/Routine/File/MappingConverger.php b/app/Support/Import/Routine/File/MappingConverger.php index 08fd612526..a6d161041a 100644 --- a/app/Support/Import/Routine/File/MappingConverger.php +++ b/app/Support/Import/Routine/File/MappingConverger.php @@ -121,12 +121,17 @@ class MappingConverger private function getRoleForColumn(int $column, int $mapped): string { $role = $this->roles[$column] ?? '_ignore'; - if ($mapped === 0) { + if (0 === $mapped) { Log::debug(sprintf('Column #%d with role "%s" is not mapped.', $column, $role)); return $role; } - if (!(isset($this->doMapping[$column]) && $this->doMapping[$column] === true)) { + if (!(isset($this->doMapping[$column]) && true === $this->doMapping[$column])) { + + // if the mapping has been filled in already by a role with a higher priority, + // ignore the mapping. + Log::debug(sprintf('Column #%d ("%s") has something.', $column, $role)); + return $role; } @@ -172,6 +177,7 @@ class MappingConverger // also store the $mapped values in a "mappedValues" array. $this->mappedValues[$newRole][] = $mapped; + Log::debug(sprintf('Values mapped to role "%s" are: ', $newRole), $this->mappedValues[$newRole]); return $newRole; } diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index c2bfa7bf81..af6392144a 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -509,7 +509,7 @@ class Navigation { $date = clone $theDate; // 1D 1W 1M 3M 6M 1Y - Log::debug(sprintf('subtractPeriod: date is %s', $date->format('Y-m-d'))); + Log::debug(sprintf('subtractPeriod: date is %s, repeat frequency is %s and subtract is %d', $date->format('Y-m-d'), $repeatFreq, $subtract)); $functionMap = [ '1D' => 'subDays', 'daily' => 'subDays', diff --git a/app/Support/Search/Modifier.php b/app/Support/Search/Modifier.php index 97ab9cf805..56a3a13755 100644 --- a/app/Support/Search/Modifier.php +++ b/app/Support/Search/Modifier.php @@ -26,7 +26,6 @@ use Carbon\Carbon; use Exception; use FireflyIII\Models\Transaction; use Log; -use Steam; /** * Class Modifier @@ -42,8 +41,8 @@ class Modifier */ public static function amountCompare(Transaction $transaction, string $amount, int $expected): bool { - $amount = Steam::positive($amount); - $transactionAmount = Steam::positive($transaction->transaction_amount); + $amount = app('steam')->positive($amount); + $transactionAmount = app('steam')->positive($transaction->transaction_amount); $compare = bccomp($amount, $transactionAmount); Log::debug(sprintf('%s vs %s is %d', $amount, $transactionAmount, $compare)); @@ -64,12 +63,12 @@ class Modifier $res = true; switch ($modifier['type']) { case 'source': - $name = Steam::tryDecrypt($transaction->account_name); + $name = app('steam')->tryDecrypt($transaction->account_name); $res = self::stringCompare($name, $modifier['value']); Log::debug(sprintf('Source is %s? %s', $modifier['value'], var_export($res, true))); break; case 'destination': - $name = Steam::tryDecrypt($transaction->opposing_account_name); + $name = app('steam')->tryDecrypt($transaction->opposing_account_name); $res = self::stringCompare($name, $modifier['value']); Log::debug(sprintf('Destination is %s? %s', $modifier['value'], var_export($res, true))); break; @@ -82,7 +81,7 @@ class Modifier Log::debug(sprintf('Budget is %s? %s', $modifier['value'], var_export($res, true))); break; case 'bill': - $name = Steam::tryDecrypt($transaction->bill_name); + $name = app('steam')->tryDecrypt($transaction->bill_name); $res = self::stringCompare($name, $modifier['value']); Log::debug(sprintf('Bill is %s? %s', $modifier['value'], var_export($res, true))); break; @@ -166,11 +165,11 @@ class Modifier { $journalBudget = ''; if (null !== $transaction->transaction_journal_budget_name) { - $journalBudget = Steam::decrypt((int)$transaction->transaction_journal_budget_encrypted, $transaction->transaction_journal_budget_name); + $journalBudget = app('steam')->decrypt((int)$transaction->transaction_journal_budget_encrypted, $transaction->transaction_journal_budget_name); } $transactionBudget = ''; if (null !== $transaction->transaction_budget_name) { - $journalBudget = Steam::decrypt((int)$transaction->transaction_budget_encrypted, $transaction->transaction_budget_name); + $journalBudget = app('steam')->decrypt((int)$transaction->transaction_budget_encrypted, $transaction->transaction_budget_name); } return self::stringCompare($journalBudget, $search) || self::stringCompare($transactionBudget, $search); @@ -186,11 +185,13 @@ class Modifier { $journalCategory = ''; if (null !== $transaction->transaction_journal_category_name) { - $journalCategory = Steam::decrypt((int)$transaction->transaction_journal_category_encrypted, $transaction->transaction_journal_category_name); + $journalCategory = app('steam')->decrypt( + (int)$transaction->transaction_journal_category_encrypted, $transaction->transaction_journal_category_name + ); } $transactionCategory = ''; if (null !== $transaction->transaction_category_name) { - $journalCategory = Steam::decrypt((int)$transaction->transaction_category_encrypted, $transaction->transaction_category_name); + $journalCategory = app('steam')->decrypt((int)$transaction->transaction_category_encrypted, $transaction->transaction_category_name); } return self::stringCompare($journalCategory, $search) || self::stringCompare($transactionCategory, $search); diff --git a/app/Support/Twig/Extension/TransactionJournal.php b/app/Support/Twig/Extension/TransactionJournal.php index 66f05708d3..5e4ec2b1a2 100644 --- a/app/Support/Twig/Extension/TransactionJournal.php +++ b/app/Support/Twig/Extension/TransactionJournal.php @@ -104,7 +104,9 @@ class TransactionJournal extends Twig_Extension if (TransactionType::WITHDRAWAL === $type) { $total['amount'] = bcmul($total['amount'], '-1'); } - $array[] = app('amount')->formatAnything($total['currency'], $total['amount']); + if (null !== $total['currency']) { + $array[] = app('amount')->formatAnything($total['currency'], $total['amount']); + } } return implode(' / ', $array); diff --git a/app/Transformers/LinkTypeTransformer.php b/app/Transformers/LinkTypeTransformer.php index 625d390c09..080fb2a52e 100644 --- a/app/Transformers/LinkTypeTransformer.php +++ b/app/Transformers/LinkTypeTransformer.php @@ -28,6 +28,10 @@ use FireflyIII\Models\LinkType; use League\Fractal\TransformerAbstract; use Symfony\Component\HttpFoundation\ParameterBag; +/** + * + * Class LinkTypeTransformer + */ class LinkTypeTransformer extends TransformerAbstract { @@ -75,7 +79,7 @@ class LinkTypeTransformer extends TransformerAbstract 'name' => $linkType->name, 'inward' => $linkType->inward, 'outward' => $linkType->outward, - 'editable' => (int)$linkType->editable, + 'editable' => 1 === (int)$linkType->editable, 'links' => [ [ 'rel' => 'self', diff --git a/app/Transformers/RuleGroupTransformer.php b/app/Transformers/RuleGroupTransformer.php index d749f09945..bc7060cee7 100644 --- a/app/Transformers/RuleGroupTransformer.php +++ b/app/Transformers/RuleGroupTransformer.php @@ -62,6 +62,11 @@ class RuleGroupTransformer extends TransformerAbstract $this->parameters = $parameters; } + /** + * @param RuleGroup $ruleGroup + * + * @return FractalCollection + */ public function includeRules(RuleGroup $ruleGroup): FractalCollection { return $this->collection($ruleGroup->rules, new RuleTransformer($this->parameters), 'rules'); diff --git a/app/User.php b/app/User.php index 28525e3ab4..aad71c773e 100644 --- a/app/User.php +++ b/app/User.php @@ -59,6 +59,10 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * * @property int $id * @property string $email + * @property bool $isAdmin used in admin user controller. + * @property bool $has2FA used in admin user controller. + * @property array $prefs used in admin user controller. + * @property mixed password */ class User extends Authenticatable { diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index 15dcc33618..f0aab84bf0 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -432,6 +432,19 @@ class FireflyValidator extends Validator return false; } + /** + * TODO fill me. + * + * @param $attribute + * @param $value + * @param $parameters + * + * @return bool + */ + public function validateRepetitionMoment($attribute, $value, $parameters): bool { + + } + /** * @SuppressWarnings(PHPMD.UnusedFormalParameter) * diff --git a/app/Validation/RecurrenceValidation.php b/app/Validation/RecurrenceValidation.php new file mode 100644 index 0000000000..42f46d3d3e --- /dev/null +++ b/app/Validation/RecurrenceValidation.php @@ -0,0 +1,194 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Validation; + +use Carbon\Carbon; +use Exception; +use Illuminate\Validation\Validator; +use InvalidArgumentException; + +/** + * Trait RecurrenceValidation + * + * Contains advanced validation rules used in validation of new and existing recurrences. + * + * @package FireflyIII\Validation + */ +trait RecurrenceValidation +{ + /** + * @param Validator $validator + */ + public function validateRepetitionMoment(Validator $validator): void + { + $data = $validator->getData(); + $repetitions = $data['repetitions'] ?? []; + /** + * @var int $index + * @var array $repetition + */ + foreach ($repetitions as $index => $repetition) { + switch ($repetition['type']) { + default: + $validator->errors()->add(sprintf('repetitions.%d.type', $index), trans('validation.valid_recurrence_rep_type')); + + return; + case 'daily': + $this->validateDaily($validator, $index, (string)$repetition['moment']); + break; + case 'monthly': + $this->validateMonthly($validator, $index, (int)$repetition['moment']); + break; + case 'ndom': + $this->validateNdom($validator, $index, (string)$repetition['moment']); + break; + case 'weekly': + $this->validateWeekly($validator, $index, (int)$repetition['moment']); + break; + case 'yearly': + $this->validateYearly($validator, $index, (string)$repetition['moment']); + break; + } + } + } + + /** + * Adds an error to the validator when there are no repetitions in the array of data. + * + * @param Validator $validator + */ + public function validateOneRepetition(Validator $validator): void + { + $data = $validator->getData(); + $repetitions = $data['repetitions'] ?? []; + // need at least one transaction + if (\count($repetitions) === 0) { + $validator->errors()->add('description', trans('validation.at_least_one_repetition')); + } + } + + /** + * Validates that the recurrence has valid repetition information. It either doesn't stop, + * or stops after X times or at X date. Not both of them., + * + * @param Validator $validator + */ + public function validateRecurrenceRepetition(Validator $validator): void + { + $data = $validator->getData(); + $repetitions = $data['nr_of_repetitions'] ?? null; + $repeatUntil = $data['repeat_until'] ?? null; + if (null !== $repetitions && null !== $repeatUntil) { + // expect a date OR count: + $validator->errors()->add('repeat_until', trans('validation.require_repeat_until')); + $validator->errors()->add('nr_of_repetitions', trans('validation.require_repeat_until')); + } + } + + /** + * If the repetition type is daily, the moment should be empty. + * + * @param Validator $validator + * @param int $index + * @param string $moment + */ + protected function validateDaily(Validator $validator, int $index, string $moment): void + { + if ('' !== $moment) { + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); + } + } + + /** + * If the repetition type is monthly, the moment should be a day between 1-31 (inclusive). + * + * @param Validator $validator + * @param int $index + * @param int $dayOfMonth + */ + protected function validateMonthly(Validator $validator, int $index, int $dayOfMonth): void + { + if ($dayOfMonth < 1 || $dayOfMonth > 31) { + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); + } + } + + /** + * If the repetition type is "ndom", the first part must be between 1-5 (inclusive), for the week in the month, + * and the second one must be between 1-7 (inclusive) for the day of the week. + * + * @param Validator $validator + * @param int $index + * @param string $moment + */ + protected function validateNdom(Validator $validator, int $index, string $moment): void + { + $parameters = explode(',', $moment); + if (\count($parameters) !== 2) { + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); + + return; + } + $nthDay = (int)($parameters[0] ?? 0.0); + $dayOfWeek = (int)($parameters[1] ?? 0.0); + if ($nthDay < 1 || $nthDay > 5) { + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); + + return; + } + if ($dayOfWeek < 1 || $dayOfWeek > 7) { + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); + } + } + + /** + * If the repetition type is weekly, the moment should be a day between 1-7 (inclusive). + * + * @param Validator $validator + * @param int $index + * @param int $dayOfWeek + */ + protected function validateWeekly(Validator $validator, int $index, int $dayOfWeek): void + { + if ($dayOfWeek < 1 || $dayOfWeek > 7) { + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); + } + } + + /** + * If the repetition type is yearly, the moment should be a valid date. + * + * @param Validator $validator + * @param int $index + * @param string $moment + */ + protected function validateYearly(Validator $validator, int $index, string $moment): void + { + try { + Carbon::createFromFormat('Y-m-d', $moment); + } catch (InvalidArgumentException|Exception $e) { + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), trans('validation.valid_recurrence_rep_moment')); + } + } +} \ No newline at end of file diff --git a/app/Validation/TransactionValidation.php b/app/Validation/TransactionValidation.php new file mode 100644 index 0000000000..af397a7e0e --- /dev/null +++ b/app/Validation/TransactionValidation.php @@ -0,0 +1,366 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Validation; + +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Models\Transaction; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\User; +use Illuminate\Validation\Validator; +use Log; + +/** + * Trait TransactionValidation + * + * @package FireflyIII\Validation + */ +trait TransactionValidation +{ + /** + * Validates the given account information. Switches on given transaction type. + * + * @param Validator $validator + */ + public function validateAccountInformation(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + $idField = 'description'; + $transactionType = $data['type'] ?? 'invalid'; + // get transaction type: + if (!isset($data['type'])) { + // the journal may exist in the request: + /** @var Transaction $transaction */ + $transaction = $this->route()->parameter('transaction'); + if (null !== $transaction) { + $transactionType = strtolower($transaction->transactionJournal->transactionType->type); + } + } + + foreach ($transactions as $index => $transaction) { + $sourceId = isset($transaction['source_id']) ? (int)$transaction['source_id'] : null; + $sourceName = $transaction['source_name'] ?? null; + $destinationId = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : null; + $destinationName = $transaction['destination_name'] ?? null; + $sourceAccount = null; + $destinationAccount = null; + switch ($transactionType) { + case 'withdrawal': + $idField = 'transactions.' . $index . '.source_id'; + $nameField = 'transactions.' . $index . '.source_name'; + $sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField); + $idField = 'transactions.' . $index . '.destination_id'; + $destinationAccount = $this->opposingAccountExists($validator, AccountType::EXPENSE, $destinationId, $destinationName, $idField); + break; + case 'deposit': + $idField = 'transactions.' . $index . '.source_id'; + $sourceAccount = $this->opposingAccountExists($validator, AccountType::REVENUE, $sourceId, $sourceName, $idField); + + $idField = 'transactions.' . $index . '.destination_id'; + $nameField = 'transactions.' . $index . '.destination_name'; + $destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField); + break; + case 'transfer': + $idField = 'transactions.' . $index . '.source_id'; + $nameField = 'transactions.' . $index . '.source_name'; + $sourceAccount = $this->assetAccountExists($validator, $sourceId, $sourceName, $idField, $nameField); + + $idField = 'transactions.' . $index . '.destination_id'; + $nameField = 'transactions.' . $index . '.destination_name'; + $destinationAccount = $this->assetAccountExists($validator, $destinationId, $destinationName, $idField, $nameField); + break; + default: + $validator->errors()->add($idField, trans('validation.invalid_account_info')); + + return; + + } + // add some errors in case of same account submitted: + if (null !== $sourceAccount && null !== $destinationAccount && $sourceAccount->id === $destinationAccount->id) { + $validator->errors()->add($idField, trans('validation.source_equals_destination')); + } + } + } + + /** + * Adds an error to the "description" field when the user has submitted no descriptions and no + * journal description. + * + * @param Validator $validator + */ + public function validateDescriptions(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + $journalDescription = (string)($data['description'] ?? ''); + $validDescriptions = 0; + foreach ($transactions as $index => $transaction) { + if (\strlen((string)($transaction['description'] ?? '')) > 0) { + $validDescriptions++; + } + } + + // no valid descriptions and empty journal description? error. + if ($validDescriptions === 0 && '' === $journalDescription) { + $validator->errors()->add('description', trans('validation.filled', ['attribute' => trans('validation.attributes.description')])); + } + } + + /** + * If the transactions contain foreign amounts, there must also be foreign currency information. + * + * @param Validator $validator + */ + public function validateForeignCurrencyInformation(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + foreach ($transactions as $index => $transaction) { + // must have currency info. + if (isset($transaction['foreign_amount']) + && !(isset($transaction['foreign_currency_id']) + || isset($transaction['foreign_currency_code']))) { + $validator->errors()->add( + 'transactions.' . $index . '.foreign_amount', + trans('validation.require_currency_info') + ); + } + } + } + + /** + * Adds an error to the validator when any transaction descriptions are equal to the journal description. + * + * @param Validator $validator + */ + public function validateJournalDescription(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + $journalDescription = (string)($data['description'] ?? ''); + foreach ($transactions as $index => $transaction) { + $description = (string)($transaction['description'] ?? ''); + // description cannot be equal to journal description. + if ($description === $journalDescription) { + $validator->errors()->add('transactions.' . $index . '.description', trans('validation.equal_description')); + } + } + } + + /** + * Adds an error to the validator when there are no transactions in the array of data. + * + * @param Validator $validator + */ + public function validateOneTransaction(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + // need at least one transaction + if (\count($transactions) === 0) { + $validator->errors()->add('description', trans('validation.at_least_one_transaction')); + } + } + + /** + * Make sure that all the splits accounts are valid in combination with each other. + * + * @param Validator $validator + */ + public function validateSplitAccounts(Validator $validator): void + { + $data = $validator->getData(); + $count = isset($data['transactions']) ? \count($data['transactions']) : 0; + if ($count < 2) { + return; + } + // this is pretty much impossible: + // @codeCoverageIgnoreStart + if (!isset($data['type'])) { + // the journal may exist in the request: + /** @var Transaction $transaction */ + $transaction = $this->route()->parameter('transaction'); + if (null === $transaction) { + return; + } + $data['type'] = strtolower($transaction->transactionJournal->transactionType->type); + } + // @codeCoverageIgnoreEnd + + // collect all source ID's and destination ID's, if present: + $sources = []; + $destinations = []; + + foreach ($data['transactions'] as $transaction) { + $sources[] = isset($transaction['source_id']) ? (int)$transaction['source_id'] : 0; + $destinations[] = isset($transaction['destination_id']) ? (int)$transaction['destination_id'] : 0; + } + $destinations = array_unique($destinations); + $sources = array_unique($sources); + // switch on type: + switch ($data['type']) { + case 'withdrawal': + if (\count($sources) > 1) { + $validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal')); + } + break; + case 'deposit': + if (\count($destinations) > 1) { + $validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal')); + } + break; + case 'transfer': + if (\count($sources) > 1 || \count($destinations) > 1) { + $validator->errors()->add('transactions.0.source_id', trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.destination_id', trans('validation.all_accounts_equal')); + } + break; + } + } + + /** + * Adds an error to the validator when the user submits a split transaction (more than 1 transactions) + * but does not give them a description. + * + * @param Validator $validator + */ + public function validateSplitDescriptions(Validator $validator): void + { + $data = $validator->getData(); + $transactions = $data['transactions'] ?? []; + foreach ($transactions as $index => $transaction) { + $description = (string)($transaction['description'] ?? ''); + // filled description is mandatory for split transactions. + if ('' === $description && \count($transactions) > 1) { + $validator->errors()->add( + 'transactions.' . $index . '.description', + trans('validation.filled', ['attribute' => trans('validation.attributes.transaction_description')]) + ); + } + } + } + + /** + * Throws an error when this asset account is invalid. + * + * @noinspection MoreThanThreeArgumentsInspection + * + * @param Validator $validator + * @param int|null $accountId + * @param null|string $accountName + * @param string $idField + * @param string $nameField + * + * @return null|Account + */ + protected function assetAccountExists(Validator $validator, ?int $accountId, ?string $accountName, string $idField, string $nameField): ?Account + { + /** @var User $admin */ + $admin = auth()->user(); + $accountId = (int)$accountId; + $accountName = (string)$accountName; + // both empty? hard exit. + if ($accountId < 1 && '' === $accountName) { + $validator->errors()->add($idField, trans('validation.filled', ['attribute' => $idField])); + + return null; + } + // ID belongs to user and is asset account: + /** @var AccountRepositoryInterface $repository */ + $repository = app(AccountRepositoryInterface::class); + $repository->setUser($admin); + $set = $repository->getAccountsById([$accountId]); + Log::debug(sprintf('Count of accounts found by ID %d is: %d', $accountId, $set->count())); + if ($set->count() === 1) { + /** @var Account $first */ + $first = $set->first(); + if ($first->accountType->type !== AccountType::ASSET) { + $validator->errors()->add($idField, trans('validation.belongs_user')); + + return null; + } + + // we ignore the account name at this point. + return $first; + } + + $account = $repository->findByName($accountName, [AccountType::ASSET]); + if (null === $account) { + $validator->errors()->add($nameField, trans('validation.belongs_user')); + + return null; + } + + return $account; + } + + /** + * Throws an error when the given opposing account (of type $type) is invalid. + * Empty data is allowed, system will default to cash. + * + * @noinspection MoreThanThreeArgumentsInspection + * + * @param Validator $validator + * @param string $type + * @param int|null $accountId + * @param null|string $accountName + * @param string $idField + * + * @return null|Account + */ + protected function opposingAccountExists(Validator $validator, string $type, ?int $accountId, ?string $accountName, string $idField): ?Account + { + /** @var User $admin */ + $admin = auth()->user(); + $accountId = (int)$accountId; + $accountName = (string)$accountName; + // both empty? done! + if ($accountId < 1 && '' === $accountName) { + return null; + } + if ($accountId !== 0) { + // ID belongs to user and is $type account: + /** @var AccountRepositoryInterface $repository */ + $repository = app(AccountRepositoryInterface::class); + $repository->setUser($admin); + $set = $repository->getAccountsById([$accountId]); + if ($set->count() === 1) { + /** @var Account $first */ + $first = $set->first(); + if ($first->accountType->type !== $type) { + $validator->errors()->add($idField, trans('validation.belongs_user')); + + return null; + } + + // we ignore the account name at this point. + return $first; + } + } + + // not having an opposing account by this name is NOT a problem. + return null; + } +} \ No newline at end of file diff --git a/changelog.md b/changelog.md index 6358b2b40b..945a303282 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,17 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). + +## [4.7.5.1] - 2018-07-14 +### Fixed +- [Issue 1531](https://github.com/firefly-iii/firefly-iii/issues/1531), the database routine incorrectly reports empty categories. +- [Issue 1532](https://github.com/firefly-iii/firefly-iii/issues/1532), broken dropdown for autosuggest things. +- [Issue 1533](https://github.com/firefly-iii/firefly-iii/issues/1533), fix where the import could not import category names. +- [Issue 1538](https://github.com/firefly-iii/firefly-iii/issues/1538), fix a bug where Spectre would not work when ignoring rules. +- [Issue 1542](https://github.com/firefly-iii/firefly-iii/issues/1542), fix a bug where the importer was incapable of generating new currencies. +- [Issue 1541](https://github.com/firefly-iii/firefly-iii/issues/1541), no longer ignore composer.lock in Docker ignore. +- Bills are stored inactive. + ## [4.7.5] - 2018-07-02 ### Added - A new feature called "recurring transactions" that will make Firefly III automatically create transactions for you. diff --git a/composer.lock b/composer.lock index a37ccfe587..56cfa6fd17 100644 --- a/composer.lock +++ b/composer.lock @@ -237,74 +237,6 @@ ], "time": "2018-04-23T19:33:40+00:00" }, - { - "name": "doctrine/annotations", - "version": "v1.6.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "reference": "c7f2050c68a9ab0bdb0f98567ec08d80ea7d24d5", - "shasum": "" - }, - "require": { - "doctrine/lexer": "1.*", - "php": "^7.1" - }, - "require-dev": { - "doctrine/cache": "1.*", - "phpunit/phpunit": "^6.4" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.6.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Docblock Annotations Parser", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "docblock", - "parser" - ], - "time": "2017-12-06T07:11:42+00:00" - }, { "name": "doctrine/cache", "version": "v1.7.1", @@ -379,170 +311,33 @@ ], "time": "2017-08-25T07:02:50+00:00" }, - { - "name": "doctrine/collections", - "version": "v1.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/collections.git", - "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/collections/zipball/a01ee38fcd999f34d9bfbcee59dbda5105449cbf", - "reference": "a01ee38fcd999f34d9bfbcee59dbda5105449cbf", - "shasum": "" - }, - "require": { - "php": "^7.1" - }, - "require-dev": { - "doctrine/coding-standard": "~0.1@dev", - "phpunit/phpunit": "^5.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.3.x-dev" - } - }, - "autoload": { - "psr-0": { - "Doctrine\\Common\\Collections\\": "lib/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Collections Abstraction library", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "array", - "collections", - "iterator" - ], - "time": "2017-07-22T10:37:32+00:00" - }, - { - "name": "doctrine/common", - "version": "v2.8.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/common.git", - "reference": "f68c297ce6455e8fd794aa8ffaf9fa458f6ade66" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/common/zipball/f68c297ce6455e8fd794aa8ffaf9fa458f6ade66", - "reference": "f68c297ce6455e8fd794aa8ffaf9fa458f6ade66", - "shasum": "" - }, - "require": { - "doctrine/annotations": "1.*", - "doctrine/cache": "1.*", - "doctrine/collections": "1.*", - "doctrine/inflector": "1.*", - "doctrine/lexer": "1.*", - "php": "~7.1" - }, - "require-dev": { - "phpunit/phpunit": "^5.7" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "2.8.x-dev" - } - }, - "autoload": { - "psr-4": { - "Doctrine\\Common\\": "lib/Doctrine/Common" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Roman Borschel", - "email": "roman@code-factory.org" - }, - { - "name": "Benjamin Eberlei", - "email": "kontakt@beberlei.de" - }, - { - "name": "Guilherme Blanco", - "email": "guilhermeblanco@gmail.com" - }, - { - "name": "Jonathan Wage", - "email": "jonwage@gmail.com" - }, - { - "name": "Johannes Schmitt", - "email": "schmittjoh@gmail.com" - } - ], - "description": "Common Library for Doctrine projects", - "homepage": "http://www.doctrine-project.org", - "keywords": [ - "annotations", - "collections", - "eventmanager", - "persistence", - "spl" - ], - "time": "2017-08-31T08:43:38+00:00" - }, { "name": "doctrine/dbal", - "version": "v2.7.1", + "version": "v2.8.0", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "11037b4352c008373561dc6fc836834eed80c3b5" + "reference": "5140a64c08b4b607b9bedaae0cedd26f04a0e621" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/11037b4352c008373561dc6fc836834eed80c3b5", - "reference": "11037b4352c008373561dc6fc836834eed80c3b5", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/5140a64c08b4b607b9bedaae0cedd26f04a0e621", + "reference": "5140a64c08b4b607b9bedaae0cedd26f04a0e621", "shasum": "" }, "require": { - "doctrine/common": "^2.7.1", + "doctrine/cache": "^1.0", + "doctrine/event-manager": "^1.0", "ext-pdo": "*", "php": "^7.1" }, "require-dev": { "doctrine/coding-standard": "^4.0", - "phpunit/phpunit": "^7.0", + "jetbrains/phpstorm-stubs": "^2018.1.2", + "phpstan/phpstan": "^0.10.1", + "phpunit/phpunit": "^7.1.2", "phpunit/phpunit-mock-objects": "!=3.2.4,!=3.2.5", - "symfony/console": "^2.0.5||^3.0", + "symfony/console": "^2.0.5|^3.0|^4.0", "symfony/phpunit-bridge": "^3.4.5|^4.0.5" }, "suggest": { @@ -554,7 +349,8 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.7.x-dev" + "dev-master": "2.8.x-dev", + "dev-develop": "3.0.x-dev" } }, "autoload": { @@ -592,7 +388,81 @@ "persistence", "queryobject" ], - "time": "2018-04-07T18:44:18+00:00" + "time": "2018-07-13T03:16:35+00:00" + }, + { + "name": "doctrine/event-manager", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/event-manager.git", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "reference": "a520bc093a0170feeb6b14e9d83f3a14452e64b3", + "shasum": "" + }, + "require": { + "php": "^7.1" + }, + "conflict": { + "doctrine/common": "<2.9@dev" + }, + "require-dev": { + "doctrine/coding-standard": "^4.0", + "phpunit/phpunit": "^7.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctrine\\Common\\": "lib/Doctrine/Common" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + }, + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com" + } + ], + "description": "Doctrine Event Manager component", + "homepage": "https://www.doctrine-project.org/projects/event-manager.html", + "keywords": [ + "event", + "eventdispatcher", + "eventmanager" + ], + "time": "2018-06-11T11:59:03+00:00" }, { "name": "doctrine/inflector", @@ -1150,16 +1020,16 @@ }, { "name": "laravel/framework", - "version": "v5.6.26", + "version": "v5.6.27", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "7047df295e77cecb6a2f84736a732af66cc6789c" + "reference": "2fe661f2444410a576aa40054ad9b7fe0bb5cee5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/7047df295e77cecb6a2f84736a732af66cc6789c", - "reference": "7047df295e77cecb6a2f84736a732af66cc6789c", + "url": "https://api.github.com/repos/laravel/framework/zipball/2fe661f2444410a576aa40054ad9b7fe0bb5cee5", + "reference": "2fe661f2444410a576aa40054ad9b7fe0bb5cee5", "shasum": "" }, "require": { @@ -1285,7 +1155,7 @@ "framework", "laravel" ], - "time": "2018-06-20T14:21:11+00:00" + "time": "2018-07-10T13:47:01+00:00" }, { "name": "laravel/passport", @@ -2079,16 +1949,16 @@ }, { "name": "paragonie/random_compat", - "version": "v2.0.15", + "version": "v2.0.17", "source": { "type": "git", "url": "https://github.com/paragonie/random_compat.git", - "reference": "10bcb46e8f3d365170f6de9d05245aa066b81f09" + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/10bcb46e8f3d365170f6de9d05245aa066b81f09", - "reference": "10bcb46e8f3d365170f6de9d05245aa066b81f09", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/29af24f25bab834fcbb38ad2a69fa93b867e070d", + "reference": "29af24f25bab834fcbb38ad2a69fa93b867e070d", "shasum": "" }, "require": { @@ -2124,7 +1994,7 @@ "pseudorandom", "random" ], - "time": "2018-06-08T15:26:40+00:00" + "time": "2018-07-04T16:31:37+00:00" }, { "name": "phpseclib/phpseclib", @@ -2698,16 +2568,16 @@ }, { "name": "swiftmailer/swiftmailer", - "version": "v6.1.0", + "version": "v6.1.2", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "0ff595e1d9d7d1c929b2a5f7b774bbcfbbd81587" + "reference": "7d760881d266d63c5e7a1155cbcf2ac656a31ca8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/0ff595e1d9d7d1c929b2a5f7b774bbcfbbd81587", - "reference": "0ff595e1d9d7d1c929b2a5f7b774bbcfbbd81587", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/7d760881d266d63c5e7a1155cbcf2ac656a31ca8", + "reference": "7d760881d266d63c5e7a1155cbcf2ac656a31ca8", "shasum": "" }, "require": { @@ -2753,7 +2623,7 @@ "mail", "mailer" ], - "time": "2018-07-02T20:24:38+00:00" + "time": "2018-07-13T07:04:35+00:00" }, { "name": "symfony/console", @@ -3841,20 +3711,21 @@ }, { "name": "twig/twig", - "version": "v1.35.3", + "version": "v1.35.4", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "b48680b6eb7d16b5025b9bfc4108d86f6b8af86f" + "reference": "7e081e98378a1e78c29cc9eba4aefa5d78a05d2a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/b48680b6eb7d16b5025b9bfc4108d86f6b8af86f", - "reference": "b48680b6eb7d16b5025b9bfc4108d86f6b8af86f", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/7e081e98378a1e78c29cc9eba4aefa5d78a05d2a", + "reference": "7e081e98378a1e78c29cc9eba4aefa5d78a05d2a", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.3.3", + "symfony/polyfill-ctype": "^1.8" }, "require-dev": { "psr/container": "^1.0", @@ -3893,16 +3764,16 @@ }, { "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", + "homepage": "https://twig.symfony.com/contributors", "role": "Contributors" } ], "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", + "homepage": "https://twig.symfony.com", "keywords": [ "templating" ], - "time": "2018-03-20T04:25:58+00:00" + "time": "2018-07-13T07:12:17+00:00" }, { "name": "vlucas/phpdotenv", @@ -3956,16 +3827,16 @@ }, { "name": "zendframework/zend-diactoros", - "version": "1.8.0", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/zendframework/zend-diactoros.git", - "reference": "11c9c1835e60eef6f9234377a480fcec096ebd9e" + "reference": "63d920d1c9ebc009d860c3666593a66298727dd6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/11c9c1835e60eef6f9234377a480fcec096ebd9e", - "reference": "11c9c1835e60eef6f9234377a480fcec096ebd9e", + "url": "https://api.github.com/repos/zendframework/zend-diactoros/zipball/63d920d1c9ebc009d860c3666593a66298727dd6", + "reference": "63d920d1c9ebc009d860c3666593a66298727dd6", "shasum": "" }, "require": { @@ -4015,7 +3886,7 @@ "psr", "psr-7" ], - "time": "2018-06-27T18:52:43+00:00" + "time": "2018-07-09T21:17:27+00:00" } ], "packages-dev": [ @@ -4258,16 +4129,16 @@ }, { "name": "fzaninotto/faker", - "version": "v1.7.1", + "version": "v1.8.0", "source": { "type": "git", "url": "https://github.com/fzaninotto/Faker.git", - "reference": "d3ed4cc37051c1ca52d22d76b437d14809fc7e0d" + "reference": "f72816b43e74063c8b10357394b6bba8cb1c10de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/d3ed4cc37051c1ca52d22d76b437d14809fc7e0d", - "reference": "d3ed4cc37051c1ca52d22d76b437d14809fc7e0d", + "url": "https://api.github.com/repos/fzaninotto/Faker/zipball/f72816b43e74063c8b10357394b6bba8cb1c10de", + "reference": "f72816b43e74063c8b10357394b6bba8cb1c10de", "shasum": "" }, "require": { @@ -4275,7 +4146,7 @@ }, "require-dev": { "ext-intl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", + "phpunit/phpunit": "^4.8.35 || ^5.7", "squizlabs/php_codesniffer": "^1.5" }, "type": "library", @@ -4304,7 +4175,7 @@ "faker", "fixtures" ], - "time": "2017-08-15T16:48:10+00:00" + "time": "2018-07-12T10:23:15+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -5255,12 +5126,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "5c802c6300dca269edde06c6ae8c7eb561de3176" + "reference": "731d60f7fc78a8816dae7049df255cd55e30c313" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/5c802c6300dca269edde06c6ae8c7eb561de3176", - "reference": "5c802c6300dca269edde06c6ae8c7eb561de3176", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/731d60f7fc78a8816dae7049df255cd55e30c313", + "reference": "731d60f7fc78a8816dae7049df255cd55e30c313", "shasum": "" }, "conflict": { @@ -5311,7 +5182,7 @@ "laravel/socialite": ">=1,<1.0.99|>=2,<2.0.10", "magento/magento1ce": ">=1.5.0.1,<1.9.3.2", "magento/magento1ee": ">=1.9,<1.14.3.2", - "magento/magento2ce": ">=2,<2.3", + "magento/product-community-edition": ">=2,<2.2.5", "monolog/monolog": ">=1.8,<1.12", "namshi/jose": "<2.2", "onelogin/php-saml": "<2.10.4", @@ -5342,6 +5213,8 @@ "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", "stormpath/sdk": ">=0,<9.9.99", "swiftmailer/swiftmailer": ">=4,<5.4.5", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/sylius": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", "symfony/dependency-injection": ">=2,<2.0.17", "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2", @@ -5362,7 +5235,7 @@ "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7", "thelia/backoffice-default-template": ">=2.1,<2.1.2", - "thelia/thelia": ">=2.1.0-beta1,<2.1.3|>=2.1,<2.1.2", + "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", @@ -5414,7 +5287,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2018-07-03T10:42:36+00:00" + "time": "2018-07-09T14:09:25+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", @@ -5463,16 +5336,16 @@ }, { "name": "sebastian/comparator", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "591a30922f54656695e59b1f39501aec513403da" + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/591a30922f54656695e59b1f39501aec513403da", - "reference": "591a30922f54656695e59b1f39501aec513403da", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/5de4fc177adf9bce8df98d8d141a7559d7ccf6da", + "reference": "5de4fc177adf9bce8df98d8d141a7559d7ccf6da", "shasum": "" }, "require": { @@ -5523,7 +5396,7 @@ "compare", "equality" ], - "time": "2018-06-14T15:05:28+00:00" + "time": "2018-07-12T15:12:46+00:00" }, { "name": "sebastian/diff", diff --git a/config/firefly.php b/config/firefly.php index 3ce05abf00..d1d8476010 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -88,8 +88,8 @@ return [ 'is_demo_site' => false, ], 'encryption' => null === env('USE_ENCRYPTION') || env('USE_ENCRYPTION') === true, - 'version' => '4.7.5', - 'api_version' => '0.4', + 'version' => '4.7.5.1', + 'api_version' => '0.5', 'db_version' => 4, 'maxUploadSize' => 15242880, 'allowedMimes' => [ diff --git a/resources/lang/de_DE/firefly.php b/resources/lang/de_DE/firefly.php index 89858113db..47c2fb2cf1 100644 --- a/resources/lang/de_DE/firefly.php +++ b/resources/lang/de_DE/firefly.php @@ -608,6 +608,7 @@ Sollen zusätzlich Ihre Girokonten angezeigt werden?', 'cannot_delete_currency' => '„:name” konnte nicht gelöscht werden, da dieser noch verwendet wird', 'deleted_currency' => 'Währung :name gelöscht', 'created_currency' => 'Währung :name erstellt', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Währung :name aktualisiert', 'ask_site_owner' => 'Bitte fragen sie :owner zum Hinzufügen, Entfernen oder Bearbeiten von Währungen.', 'currencies_intro' => 'Firefly III unterstützt verschiedene Währungen, welche hier eingestellt und aktiviert werden können.', diff --git a/resources/lang/en_US/firefly.php b/resources/lang/en_US/firefly.php index ad47b99796..303114c145 100644 --- a/resources/lang/en_US/firefly.php +++ b/resources/lang/en_US/firefly.php @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'Cannot delete :name because it is still in use.', 'deleted_currency' => 'Currency :name deleted', 'created_currency' => 'Currency :name created', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Currency :name updated', 'ask_site_owner' => 'Please ask :owner to add, remove or edit currencies.', 'currencies_intro' => 'Firefly III supports various currencies which you can set and enable here.', diff --git a/resources/lang/es_ES/firefly.php b/resources/lang/es_ES/firefly.php index 4d83113a79..3b7353af44 100644 --- a/resources/lang/es_ES/firefly.php +++ b/resources/lang/es_ES/firefly.php @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'No puede eliminar :name porque todavía esta en uso.', 'deleted_currency' => 'Moneda :name eliminada', 'created_currency' => 'Moneda :name creada', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Moneda :name actualizada', 'ask_site_owner' => 'Por favor pregunte :owner por agregar,elimine o edite monedas.', 'currencies_intro' => 'Firefly III respalda varias monedas que usted puede establecer y habilitar aquí.', diff --git a/resources/lang/fr_FR/config.php b/resources/lang/fr_FR/config.php index 05283eb88f..17cd33ed32 100644 --- a/resources/lang/fr_FR/config.php +++ b/resources/lang/fr_FR/config.php @@ -27,8 +27,8 @@ return [ 'locale' => 'fr, French, fr_FR, fr_FR.utf8, fr_FR.UTF-8', 'month' => '%B %Y', 'month_and_day' => '%e %B %Y', - 'month_and_date_day' => '%A %B %e, %Y', - 'month_and_day_no_year' => '%B %e', + 'month_and_date_day' => '%A %e %B %Y', + 'month_and_day_no_year' => '%e %B', 'date_time' => '%B %e %Y @ %T', 'specific_day' => '%e %B %Y', 'week_in_year' => 'Semaine %W %Y', @@ -41,11 +41,11 @@ return [ 'week_in_year_js' => '[Week] w, YYYY', 'year_js' => 'YYYY', 'half_year_js' => 'Q YYYY', - 'dow_1' => 'Monday', - 'dow_2' => 'Tuesday', - 'dow_3' => 'Wednesday', - 'dow_4' => 'Thursday', - 'dow_5' => 'Friday', - 'dow_6' => 'Saturday', - 'dow_7' => 'Sunday', + 'dow_1' => 'Lundi', + 'dow_2' => 'Mardi', + 'dow_3' => 'Mercredi', + 'dow_4' => 'Jeudi', + 'dow_5' => 'Vendredi', + 'dow_6' => 'Samedi', + 'dow_7' => 'Dimanche', ]; diff --git a/resources/lang/fr_FR/demo.php b/resources/lang/fr_FR/demo.php index 6464f29911..2f90cf6cc1 100644 --- a/resources/lang/fr_FR/demo.php +++ b/resources/lang/fr_FR/demo.php @@ -34,6 +34,6 @@ return [ 'transactions-index' => 'Ces dépenses, dépôts et transferts ne sont pas particulièrement imaginatifs. Ils ont été générés automatiquement.', 'piggy-banks-index' => 'Comme vous pouvez le voir, il y a trois tirelires. Utilisez les boutons plus et moins pour influer sur le montant d’argent dans chaque tirelire. Cliquez sur le nom de la tirelire pour voir l’administration pour chaque tirelire.', 'import-index' => 'Tout fichier CSV peut être importé dans Firefly III. L\'importation de données depuis bunq et Specter est également prise en charge. D\'autres banques et agrégateurs financiers seront mis en place dans le futur. En tant qu\'utilisateur du site de démonstration, vous ne pouvez voir que le «faux» service en action. Il va générer des transactions aléatoires pour vous montrer comment se déroule le processus.', - 'recurring-index' => 'Please note that this feature is under active development and may not work as expected.', - 'recurring-create' => 'Please note that this feature is under active development and may not work as expected.', + 'recurring-index' => 'Veuillez noter que cette fonctionnalité est en cours de développement et peut ne pas fonctionner comme prévu.', + 'recurring-create' => 'Veuillez noter que cette fonctionnalité est en cours de développement et peut ne pas fonctionner comme prévu.', ]; diff --git a/resources/lang/fr_FR/firefly.php b/resources/lang/fr_FR/firefly.php index f082d0631f..3a515fa727 100644 --- a/resources/lang/fr_FR/firefly.php +++ b/resources/lang/fr_FR/firefly.php @@ -465,7 +465,7 @@ return [ 'pref_two_factor_auth_code_help' => 'Scanner le code QR avec une application sur votre téléphone comme Authy ou Google Authenticator et entrez le code généré.', 'pref_two_factor_auth_reset_code' => 'Réinitialiser le code de vérification', 'pref_two_factor_auth_disable_2fa' => 'Désactiver l\'authentification en deux étapes', - '2fa_use_secret_instead' => 'If you cannot scan the QR code, feel free to use the secret instead: :secret.', + '2fa_use_secret_instead' => 'Si vous ne pouvez pas scanner le code QR, vous pouvez utiliser le secret : :secret.', 'pref_save_settings' => 'Enregistrer les paramètres', 'saved_preferences' => 'Préférences enregistrées!', 'preferences_general' => 'Général', @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'Impossible de supprimer :name car il est encore utilisé.', 'deleted_currency' => 'Devise ":name" supprimée', 'created_currency' => 'Devise ":name" créée', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Devise ":name" mise à jour', 'ask_site_owner' => 'Merci de demander à :owner pour ajouter, modifier ou supprimer des devises.', 'currencies_intro' => 'Firefly III prend en charge diverses devises que vous pouvez configurer et activer ici.', @@ -1062,7 +1063,7 @@ return [ 'instance_configuration' => 'Configuration', 'firefly_instance_configuration' => 'Options de configuration pour Firefly III', 'setting_single_user_mode' => 'Mode utilisateur unique', - 'setting_single_user_mode_explain' => 'By default, Firefly III only accepts one (1) registration: you. This is a security measure, preventing others from using your instance unless you allow them to. Future registrations are blocked. When you uncheck this box, others can use your instance as well, assuming they can reach it (when it is connected to the internet).', + 'setting_single_user_mode_explain' => 'Par défaut, Firefly III accepte uniquement une (1) inscription : vous. Il s\'agit d\'une mesure de sécurité qui empêche les inconnus d\'utiliser votre instance, à moins que vous ne les y autorisiez. Les inscriptions futures sont bloquées. Lorsque vous désactivez cette case, d\'autres personnes peuvent utiliser votre instance, en supposant qu\'elles puissent l\'atteindre (quand elle est connectée à Internet).', 'store_configuration' => 'Sauvegarder la configuration', 'single_user_administration' => 'Gestion de l\'utilisateur pour :email', 'edit_user' => 'Modifier l\'utilisateur :email', @@ -1134,8 +1135,8 @@ return [ 'is (partially) refunded by_inward' => 'est (partiellement) remboursé par', 'is (partially) paid for by_inward' => 'est (partiellement) payé par', 'is (partially) reimbursed by_inward' => 'est (partiellement) remboursé par', - 'inward_transaction' => 'Inward transaction', - 'outward_transaction' => 'Outward transaction', + 'inward_transaction' => 'Opération entrante', + 'outward_transaction' => 'Opération sortante', 'relates to_outward' => 'se rapporte à', '(partially) refunds_outward' => 'rembourse (partiellement)', '(partially) pays for_outward' => 'paye (partiellement) pour', @@ -1157,9 +1158,9 @@ return [ 'cannot_convert_split_journal' => 'Vous ne pouvez pas convertir une transaction ventilée', // Import page (general strings only) - 'import_index_title' => 'Import transactions into Firefly III', + 'import_index_title' => 'Importer des opérations dans Firefly III', 'import_data' => 'Importer des données', - 'import_transactions' => 'Import transactions', + 'import_transactions' => 'Importer des opérations', // sandstorm.io errors and messages: 'sandstorm_not_available' => 'Cette fonction n\'est pas disponible lorsque vous utilisez Firefly III dans un environnement Sandstorm.io.', @@ -1211,66 +1212,66 @@ return [ 'no_bills_create_default' => 'Créer une facture', // recurring transactions - 'recurrences' => 'Recurring transactions', - 'no_recurring_title_default' => 'Let\'s create a recurring transaction!', - 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', - 'no_recurring_imperative_default' => 'This is a pretty advanced feature but it can be extremely useful. Make sure you read the documentation (?)-icon in the top right corner) before you continue.', - 'no_recurring_create_default' => 'Create a recurring transaction', - 'make_new_recurring' => 'Create a recurring transaction', - 'recurring_daily' => 'Every day', - 'recurring_weekly' => 'Every week on :weekday', - 'recurring_monthly' => 'Every month on the :dayOfMonth(st/nd/rd/th) day', - 'recurring_ndom' => 'Every month on the :dayOfMonth(st/nd/rd/th) :weekday', - 'recurring_yearly' => 'Every year on :date', - 'overview_for_recurrence' => 'Overview for recurring transaction ":title"', - 'warning_duplicates_repetitions' => 'In rare instances, dates appear twice in this list. This can happen when multiple repetitions collide. Firefly III will always generate one transaction per day.', - 'created_transactions' => 'Related transactions', - 'expected_Withdrawals' => 'Expected withdrawals', - 'expected_Deposits' => 'Expected deposits', - 'expected_Transfers' => 'Expected transfers', - 'created_Withdrawals' => 'Created withdrawals', - 'created_Deposits' => 'Created deposits', - 'created_Transfers' => 'Created transfers', - 'created_from_recurrence' => 'Created from recurring transaction ":title" (#:id)', + 'recurrences' => 'Opérations périodiques', + 'no_recurring_title_default' => 'Créons une opération périodique !', + 'no_recurring_intro_default' => 'Vous n’avez pas encore d\'opérations périodiques. Vous pouvez en utiliser pour que Firefly III crée automatiquement des opérations pour vous.', + 'no_recurring_imperative_default' => 'Il s’agit d’une fonctionnalité plutôt poussée, mais elle peut être très utile. Assurez-vous de lire la documentation ( icône ? en haut à droite) avant de continuer.', + 'no_recurring_create_default' => 'Créer une opération périodique', + 'make_new_recurring' => 'Créer une opération périodique', + 'recurring_daily' => 'Tous les jours', + 'recurring_weekly' => 'Chaque semaine le :weekday', + 'recurring_monthly' => 'Le :dayOfMonth(er/ème) jour de chaque mois', + 'recurring_ndom' => 'Le :dayOfMonth(er/ème) :weekday de chaque mois', + 'recurring_yearly' => 'Chaque année le :date', + 'overview_for_recurrence' => 'Aperçu de l’opération périodique ":title"', + 'warning_duplicates_repetitions' => 'Dans de rares cas, des dates apparaissent en double dans cette liste. Cela peut arriver lorsque plusieurs répétitions se superposent. Firefly III génèrera toujours une seule transaction par jour.', + 'created_transactions' => 'Opérations associées', + 'expected_Withdrawals' => 'Dépenses attendues', + 'expected_Deposits' => 'Revenus attendus', + 'expected_Transfers' => 'Transferts attendus', + 'created_Withdrawals' => 'Dépenses créées', + 'created_Deposits' => 'Revenus créés', + 'created_Transfers' => 'Transferts créés', + 'created_from_recurrence' => 'Créé à partir de l\'opération périodique ":title" (#:id)', - 'recurring_meta_field_tags' => 'Tags', + 'recurring_meta_field_tags' => 'Mots-clés', 'recurring_meta_field_notes' => 'Notes', - 'recurring_meta_field_bill_id' => 'Bill', - 'recurring_meta_field_piggy_bank_id' => 'Piggy bank', - 'create_new_recurrence' => 'Create new recurring transaction', - 'help_first_date' => 'Indicate the first expected recurrence. This must be in the future.', - 'help_first_date_no_past' => 'Indicate the first expected recurrence. Firefly III will not create transactions in the past.', - 'no_currency' => '(no currency)', - 'mandatory_for_recurring' => 'Mandatory recurrence information', - 'mandatory_for_transaction' => 'Mandatory transaction information', - 'optional_for_recurring' => 'Optional recurrence information', - 'optional_for_transaction' => 'Optional transaction information', - 'change_date_other_options' => 'Change the "first date" to see more options.', - 'mandatory_fields_for_tranaction' => 'The values here will end up in the transaction(s) being created', - 'click_for_calendar' => 'Click here for a calendar that shows you when the transaction would repeat.', - 'repeat_forever' => 'Repeat forever', - 'repeat_until_date' => 'Repeat until date', - 'repeat_times' => 'Repeat a number of times', - 'recurring_skips_one' => 'Every other', - 'recurring_skips_more' => 'Skips :count occurrences', - 'store_new_recurrence' => 'Store recurring transaction', - 'stored_new_recurrence' => 'Recurring transaction ":title" stored successfully.', - 'edit_recurrence' => 'Edit recurring transaction ":title"', - 'recurring_repeats_until' => 'Repeats until :date', - 'recurring_repeats_forever' => 'Repeats forever', - 'recurring_repeats_x_times' => 'Repeats :count time(s)', - 'update_recurrence' => 'Update recurring transaction', - 'updated_recurrence' => 'Updated recurring transaction ":title"', - 'recurrence_is_inactive' => 'This recurring transaction is not active and will not generate new transactions.', - 'delete_recurring' => 'Delete recurring transaction ":title"', - 'new_recurring_transaction' => 'New recurring transaction', - 'help_weekend' => 'What should Firefly III do when the recurring transaction falls on a Saturday or Sunday?', - 'do_nothing' => 'Just create the transaction', - 'skip_transaction' => 'Skip the occurence', - 'jump_to_friday' => 'Create the transaction on the previous Friday instead', - 'jump_to_monday' => 'Create the transaction on the next Monday instead', - 'will_jump_friday' => 'Will be created on Friday instead of the weekends.', - 'will_jump_monday' => 'Will be created on Monday instead of the weekends.', - 'except_weekends' => 'Except weekends', - 'recurrence_deleted' => 'Recurring transaction ":title" deleted', + 'recurring_meta_field_bill_id' => 'Facture', + 'recurring_meta_field_piggy_bank_id' => 'Tirelire', + 'create_new_recurrence' => 'Créer une nouvelle opération périodique', + 'help_first_date' => 'Indiquer la première occurrence attendue. Doit être dans le futur.', + 'help_first_date_no_past' => 'Indiquer la première occurrence attendue. Firefly III ne créera pas d\'opérations dans le passé.', + 'no_currency' => '(pas de devise)', + 'mandatory_for_recurring' => 'Informations de répétition obligatoires', + 'mandatory_for_transaction' => 'Informations d\'opération obligatoires', + 'optional_for_recurring' => 'Informations de répétition optionnelles', + 'optional_for_transaction' => 'Informations d\'opération optionnelles', + 'change_date_other_options' => 'Modifiez la date de début pour voir plus d\'options.', + 'mandatory_fields_for_tranaction' => 'Les valeurs ci-dessous seront enregistrées dans les opérations créées', + 'click_for_calendar' => 'Cliquez ici pour voir les répétitions des opérations sur un calendrier.', + 'repeat_forever' => 'Répéter pour toujours', + 'repeat_until_date' => 'Répéter jusqu\'à une date', + 'repeat_times' => 'Répéter un nombre de fois', + 'recurring_skips_one' => 'Tous les', + 'recurring_skips_more' => 'Passer :count répétitions', + 'store_new_recurrence' => 'Enregistrer l\'opération périodique', + 'stored_new_recurrence' => 'Opération périodique ":title" enregistrée avec succès.', + 'edit_recurrence' => 'Modifier l\'opération périodique ":title"', + 'recurring_repeats_until' => 'Se répète jusqu\'à :date', + 'recurring_repeats_forever' => 'Se répète pour toujours', + 'recurring_repeats_x_times' => 'Se répète :count fois', + 'update_recurrence' => 'Mettre à jour l\'opération périodique', + 'updated_recurrence' => 'Opération périodique ":title" mise à jour', + 'recurrence_is_inactive' => 'Cette opération périodique n’est pas active et ne génère pas de nouvelles opérations.', + 'delete_recurring' => 'Supprimer l\'opération périodique ":title"', + 'new_recurring_transaction' => 'Nouvelle opération périodique', + 'help_weekend' => 'Que doit faire Firefly III lorsque l’opération périodique tombe un samedi ou un dimanche ?', + 'do_nothing' => 'Créer l\'opération tout de même', + 'skip_transaction' => 'Ignorer l’occurrence', + 'jump_to_friday' => 'Créer l\'opération le vendredi précédent', + 'jump_to_monday' => 'Créer l\'opération le lundi suivant', + 'will_jump_friday' => 'Sera créé le vendredi plutôt que les week-ends.', + 'will_jump_monday' => 'Sera créé le lundi plutôt que les week-ends.', + 'except_weekends' => 'Sauf les week-ends', + 'recurrence_deleted' => 'Opération périodique ":title" supprimée', ]; diff --git a/resources/lang/fr_FR/form.php b/resources/lang/fr_FR/form.php index 574c59bd45..1577844085 100644 --- a/resources/lang/fr_FR/form.php +++ b/resources/lang/fr_FR/form.php @@ -43,13 +43,13 @@ return [ 'external_ip' => 'L\'adresse IP externe de votre serveur', 'attachments' => 'Documents joints', 'journal_amount' => 'Montant', - 'journal_source_name' => 'Revenue account (source)', - 'journal_source_id' => 'Asset account (source)', + 'journal_source_name' => 'Compte de recettes (source)', + 'journal_source_id' => 'Compte d’actif (source)', 'BIC' => 'Code BIC', 'verify_password' => 'Vérifiez la sécurité du mot de passe', 'source_account' => 'Compte d\'origine', 'destination_account' => 'Compte destinataire', - 'journal_destination_id' => 'Asset account (destination)', + 'journal_destination_id' => 'Compte d’actif (destination)', 'asset_destination_account' => 'Compte d’actif (destination)', 'asset_source_account' => 'Compte d’actif (source)', 'journal_description' => 'Description', @@ -150,7 +150,7 @@ return [ 'delete_rule_group' => 'Supprimer le groupe de filtres ":title"', 'delete_link_type' => 'Supprimer le type de lien ":name"', 'delete_user' => 'Supprimer l\'utilisateur ":email"', - 'delete_recurring' => 'Delete recurring transaction ":title"', + 'delete_recurring' => 'Supprimer l\'opération périodique ":title"', 'user_areYouSure' => 'Si vous supprimez l\'utilisateur ":email", tout disparaitra. Il n\'y a pas d\'annulation, de "dé-suppression" ou quoi que ce soit de la sorte. Si vous supprimez votre propre compte, vous n\'aurez plus accès à cette instance de Firefly III.', 'attachment_areYouSure' => 'Êtes-vous sûr de vouloir supprimer la pièce jointe nommée ":name" ?', 'account_areYouSure' => 'Êtes-vous sûr de vouloir supprimer le compte nommé ":name" ?', @@ -159,7 +159,7 @@ return [ 'ruleGroup_areYouSure' => 'Êtes-vous sûr de vouloir supprimer le groupe de règles intitulé ":title" ?', 'budget_areYouSure' => 'Êtes-vous sûr de vouloir supprimer le budget nommé ":name" ?', 'category_areYouSure' => 'Êtes-vous sûr de vouloir supprimer la catégorie nommée ":name" ?', - 'recurring_areYouSure' => 'Are you sure you want to delete the recurring transaction titled ":title"?', + 'recurring_areYouSure' => 'Êtes-vous sûr de vouloir supprimer l\'opération périodique intitulée ":title" ?', 'currency_areYouSure' => 'Êtes-vous sûr de vouloir supprimer la devise nommée ":name" ?', 'piggyBank_areYouSure' => 'Êtes-vous sûr de vouloir supprimer la tirelire nommée ":name" ?', 'journal_areYouSure' => 'Êtes-vous sûr de vouloir supprimer la description de l\'opération ":description" ?', @@ -175,11 +175,11 @@ return [ 'also_delete_connections' => 'La seule transaction liée à ce type de lien perdra cette connexion. | Toutes les transactions :count liées à ce type de lien perdront leur connexion.', 'also_delete_rules' => 'La seule règle liée à ce groupe de règles sera aussi supprimée.|Les :count règles liées à ce groupe de règles seront aussi supprimées.', 'also_delete_piggyBanks' => 'La seule tirelire liée à ce compte sera aussi supprimée.|Les :count tirelires liées à ce compte seront aussi supprimées.', - 'bill_keep_transactions' => 'The only transaction connected to this bill will not be deleted.|All :count transactions connected to this bill will be spared deletion.', - 'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will be spared deletion.', - 'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will be spared deletion.', - 'recurring_keep_transactions' => 'The only transaction created by this recurring transaction will not be deleted.|All :count transactions created by this recurring transaction will be spared deletion.', - 'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will be spared deletion.', + 'bill_keep_transactions' => 'La seule opération liée à cette facture ne sera pas supprimée.|Les :count opérations liées à cette facture ne seront pas supprimées.', + 'budget_keep_transactions' => 'La seule opération liée à ce budget ne sera pas supprimée.|Les :count opérations liées à ce budget ne seront pas supprimées.', + 'category_keep_transactions' => 'La seule opération liée à cette catégorie ne sera pas supprimée.|Les :count opérations liées à cette catégorie ne seront pas supprimées.', + 'recurring_keep_transactions' => 'La seule opération liée à cette opération périodique ne sera pas supprimée.|Les :count opérations liées à cette opération périodique ne seront pas supprimées.', + 'tag_keep_transactions' => 'La seule opération liée à ce tag ne sera pas supprimée.|Les :count opérations liées à ce tag ne seront pas supprimées.', 'check_for_updates' => 'Vérifier les mises à jour', 'email' => 'Adresse Email', @@ -226,16 +226,16 @@ return [ 'inward' => 'Description vers l’intérieur', 'outward' => 'Description de l’extérieur', 'rule_group_id' => 'Groupe de règles', - 'transaction_description' => 'Transaction description', - 'first_date' => 'First date', - 'transaction_type' => 'Transaction type', - 'repeat_until' => 'Repeat until', - 'recurring_description' => 'Recurring transaction description', - 'repetition_type' => 'Type of repetition', - 'foreign_currency_id' => 'Foreign currency', - 'repetition_end' => 'Repetition ends', - 'repetitions' => 'Repetitions', - 'calendar' => 'Calendar', - 'weekend' => 'Weekend', + 'transaction_description' => 'Description de la transaction', + 'first_date' => 'Date de début', + 'transaction_type' => 'Type de transaction', + 'repeat_until' => 'Répéter jusqu\'à', + 'recurring_description' => 'Description de l\'opération périodique', + 'repetition_type' => 'Type de répétition', + 'foreign_currency_id' => 'Devise étrangère', + 'repetition_end' => 'Fin de répétition', + 'repetitions' => 'Répétitions', + 'calendar' => 'Calendrier', + 'weekend' => 'Week-end', ]; diff --git a/resources/lang/fr_FR/import.php b/resources/lang/fr_FR/import.php index 609ca1d477..511bba370b 100644 --- a/resources/lang/fr_FR/import.php +++ b/resources/lang/fr_FR/import.php @@ -51,25 +51,25 @@ return [ 'need_prereq_intro' => 'Certaines méthodes d\'importation nécessitent votre attention avant de pouvoir être utilisées. Par exemple, elles peuvent nécessiter des clés d\'API spéciales ou des clés secrètes. Vous pouvez les configurer ici. L\'icône indique si ces conditions préalables ont été remplies.', 'do_prereq_fake' => 'Prérequis pour la simulation', 'do_prereq_file' => 'Prérequis pour les importations de fichiers', - 'do_prereq_bunq' => 'Prerequisites for imports from bunq', - 'do_prereq_spectre' => 'Prerequisites for imports using Spectre', - 'do_prereq_plaid' => 'Prerequisites for imports using Plaid', - 'do_prereq_yodlee' => 'Prerequisites for imports using Yodlee', - 'do_prereq_quovo' => 'Prerequisites for imports using Quovo', + 'do_prereq_bunq' => 'Prérequis pour les importations depuis Bunq', + 'do_prereq_spectre' => 'Prérequis pour les importations depuis Spectre', + 'do_prereq_plaid' => 'Prérequis pour les importations depuis Plaid', + 'do_prereq_yodlee' => 'Prérequis pour les importations depuis Yodlee', + 'do_prereq_quovo' => 'Prérequis pour les importations depuis Quovo', // provider config box (index) - 'can_config_title' => 'Import configuration', - 'can_config_intro' => 'Some import methods can be configured to your liking. They have extra settings you can tweak.', - 'do_config_fake' => 'Configuration for the fake provider', - 'do_config_file' => 'Configuration for file imports', - 'do_config_bunq' => 'Configuration for bunq imports', - 'do_config_spectre' => 'Configuration for imports from Spectre', - 'do_config_plaid' => 'Configuration for imports from Plaid', - 'do_config_yodlee' => 'Configuration for imports from Yodlee', - 'do_config_quovo' => 'Configuration for imports from Quovo', + 'can_config_title' => 'Configuration d\'importation', + 'can_config_intro' => 'Certaines méthodes d’importation peuvent être configurées selon vos préférences. Elles ont des paramètres supplémentaires que vous pouvez modifier.', + 'do_config_fake' => 'Configuration du simulateur d\'importation', + 'do_config_file' => 'Configuration pour l’importation de fichier', + 'do_config_bunq' => 'Configuration pour les importations depuis Bunq', + 'do_config_spectre' => 'Configuration pour les importations depuis Spectre', + 'do_config_plaid' => 'Configuration pour les importations depuis Plaid', + 'do_config_yodlee' => 'Configuration pour les importations depuis Yodlee', + 'do_config_quovo' => 'Configuration pour les importations depuis Quovo', // prerequisites: - 'prereq_fake_title' => 'Prerequisites for an import from the fake import provider', - 'prereq_fake_text' => 'This fake provider requires a fake API key. It must be 32 characters long. You can use this one: 123456789012345678901234567890AA', + 'prereq_fake_title' => 'Prérequis pour une importation utilisant le simulateur d\'importation', + 'prereq_fake_text' => 'Le simulateur d\'importation nécessite une fausse clé d\'API. Vous pouvez utiliser la clé suivante : 123456789012345678901234567890AA', 'prereq_spectre_title' => 'Prerequisites for an import using the Spectre API', 'prereq_spectre_text' => 'In order to import data using the Spectre API (v4), you must provide Firefly III with two secret values. They can be found on the secrets page.', 'prereq_spectre_pub' => 'Likewise, the Spectre API needs to know the public key you see below. Without it, it will not recognize you. Please enter this public key on your secrets page.', @@ -243,11 +243,11 @@ return [ 'column_date-payment' => 'Date de paiement de la transaction', 'column_date-invoice' => 'Date de facturation de la transaction', 'column_description' => 'Description', - 'column_opposing-iban' => 'Compte destinataire (IBAN)', - 'column_opposing-bic' => 'Compte destinataire (BIC)', - 'column_opposing-id' => 'Compte destinataire (ID correspondant à FF3)', + 'column_opposing-iban' => 'Compte opposé (IBAN)', + 'column_opposing-bic' => 'Compte opposé (BIC)', + 'column_opposing-id' => 'Compte opposé (ID correspondant à FF3)', 'column_external-id' => 'ID externe', - 'column_opposing-name' => 'Compte destinataire (nom)', + 'column_opposing-name' => 'Compte opposé (nom)', 'column_rabo-debit-credit' => 'Indicateur de débit/crédit spécifique à Rabobank', 'column_ing-debit-credit' => 'Indicateur de débit/crédit spécifique à ING', 'column_sepa-ct-id' => 'Référence de bout en bout SEPA', diff --git a/resources/lang/fr_FR/list.php b/resources/lang/fr_FR/list.php index c2d0261328..2b744d390b 100644 --- a/resources/lang/fr_FR/list.php +++ b/resources/lang/fr_FR/list.php @@ -123,9 +123,9 @@ return [ 'spectre_last_use' => 'Dernière connexion', 'spectre_status' => 'Statut', 'bunq_payment_id' => 'ID de paiement bunq', - 'repetitions' => 'Repetitions', - 'title' => 'Title', - 'transaction_s' => 'Transaction(s)', - 'field' => 'Field', - 'value' => 'Value', + 'repetitions' => 'Répétitions', + 'title' => 'Titre', + 'transaction_s' => 'Opération(s)', + 'field' => 'Champ', + 'value' => 'Valeur', ]; diff --git a/resources/lang/fr_FR/validation.php b/resources/lang/fr_FR/validation.php index e5277aa087..1ae9f2a1f3 100644 --- a/resources/lang/fr_FR/validation.php +++ b/resources/lang/fr_FR/validation.php @@ -24,7 +24,7 @@ declare(strict_types=1); return [ 'iban' => 'Il ne s\'agit pas d\'un IBAN valide.', - 'source_equals_destination' => 'The source account equals the destination account.', + 'source_equals_destination' => 'Le compte source est égal au compte de destination.', 'unique_account_number_for_user' => 'Il semble que ce numéro de compte est déjà utilisé.', 'unique_iban_for_user' => 'Il semble que cet IBAN soit déjà utilisé.', 'deleted_user' => 'Compte tenu des contraintes de sécurité, vous ne pouvez pas vous inscrire en utilisant cette adresse e-mail.', @@ -34,22 +34,22 @@ return [ 'file_attached' => 'Envoi du fichier ":name" avec succès.', 'must_exist' => 'L\'ID dans le champ :attribute n\'existe pas dans la base de données.', 'all_accounts_equal' => 'Tous les comptes dans ce champ doivent être égaux.', - 'invalid_selection' => 'Your selection is invalid.', + 'invalid_selection' => 'Votre sélection est invalide.', 'belongs_user' => 'Cette valeur n\'est pas valide pour ce champ.', 'at_least_one_transaction' => 'Besoin d\'au moins une transaction.', - 'at_least_one_repetition' => 'Need at least one repetition.', - 'require_repeat_until' => 'Require either a number of repetitions, or an end date (repeat_until). Not both.', + 'at_least_one_repetition' => 'Besoin d\'au moins une répétition.', + 'require_repeat_until' => 'Besoin d’un certain nombre de répétitions ou d\'une date de fin (repeat_until). Pas les deux.', 'require_currency_info' => 'Le contenu de ce champ n\'est pas valide sans informations sur la devise.', 'equal_description' => 'La description de la transaction ne doit pas être égale à la description globale.', 'file_invalid_mime' => 'Le fichier ":name" est du type ":mime" ce qui n\'est pas accepté pour un nouvel envoi.', 'file_too_large' => 'Le fichier ":name" est trop grand.', - 'belongs_to_user' => 'The value of :attribute is unknown.', + 'belongs_to_user' => 'La valeur de :attribute est inconnue.', 'accepted' => 'Le champ :attribute doit être accepté.', 'bic' => 'Ce n’est pas un code BIC valide.', - 'at_least_one_trigger' => 'Rule must have at least one trigger.', - 'at_least_one_action' => 'Rule must have at least one action.', - 'base64' => 'This is not valid base64 encoded data.', - 'model_id_invalid' => 'The given ID seems invalid for this model.', + 'at_least_one_trigger' => 'Une règle doit avoir au moins un déclencheur.', + 'at_least_one_action' => 'Une règle doit avoir au moins une action.', + 'base64' => 'Il ne s\'agit pas de données base64 valides.', + 'model_id_invalid' => 'L’ID fournit ne semble pas valide pour ce modèle.', 'more' => ':attribute doit être supérieur à zéro.', 'active_url' => 'Le champ :attribute n\'est pas une URL valide.', 'after' => 'Le champ :attribute doit être une date postérieure à :date.', @@ -59,8 +59,8 @@ return [ 'array' => 'Le champ :attribute doit être un tableau.', 'unique_for_user' => 'Il existe déjà une entrée avec ceci :attribute.', 'before' => 'Le champ :attribute doit être une date antérieure à :date.', - 'unique_object_for_user' => 'This name is already in use.', - 'unique_account_for_user' => 'This account name is already in use.', + 'unique_object_for_user' => 'Ce nom est déjà utilisé.', + 'unique_account_for_user' => 'Ce nom de compte est déjà utilisé.', 'between.numeric' => 'La valeur de :attribute doit être comprise entre :min et :max.', 'between.file' => 'Le fichier :attribute doit avoir une taille entre :min et :max kilo-octets.', 'between.string' => 'Le texte :attribute doit avoir entre :min et :max caractères.', @@ -91,9 +91,9 @@ return [ 'min.array' => 'Le tableau :attribute doit avoir au moins :min éléments.', 'not_in' => 'Le champ :attribute sélectionné n\'est pas valide.', 'numeric' => 'Le champ :attribute doit contenir un nombre.', - 'numeric_native' => 'The native amount must be a number.', - 'numeric_destination' => 'The destination amount must be a number.', - 'numeric_source' => 'The source amount must be a number.', + 'numeric_native' => 'Le montant natif doit être un nombre.', + 'numeric_destination' => 'Le montant de destination doit être un nombre.', + 'numeric_source' => 'Le montant source doit être un nombre.', 'regex' => 'Le format du champ :attribute est invalide.', 'required' => 'Le champ :attribute est obligatoire.', 'required_if' => 'Le champ :attribute est obligatoire quand la valeur de :other est :value.', @@ -118,12 +118,12 @@ return [ 'file' => 'Le :attribute doit être un fichier.', 'in_array' => 'Le champ :attribute n\'existe pas dans :other.', 'present' => 'Le champs :attribute doit être rempli.', - 'amount_zero' => 'The total amount cannot be zero.', + 'amount_zero' => 'Le montant total ne peut pas être zéro.', 'unique_piggy_bank_for_user' => 'Le nom de la tirelire doit être unique.', - 'secure_password' => 'This is not a secure password. Please try again. For more information, visit http://bit.ly/FF3-password-security.', - 'valid_recurrence_rep_type' => 'Invalid repetition type for recurring transactions.', - 'valid_recurrence_rep_moment' => 'Invalid repetition moment for this type of repetition.', - 'invalid_account_info' => 'Invalid account information.', + 'secure_password' => 'Ce n’est pas un mot de passe sécurisé. Veuillez essayer à nouveau. Pour plus d’informations, visitez http://bit.ly/FF3-password-security.', + 'valid_recurrence_rep_type' => 'Type de répétition non valide pour des opérations périodiques.', + 'valid_recurrence_rep_moment' => 'Période de répétition non valide pour ce type de répétition.', + 'invalid_account_info' => 'Informations de compte non valides.', 'attributes' => [ 'email' => 'adresse email', 'description' => 'description', diff --git a/resources/lang/id_ID/firefly.php b/resources/lang/id_ID/firefly.php index d5a358e8a8..9ca397822f 100644 --- a/resources/lang/id_ID/firefly.php +++ b/resources/lang/id_ID/firefly.php @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'Tidak dapat menghapus :name karena masih digunakan.', 'deleted_currency' => 'Mata uang :name dihapus', 'created_currency' => 'Mata uang :name dibuat', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Mata uang :name diperbarui', 'ask_site_owner' => 'Harap bertanya :owner untuk menambahkan, menghapus atau mengedit mata uang.', 'currencies_intro' => 'Firefly III mendukung berbagai mata uang yang dapat Anda atur dan aktifkan di sini.', diff --git a/resources/lang/it_IT/firefly.php b/resources/lang/it_IT/firefly.php index e8ac7bec0d..6006229752 100644 --- a/resources/lang/it_IT/firefly.php +++ b/resources/lang/it_IT/firefly.php @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'Impossibile eliminare :name perché è ancora in uso.', 'deleted_currency' => 'Valuta :name elimina', 'created_currency' => 'Valuta :name creata', + 'could_not_store_currency' => 'Impossibile memorizzare la nuova valuta.', 'updated_currency' => 'Valuta :name aggiornata', 'ask_site_owner' => 'Chiedi a :owner di aggiungere, rimuovere o modificare valute.', 'currencies_intro' => 'Firefly III supporta varie valute che è possibile impostare e abilitare qui.', diff --git a/resources/lang/nl_NL/firefly.php b/resources/lang/nl_NL/firefly.php index 6e4acdc31b..3a66818cd8 100644 --- a/resources/lang/nl_NL/firefly.php +++ b/resources/lang/nl_NL/firefly.php @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'Kan ":name" niet verwijderen, want deze is in gebruik.', 'deleted_currency' => 'Valuta :name verwijderd', 'created_currency' => 'Nieuwe valuta :name opgeslagen', + 'could_not_store_currency' => 'Kon nieuwe valuta niet opslaan.', 'updated_currency' => 'Valuta :name bijgewerkt', 'ask_site_owner' => 'Vraag :owner of deze valuta wilt toevoegen, verwijderen of wijzigen.', 'currencies_intro' => 'Firefly III ondersteunt diverse valuta die je hier kan instellen en bewerken.', diff --git a/resources/lang/pl_PL/firefly.php b/resources/lang/pl_PL/firefly.php index c23c3c6557..0ecac118f5 100644 --- a/resources/lang/pl_PL/firefly.php +++ b/resources/lang/pl_PL/firefly.php @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'Nie można usunąć waluty :name, ponieważ jest ona nadal używana.', 'deleted_currency' => 'Waluta :name została usunięta', 'created_currency' => 'Waluta :name została utworzona', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Waluta :name została zmodyfikowana', 'ask_site_owner' => 'Poproś :owner aby dodał, usunął lub zmodyfikował waluty.', 'currencies_intro' => 'Firefly III obsługuje różne waluty, które można ustawić i włączyć tutaj.', @@ -1157,7 +1158,7 @@ return [ 'cannot_convert_split_journal' => 'Nie można przekonwertować podzielonej transakcji', // Import page (general strings only) - 'import_index_title' => 'Import transactions into Firefly III', + 'import_index_title' => 'Importuj transakcje do Firefly III', 'import_data' => 'Importuj dane', 'import_transactions' => 'Importuj transakcje', @@ -1212,7 +1213,7 @@ return [ // recurring transactions 'recurrences' => 'Cykliczne transakcje', - 'no_recurring_title_default' => 'Let\'s create a recurring transaction!', + 'no_recurring_title_default' => 'Utwórzmy cykliczną transakcję!', 'no_recurring_intro_default' => 'You have no recurring transactions yet. You can use these to make Firefly III automatically create transactions for you.', 'no_recurring_imperative_default' => 'This is a pretty advanced feature but it can be extremely useful. Make sure you read the documentation (?)-icon in the top right corner) before you continue.', 'no_recurring_create_default' => 'Utwórz cykliczną transakcję', @@ -1248,29 +1249,29 @@ return [ 'change_date_other_options' => 'Change the "first date" to see more options.', 'mandatory_fields_for_tranaction' => 'The values here will end up in the transaction(s) being created', 'click_for_calendar' => 'Click here for a calendar that shows you when the transaction would repeat.', - 'repeat_forever' => 'Repeat forever', + 'repeat_forever' => 'Powtarzaj bez końca', 'repeat_until_date' => 'Powtarzaj aż do dnia', 'repeat_times' => 'Powtarzaj określoną liczbę razy', 'recurring_skips_one' => 'Every other', 'recurring_skips_more' => 'Skips :count occurrences', - 'store_new_recurrence' => 'Store recurring transaction', + 'store_new_recurrence' => 'Zachowaj cykliczną transakcję', 'stored_new_recurrence' => 'Recurring transaction ":title" stored successfully.', - 'edit_recurrence' => 'Edit recurring transaction ":title"', - 'recurring_repeats_until' => 'Repeats until :date', - 'recurring_repeats_forever' => 'Repeats forever', - 'recurring_repeats_x_times' => 'Repeats :count time(s)', - 'update_recurrence' => 'Update recurring transaction', + 'edit_recurrence' => 'Modyfikuj cykliczną transakcję ":title"', + 'recurring_repeats_until' => 'Powtarzaj aż do :date', + 'recurring_repeats_forever' => 'Powtarza się bez końca', + 'recurring_repeats_x_times' => 'Powtarzaj :count raz(y)', + 'update_recurrence' => 'Aktualizuj cykliczną transakcję', 'updated_recurrence' => 'Updated recurring transaction ":title"', 'recurrence_is_inactive' => 'This recurring transaction is not active and will not generate new transactions.', 'delete_recurring' => 'Delete recurring transaction ":title"', - 'new_recurring_transaction' => 'New recurring transaction', - 'help_weekend' => 'What should Firefly III do when the recurring transaction falls on a Saturday or Sunday?', - 'do_nothing' => 'Just create the transaction', - 'skip_transaction' => 'Skip the occurence', + 'new_recurring_transaction' => 'Nowa cykliczna transakcja', + 'help_weekend' => 'Co powinien zrobić Firefly III, jeśli cykliczna transakcja się nie powiedzie w Sobotę lub Niedzielę?', + 'do_nothing' => 'Po prostu utwórz transakcję', + 'skip_transaction' => 'Pomiń wystąpienie', 'jump_to_friday' => 'Create the transaction on the previous Friday instead', 'jump_to_monday' => 'Create the transaction on the next Monday instead', 'will_jump_friday' => 'Will be created on Friday instead of the weekends.', 'will_jump_monday' => 'Will be created on Monday instead of the weekends.', - 'except_weekends' => 'Except weekends', - 'recurrence_deleted' => 'Recurring transaction ":title" deleted', + 'except_weekends' => 'Pomiń weekendy', + 'recurrence_deleted' => 'Cykliczna transakcja ":title" została usunięta', ]; diff --git a/resources/lang/pl_PL/form.php b/resources/lang/pl_PL/form.php index fe09cafffd..8e14752274 100644 --- a/resources/lang/pl_PL/form.php +++ b/resources/lang/pl_PL/form.php @@ -43,13 +43,13 @@ return [ 'external_ip' => 'Zewnętrzny adres IP Twojego serwera', 'attachments' => 'Załączniki', 'journal_amount' => 'Kwota', - 'journal_source_name' => 'Revenue account (source)', - 'journal_source_id' => 'Asset account (source)', + 'journal_source_name' => 'Konto przychodów (źródło)', + 'journal_source_id' => 'Konto aktywów (źródło)', 'BIC' => 'BIC', 'verify_password' => 'Sprawdź bezpieczeństwo hasła', 'source_account' => 'Konto źródłowe', 'destination_account' => 'Konto docelowe', - 'journal_destination_id' => 'Asset account (destination)', + 'journal_destination_id' => 'Konto aktywów (przeznaczenie)', 'asset_destination_account' => 'Konto aktywów (przeznaczenie)', 'asset_source_account' => 'Konto aktywów (źródło)', 'journal_description' => 'Opis', @@ -150,7 +150,7 @@ return [ 'delete_rule_group' => 'Usuń grupę reguł ":title"', 'delete_link_type' => 'Usuń typ łącza ":name"', 'delete_user' => 'Usuń użytkownika ":email"', - 'delete_recurring' => 'Delete recurring transaction ":title"', + 'delete_recurring' => 'Usuń cykliczną transakcję ":title"', 'user_areYouSure' => 'Jeśli usuniesz użytkownika ":email", wszystko zniknie. Nie ma cofania, przywracania ani czegokolwiek. Jeśli usuniesz siebie, stracisz dostęp do tej instalacji Firefly III.', 'attachment_areYouSure' => 'Czy na pewno chcesz usunąć załącznik o nazwie ":name"?', 'account_areYouSure' => 'Czy na pewno chcesz usunąć konto o nazwie ":name"?', diff --git a/resources/lang/pl_PL/import.php b/resources/lang/pl_PL/import.php index 8e2b109e85..7fb904c8e4 100644 --- a/resources/lang/pl_PL/import.php +++ b/resources/lang/pl_PL/import.php @@ -33,7 +33,7 @@ return [ 'cannot_create_for_provider' => 'Firefly III cannot create a job for the ":provider"-provider.', // index page: - 'general_index_title' => 'Import a file', + 'general_index_title' => 'Importuj plik', 'general_index_intro' => 'Welcome to Firefly III\'s import routine. There are a few ways of importing data into Firefly III, displayed here as buttons.', // import provider strings (index): 'button_fake' => 'Fake an import', @@ -97,8 +97,8 @@ return [ 'job_config_file_upload_text' => 'This routine will help you import files from your bank into Firefly III. ', 'job_config_file_upload_help' => 'Select your file. Please make sure the file is UTF-8 encoded.', 'job_config_file_upload_config_help' => 'If you have previously imported data into Firefly III, you may have a configuration file, which will pre-set configuration values for you. For some banks, other users have kindly provided their configuration file', - 'job_config_file_upload_type_help' => 'Select the type of file you will upload', - 'job_config_file_upload_submit' => 'Upload files', + 'job_config_file_upload_type_help' => 'Wybierz typ pliku, który będziesz przesyłać', + 'job_config_file_upload_submit' => 'Prześlij pliki', 'import_file_type_csv' => 'CSV (wartości oddzielone przecinkami)', 'file_not_utf8' => 'The file you have uploaded is not encoded as UTF-8 or ASCII. Firefly III cannot handle such files. Please use Notepad++ or Sublime to convert your file to UTF-8.', 'job_config_uc_title' => 'Import setup (2/4) - Basic file setup', @@ -127,7 +127,7 @@ return [ 'spectre_no_mapping' => 'Wygląda na to, że nie wybrałeś żadnych kont z których można zaimportować dane.', 'imported_from_account' => 'Zaimportowane z ":account"', 'spectre_account_with_number' => ':number konta', - 'job_config_spectre_apply_rules' => 'Apply rules', + 'job_config_spectre_apply_rules' => 'Zastosuj reguły', 'job_config_spectre_apply_rules_text' => 'By default, your rules will be applied to the transactions created during this import routine. If you do not want this to happen, deselect this checkbox.', // job configuration for bunq: 'job_config_bunq_accounts_title' => 'konta bunq', @@ -135,7 +135,7 @@ return [ 'bunq_no_mapping' => 'It seems you have not selected any accounts.', 'should_download_config' => 'You should download the configuration file for this job. This will make future imports way easier.', 'share_config_file' => 'If you have imported data from a public bank, you should share your configuration file so it will be easy for other users to import their data. Sharing your configuration file will not expose your financial details.', - 'job_config_bunq_apply_rules' => 'Apply rules', + 'job_config_bunq_apply_rules' => 'Zastosuj reguły', 'job_config_bunq_apply_rules_text' => 'By default, your rules will be applied to the transactions created during this import routine. If you do not want this to happen, deselect this checkbox.', // keys from "extra" array: 'spectre_extra_key_iban' => 'IBAN', @@ -149,14 +149,14 @@ return [ 'spectre_extra_key_available_amount' => 'Dostępna kwota', 'spectre_extra_key_credit_limit' => 'Limit kredytowy', 'spectre_extra_key_interest_rate' => 'Oprocentowanie', - 'spectre_extra_key_expiry_date' => 'Expiry date', + 'spectre_extra_key_expiry_date' => 'Data wygaśnięcia', 'spectre_extra_key_open_date' => 'Data otwarcia', 'spectre_extra_key_current_time' => 'Aktualny czas', - 'spectre_extra_key_current_date' => 'Current date', - 'spectre_extra_key_cards' => 'Cards', - 'spectre_extra_key_units' => 'Units', - 'spectre_extra_key_unit_price' => 'Unit price', - 'spectre_extra_key_transactions_count' => 'Transaction count', + 'spectre_extra_key_current_date' => 'Aktualna data', + 'spectre_extra_key_cards' => 'Karty', + 'spectre_extra_key_units' => 'Jednostki', + 'spectre_extra_key_unit_price' => 'Cena jednostkowa', + 'spectre_extra_key_transactions_count' => 'Liczba transakcji', // specifics: 'specific_ing_name' => 'ING NL', @@ -196,16 +196,16 @@ return [ 'status_wait_title' => 'Proszę czekać...', 'status_wait_text' => 'To pole za chwilę zniknie.', 'status_running_title' => 'Trwa importowanie', - 'status_job_running' => 'Please wait, running the import...', - 'status_job_storing' => 'Please wait, storing data...', - 'status_job_rules' => 'Please wait, running rules...', + 'status_job_running' => 'Proszę czekać, trwa importowanie danych...', + 'status_job_storing' => 'Proszę czekać, zapisuję dane...', + 'status_job_rules' => 'Proszę czekać, trwa procesowanie reguł...', 'status_fatal_title' => 'Błąd krytyczny', 'status_fatal_text' => 'The import has suffered from an error it could not recover from. Apologies!', 'status_fatal_more' => 'This (possibly very cryptic) error message is complemented by log files, which you can find on your hard drive, or in the Docker container where you run Firefly III from.', 'status_finished_title' => 'Import zakończony', 'status_finished_text' => 'Importowanie zostało zakończone.', 'finished_with_errors' => 'There were some errors during the import. Please review them carefully.', - 'unknown_import_result' => 'Unknown import result', + 'unknown_import_result' => 'Nieznany wynik importu', 'result_no_transactions' => 'No transactions have been imported. Perhaps they were all duplicates is simply no transactions where present to be imported. Perhaps the log files can tell you what happened. If you import data regularly, this is normal.', 'result_one_transaction' => 'Exactly one transaction has been imported. It is stored under tag :tag where you can inspect it further.', 'result_many_transactions' => 'Firefly III has imported :count transactions. They are stored under tag :tag where you can inspect them further.', @@ -244,7 +244,7 @@ return [ 'column_date-invoice' => 'Transaction invoice date', 'column_description' => 'Opis', 'column_opposing-iban' => 'Przeciwstawne konto (IBAN)', - 'column_opposing-bic' => 'Opposing account (BIC)', + 'column_opposing-bic' => 'Przeciwstawne konto (BIC)', 'column_opposing-id' => 'ID przeciwstawnego konta (z bazy FF3)', 'column_external-id' => 'Zewnętrzne ID', 'column_opposing-name' => 'Przeciwstawne konto (nazwa)', diff --git a/resources/lang/pl_PL/validation.php b/resources/lang/pl_PL/validation.php index 2cd06c8b85..0e8adfdf34 100644 --- a/resources/lang/pl_PL/validation.php +++ b/resources/lang/pl_PL/validation.php @@ -34,10 +34,10 @@ return [ 'file_attached' => 'Pomyślnie wgrano plik ":name".', 'must_exist' => 'Identyfikator w polu :attribute nie istnieje w bazie danych.', 'all_accounts_equal' => 'Wszystkie konta w tym polu muszą być takie same.', - 'invalid_selection' => 'Your selection is invalid.', + 'invalid_selection' => 'Twój wybór jest nieprawidłowy.', 'belongs_user' => 'Ta wartość jest nieprawidłowa dla tego pola.', 'at_least_one_transaction' => 'Wymaga co najmniej jednej transakcji.', - 'at_least_one_repetition' => 'Need at least one repetition.', + 'at_least_one_repetition' => 'Wymaga co najmniej jednego powtórzenia.', 'require_repeat_until' => 'Require either a number of repetitions, or an end date (repeat_until). Not both.', 'require_currency_info' => 'Treść tego pola jest nieprawidłowa bez informacji o walucie.', 'equal_description' => 'Opis transakcji nie powinien być równy globalnemu opisowi.', @@ -46,9 +46,9 @@ return [ 'belongs_to_user' => 'The value of :attribute is unknown.', 'accepted' => ':attribute musi zostać zaakceptowany.', 'bic' => 'To nie jest prawidłowy BIC.', - 'at_least_one_trigger' => 'Rule must have at least one trigger.', - 'at_least_one_action' => 'Rule must have at least one action.', - 'base64' => 'This is not valid base64 encoded data.', + 'at_least_one_trigger' => 'Reguła powinna mieć co najmniej jeden wyzwalacz.', + 'at_least_one_action' => 'Reguła powinna mieć co najmniej jedną akcję.', + 'base64' => 'To nie są prawidłowe dane zakodowane w base64.', 'model_id_invalid' => 'The given ID seems invalid for this model.', 'more' => ':attribute musi być większy od zera.', 'active_url' => ':attribute nie jest prawidłowym adresem URL.', @@ -59,8 +59,8 @@ return [ 'array' => ':attribute musi być tablicą.', 'unique_for_user' => 'Istnieje już wpis z tym :attribute.', 'before' => ':attribute musi być wcześniejszą datą w stosunku do :date.', - 'unique_object_for_user' => 'This name is already in use.', - 'unique_account_for_user' => 'This account name is already in use.', + 'unique_object_for_user' => 'Ta nazwa jest już w użyciu.', + 'unique_account_for_user' => 'Ta nazwa konta jest już w użyciu.', 'between.numeric' => ':attribute musi się mieścić w zakresie pomiędzy :min a :max.', 'between.file' => ':attribute musi się mieścić w zakresie pomiędzy :min oraz :max kilobajtów.', 'between.string' => ':attribute musi zawierać pomiędzy :min a :max znaków.', @@ -92,8 +92,8 @@ return [ 'not_in' => 'Wybrany :attribute jest nieprawidłowy.', 'numeric' => ':attribute musi byc liczbą.', 'numeric_native' => 'The native amount must be a number.', - 'numeric_destination' => 'The destination amount must be a number.', - 'numeric_source' => 'The source amount must be a number.', + 'numeric_destination' => 'Kwota docelowa musi być liczbą.', + 'numeric_source' => 'Kwota źródłowa musi być liczbą.', 'regex' => 'Format :attribute jest nieprawidłowy.', 'required' => 'Pole :attribute jest wymagane.', 'required_if' => 'Pole :attribute jest wymagane gdy :other jest :value.', @@ -118,12 +118,12 @@ return [ 'file' => ':attribute musi być plikiem.', 'in_array' => 'Pole :attribute nie istnieje w :other.', 'present' => 'Pole :attribute musi być obecne.', - 'amount_zero' => 'The total amount cannot be zero.', - 'unique_piggy_bank_for_user' => 'The name of the piggy bank must be unique.', - 'secure_password' => 'This is not a secure password. Please try again. For more information, visit http://bit.ly/FF3-password-security.', + 'amount_zero' => 'Całkowita kwota nie może wynosić zero.', + 'unique_piggy_bank_for_user' => 'Nazwa skarbonki musi być unikalna.', + 'secure_password' => 'To nie jest bezpieczne hasło. Proszę spróbować ponownie. Aby uzyskać więcej informacji odwiedź http://bit.ly/FF3-password-security.', 'valid_recurrence_rep_type' => 'Invalid repetition type for recurring transactions.', 'valid_recurrence_rep_moment' => 'Invalid repetition moment for this type of repetition.', - 'invalid_account_info' => 'Invalid account information.', + 'invalid_account_info' => 'Nieprawidłowe informacje o koncie.', 'attributes' => [ 'email' => 'adres e-mail', 'description' => 'opis', diff --git a/resources/lang/pt_BR/firefly.php b/resources/lang/pt_BR/firefly.php index 41ad6e78ff..b69e504001 100644 --- a/resources/lang/pt_BR/firefly.php +++ b/resources/lang/pt_BR/firefly.php @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'Não é possível excluir :name porque ainda está em uso.', 'deleted_currency' => 'Moeda :name excluída', 'created_currency' => 'Moeda :name criada', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Moeda :name atualizada', 'ask_site_owner' => 'Por favor, pergunte ao :owner para adicionar, remover ou editar moedas.', 'currencies_intro' => 'Firefly III oferece suporte a várias moedas que você pode definir e ativar aqui.', diff --git a/resources/lang/ru_RU/firefly.php b/resources/lang/ru_RU/firefly.php index c18e2716da..ada0cadb33 100644 --- a/resources/lang/ru_RU/firefly.php +++ b/resources/lang/ru_RU/firefly.php @@ -607,6 +607,7 @@ return [ 'cannot_delete_currency' => 'Невозможно удалить валюту :name, поскольку она используется.', 'deleted_currency' => 'Валюта :name удалена', 'created_currency' => 'Валюта :name создана', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Валюта :name обновлена', 'ask_site_owner' => 'Пожалуйста, обратитесь к :owner для добавления, удаления или изменения валюты.', 'currencies_intro' => 'Firefly III может работать с несколькими валютами. Вы можете управлять ими здесь.', diff --git a/resources/lang/tr_TR/firefly.php b/resources/lang/tr_TR/firefly.php index e7e77d38ab..eff00bba00 100644 --- a/resources/lang/tr_TR/firefly.php +++ b/resources/lang/tr_TR/firefly.php @@ -610,6 +610,7 @@ işlemlerin kontrol edildiğini lütfen unutmayın.', 'cannot_delete_currency' => ':name hala kullanıldığı için silinemiyor.', 'deleted_currency' => 'Para birimi :name silindi', 'created_currency' => 'Para birimi :name oluşturuldu', + 'could_not_store_currency' => 'Could not store the new currency.', 'updated_currency' => 'Para birimi :name güncellendi', 'ask_site_owner' => 'Lütfen para birimleri eklemek, kaldırmak veya düzenlemek için :owner\'a danışın.', 'currencies_intro' => 'Firefly III, burada ayarlayabileceğiniz ve etkinleştirebileceğiniz çeşitli para birimlerini destekliyor.', diff --git a/resources/views/reports/partials/journals-audit.twig b/resources/views/reports/partials/journals-audit.twig index b59e9103b7..b3d1c88381 100644 --- a/resources/views/reports/partials/journals-audit.twig +++ b/resources/views/reports/partials/journals-audit.twig @@ -57,11 +57,12 @@ {% endif %} - {{ formatAmountByCurrency(transaction.currency, transaction.before) }} + + {{ formatAmountByCurrency(transaction.transactionCurrency, transaction.before) }} {{ transaction|transactionAmount }} - {{ formatAmountByCurrency(transaction.currency, transaction.after) }} + {{ formatAmountByCurrency(transaction.transactionCurrency, transaction.after) }} {{ transaction.date.formatLocalized(monthAndDayFormat) }} diff --git a/resources/views/rules/partials/trigger.twig b/resources/views/rules/partials/trigger.twig index b90bab7e2e..e8f9279426 100644 --- a/resources/views/rules/partials/trigger.twig +++ b/resources/views/rules/partials/trigger.twig @@ -18,7 +18,7 @@ {% endfor %} - + diff --git a/resources/views/transactions/mass/edit.twig b/resources/views/transactions/mass/edit.twig index fa863e3847..ba64145b24 100644 --- a/resources/views/transactions/mass/edit.twig +++ b/resources/views/transactions/mass/edit.twig @@ -67,7 +67,7 @@ - + {# SOURCE ACCOUNT ID FOR TRANSFER OR WITHDRAWAL #} {% if transaction.type == 'Transfer' or transaction.type == 'Withdrawal' %} @@ -100,7 +100,7 @@ {% endif %} {# category #} - + diff --git a/routes/web.php b/routes/web.php index 84dd57281a..3232892b16 100755 --- a/routes/web.php +++ b/routes/web.php @@ -117,12 +117,14 @@ Route::group( // reconcile routes: Route::get('reconcile/{account}/index/{start_date?}/{end_date?}', ['uses' => 'Account\ReconcileController@reconcile', 'as' => 'reconcile']); - Route::get( - 'reconcile/{account}/transactions/{start_date?}/{end_date?}', ['uses' => 'Account\ReconcileController@transactions', 'as' => 'reconcile.transactions'] - ); - Route::get('reconcile/{account}/overview/{start_date?}/{end_date?}', ['uses' => 'Account\ReconcileController@overview', 'as' => 'reconcile.overview']); + + Route::post('reconcile/{account}/submit/{start_date?}/{end_date?}', ['uses' => 'Account\ReconcileController@submit', 'as' => 'reconcile.submit']); + // reconcile JSON routes + Route::get('reconcile/{account}/overview/{start_date?}/{end_date?}', ['uses' => 'Json\ReconcileController@overview', 'as' => 'reconcile.overview']); + Route::get('reconcile/{account}/transactions/{start_date?}/{end_date?}', ['uses' => 'Json\ReconcileController@transactions', 'as' => 'reconcile.transactions']); + // show reconciliation Route::get('reconcile/show/{tj}', ['uses' => 'Account\ReconcileController@show', 'as' => 'reconcile.show']); Route::get('reconcile/edit/{tj}', ['uses' => 'Account\ReconcileController@edit', 'as' => 'reconcile.edit']); diff --git a/tests/Api/V1/Controllers/BudgetLimitControllerTest.php b/tests/Api/V1/Controllers/BudgetLimitControllerTest.php index 47a222a80f..a7c283ef4e 100644 --- a/tests/Api/V1/Controllers/BudgetLimitControllerTest.php +++ b/tests/Api/V1/Controllers/BudgetLimitControllerTest.php @@ -116,15 +116,16 @@ class BudgetLimitControllerTest extends TestCase // mock calls: $repository->shouldReceive('setUser')->once(); - $repository->shouldReceive('findNull')->andReturn($budget); + $repository->shouldReceive('findNull')->andReturn(null); $repository->shouldReceive('getAllBudgetLimits')->once()->andReturn($budget->budgetlimits()->get()); // call API $params = [ - 'start_date' => '2018-01-01', - 'end_date' => '2018-01-31', + 'start' => '2018-01-01', + 'end' => '2018-01-31', ]; - $response = $this->get('/api/v1/budget_limits?' . http_build_query($params)); + $uri = '/api/v1/budget_limits?' . http_build_query($params); + $response = $this->get($uri); $response->assertStatus(200); $response->assertHeader('Content-Type', 'application/vnd.api+json'); } @@ -149,8 +150,8 @@ class BudgetLimitControllerTest extends TestCase // call API $params = [ 'budget_id' => $budget->id, - 'start_date' => '2018-01-01', - 'end_date' => '2018-01-31', + 'start' => '2018-01-01', + 'end' => '2018-01-31', ]; $response = $this->get('/api/v1/budget_limits?' . http_build_query($params)); $response->assertStatus(200); diff --git a/tests/Api/V1/Controllers/CurrencyControllerTest.php b/tests/Api/V1/Controllers/CurrencyControllerTest.php index c90dada382..b9f0f64fb6 100644 --- a/tests/Api/V1/Controllers/CurrencyControllerTest.php +++ b/tests/Api/V1/Controllers/CurrencyControllerTest.php @@ -163,7 +163,7 @@ class CurrencyControllerTest extends TestCase 'code' => 'ABC', 'symbol' => 'A', 'decimal_places' => 2, - 'default' => 'false', + 'default' => '0', ]; // test API @@ -200,7 +200,7 @@ class CurrencyControllerTest extends TestCase 'code' => 'ABC', 'symbol' => 'A', 'decimal_places' => 2, - 'default' => 'true', + 'default' => '1', ]; // test API @@ -232,7 +232,7 @@ class CurrencyControllerTest extends TestCase 'code' => 'ABC', 'symbol' => '$E', 'decimal_places' => '2', - 'default' => 'false', + 'default' => '0', ]; // test API @@ -270,7 +270,7 @@ class CurrencyControllerTest extends TestCase 'code' => 'ABC', 'symbol' => '$E', 'decimal_places' => '2', - 'default' => 'true', + 'default' => '1', ]; // test API diff --git a/tests/Api/V1/Controllers/CurrencyExchangeRateControllerTest.php b/tests/Api/V1/Controllers/CurrencyExchangeRateControllerTest.php index 4a0c1c8e04..c6c718b230 100644 --- a/tests/Api/V1/Controllers/CurrencyExchangeRateControllerTest.php +++ b/tests/Api/V1/Controllers/CurrencyExchangeRateControllerTest.php @@ -85,8 +85,13 @@ class CurrencyExchangeRateControllerTest extends TestCase $response->assertStatus(200); $response->assertJson( ['data' => [ - 'rate' => 0.5, - 'links' => [ + 'type' => 'currency_exchange_rates', + 'id' => '0', + 'attributes' => [ + 'rate' => 0.5, + ], + 'links' => [ + [ 'rel' => 'self', 'uri' => '/currency_exchange_rates/', diff --git a/tests/Api/V1/Controllers/TransactionControllerTest.php b/tests/Api/V1/Controllers/TransactionControllerTest.php index e3176207df..2a06e0f402 100644 --- a/tests/Api/V1/Controllers/TransactionControllerTest.php +++ b/tests/Api/V1/Controllers/TransactionControllerTest.php @@ -1257,7 +1257,7 @@ class TransactionControllerTest extends TestCase /** * Show index with range. - * + * * @covers \FireflyIII\Api\V1\Controllers\TransactionController */ public function testIndexWithRange(): void @@ -1274,7 +1274,7 @@ class TransactionControllerTest extends TestCase $collector->setAllAssetAccounts(); $collector->setLimit(5)->setPage(1); try { - $paginator = $collector->getPaginatedJournals(); + $paginator = $collector->getPaginatedJournals(); } catch (FireflyException $e) { $this->assertTrue(false, $e->getMessage()); } @@ -1324,17 +1324,18 @@ class TransactionControllerTest extends TestCase /** * Show a deposit. - * + * * @covers \FireflyIII\Api\V1\Controllers\TransactionController */ public function testShowDeposit(): void { + $loop = 0; do { - // this is kind of cheating but OK. /** @var TransactionJournal $journal */ $journal = $this->user()->transactionJournals()->inRandomOrder()->where('transaction_type_id', 2)->whereNull('deleted_at')->first(); $count = $journal->transactions()->count(); - } while ($count !== 2); + $loop++; + } while ($count !== 2 && $loop < 30); $transaction = $journal->transactions()->first(); @@ -1387,19 +1388,21 @@ class TransactionControllerTest extends TestCase /** * Show a withdrawal. - * + * * @covers \FireflyIII\Api\V1\Controllers\TransactionController */ public function testShowWithdrawal(): void { + $loop = 0; do { // this is kind of cheating but OK. /** @var TransactionJournal $journal */ $journal = $this->user()->transactionJournals()->inRandomOrder()->where('transaction_type_id', 1)->whereNull('deleted_at')->first(); $count = $journal->transactions()->count(); - } while ($count !== 2); + $loop++; + } while ($count !== 2 && $loop < 30); /** @var Transaction $transaction */ - $transaction = $journal->transactions()->first(); + $transaction = $journal->transactions()->first(); $transaction->description = null; $transaction->save(); diff --git a/tests/Api/V1/Controllers/UserControllerTest.php b/tests/Api/V1/Controllers/UserControllerTest.php index 83c48bae60..457b1e0e4c 100644 --- a/tests/Api/V1/Controllers/UserControllerTest.php +++ b/tests/Api/V1/Controllers/UserControllerTest.php @@ -28,6 +28,7 @@ use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Laravel\Passport\Passport; use Log; +use Mockery; use Tests\TestCase; /** @@ -94,6 +95,7 @@ class UserControllerTest extends TestCase $users = factory(User::class, 10)->create(); // mock stuff: $repository = $this->mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->once()->andReturn(true); // mock calls: $repository->shouldReceive('all')->withAnyArgs()->andReturn($users)->once(); @@ -116,7 +118,9 @@ class UserControllerTest extends TestCase */ public function testShow(): void { - $user = User::first(); + $user = User::first(); + $repository = $this->mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->once()->andReturn(true); // test API $response = $this->get('/api/v1/users/' . $user->id); @@ -139,6 +143,7 @@ class UserControllerTest extends TestCase // mock $userRepos = $this->mock(UserRepositoryInterface::class); + $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->twice()->andReturn(true); $userRepos->shouldReceive('store')->once()->andReturn($this->user()); // test API @@ -162,7 +167,7 @@ class UserControllerTest extends TestCase // mock $userRepos = $this->mock(UserRepositoryInterface::class); - + $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->twice()->andReturn(true); // test API $response = $this->post('/api/v1/users', $data, ['Accept' => 'application/json']); $response->assertStatus(422); @@ -198,6 +203,7 @@ class UserControllerTest extends TestCase // mock $userRepos = $this->mock(UserRepositoryInterface::class); $userRepos->shouldReceive('update')->once()->andReturn($user); + $userRepos->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->twice()->andReturn(true); // call API $response = $this->put('/api/v1/users/' . $user->id, $data); diff --git a/tests/Feature/Controllers/Account/ReconcileControllerTest.php b/tests/Feature/Controllers/Account/ReconcileControllerTest.php index a3a33e47ab..e4476b9754 100644 --- a/tests/Feature/Controllers/Account/ReconcileControllerTest.php +++ b/tests/Feature/Controllers/Account/ReconcileControllerTest.php @@ -87,48 +87,6 @@ class ReconcileControllerTest extends TestCase $response->assertRedirect(route('transactions.edit', [$journal->id])); } - /** - * Test overview of reconciliation. - * - * @covers \FireflyIII\Http\Controllers\Account\ReconcileController - */ - public function testOverview(): void - { - $transactions = $this->user()->transactions()->inRandomOrder()->take(3)->get(); - $repository = $this->mock(JournalRepositoryInterface::class); - $repository->shouldReceive('firstNull')->andReturn(new TransactionJournal); - $repository->shouldReceive('getTransactionsById')->andReturn($transactions)->twice(); - - $parameters = [ - 'startBalance' => '0', - 'endBalance' => '10', - 'transactions' => [1, 2, 3], - 'cleared' => [4, 5, 6], - ]; - $this->be($this->user()); - $response = $this->get(route('accounts.reconcile.overview', [1, '20170101', '20170131']) . '?' . http_build_query($parameters)); - $response->assertStatus(200); - } - - /** - * Test overview when it's not an asset. - * - * @covers \FireflyIII\Http\Controllers\Account\ReconcileController - * @expectedExceptionMessage is not an asset account - */ - public function testOverviewNotAsset(): void - { - $account = $this->user()->accounts()->where('account_type_id', '!=', 3)->first(); - $parameters = [ - 'startBalance' => '0', - 'endBalance' => '10', - 'transactions' => [1, 2, 3], - 'cleared' => [4, 5, 6], - ]; - $this->be($this->user()); - $response = $this->get(route('accounts.reconcile.overview', [$account->id, '20170101', '20170131']) . '?' . http_build_query($parameters)); - $response->assertStatus(500); - } /** * Test showing the reconciliation. @@ -275,33 +233,6 @@ class ReconcileControllerTest extends TestCase $response->assertSessionHas('success'); } - /** - * List transactions for reconciliation view. - * - * @covers \FireflyIII\Http\Controllers\Account\ReconcileController - */ - public function testTransactions(): void - { - $repository = $this->mock(CurrencyRepositoryInterface::class); - $repository->shouldReceive('findNull')->once()->andReturn(TransactionCurrency::find(1)); - - $this->be($this->user()); - $response = $this->get(route('accounts.reconcile.transactions', [1, '20170101', '20170131'])); - $response->assertStatus(200); - } - - /** - * @covers \FireflyIII\Http\Controllers\Account\ReconcileController - */ - public function testTransactionsInitialBalance(): void - { - $transaction = Transaction::leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') - ->where('accounts.user_id', $this->user()->id)->where('accounts.account_type_id', 6)->first(['account_id']); - $this->be($this->user()); - $response = $this->get(route('accounts.reconcile.transactions', [$transaction->account_id, '20170101', '20170131'])); - $response->assertStatus(302); - } - /** * @covers \FireflyIII\Http\Controllers\Account\ReconcileController * @covers \FireflyIII\Http\Requests\ReconciliationUpdateRequest diff --git a/tests/Feature/Controllers/Admin/UpdateControllerTest.php b/tests/Feature/Controllers/Admin/UpdateControllerTest.php index 4b17eaf5cd..0d9212bb35 100644 --- a/tests/Feature/Controllers/Admin/UpdateControllerTest.php +++ b/tests/Feature/Controllers/Admin/UpdateControllerTest.php @@ -151,11 +151,10 @@ class UpdateControllerTest extends TestCase $falseConfig = new Configuration; $falseConfig->data = false; FireflyConfig::shouldReceive('get')->withArgs(['is_demo_site', false])->once()->andReturn($falseConfig); + FireflyConfig::shouldReceive('set')->withArgs(['last_update_check', Mockery::any()])->once()->andReturn(new Configuration); $version = config('firefly.version') . '-alpha'; - $releases = [ - new Release(['id' => 'x', 'title' => $version, 'content' => '', 'updated' => new Carbon]), - ]; + $releases = []; $updater = $this->mock(UpdateRequest::class); $updater->shouldReceive('call')->andThrow(FireflyException::class, 'Something broke.'); $updater->shouldReceive('getReleases')->andReturn($releases); diff --git a/tests/Feature/Controllers/Admin/UserControllerTest.php b/tests/Feature/Controllers/Admin/UserControllerTest.php index 9b034f16d8..e5a7c24048 100644 --- a/tests/Feature/Controllers/Admin/UserControllerTest.php +++ b/tests/Feature/Controllers/Admin/UserControllerTest.php @@ -25,6 +25,7 @@ namespace Tests\Feature\Controllers\Admin; use FireflyIII\Repositories\User\UserRepositoryInterface; use Illuminate\Support\Collection; use Log; +use Mockery; use Tests\TestCase; /** @@ -35,7 +36,7 @@ class UserControllerTest extends TestCase /** * */ - public function setUp() + public function setUp(): void { parent::setUp(); Log::debug(sprintf('Now in %s.', \get_class($this))); @@ -46,6 +47,9 @@ class UserControllerTest extends TestCase */ public function testDelete(): void { + $repository = $this->mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->once()->andReturn(true); $this->be($this->user()); $response = $this->get(route('admin.users.delete', [1])); $response->assertStatus(200); @@ -60,6 +64,9 @@ class UserControllerTest extends TestCase { $repository = $this->mock(UserRepositoryInterface::class); $repository->shouldReceive('destroy')->once(); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->once()->andReturn(true); + $this->be($this->user()); $response = $this->post(route('admin.users.destroy', ['2'])); $response->assertStatus(302); @@ -71,6 +78,9 @@ class UserControllerTest extends TestCase */ public function testEdit(): void { + $repository = $this->mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->once()->andReturn(true); $this->be($this->user()); $response = $this->get(route('admin.users.edit', [1])); $response->assertStatus(200); @@ -84,6 +94,8 @@ class UserControllerTest extends TestCase public function testIndex(): void { $repository = $this->mock(UserRepositoryInterface::class); + //$repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->times(2)->andReturn(true); $user = $this->user(); $repository->shouldReceive('all')->andReturn(new Collection([$user])); @@ -100,6 +112,7 @@ class UserControllerTest extends TestCase public function testShow(): void { $repository = $this->mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->once()->andReturn(true); $repository->shouldReceive('getUserData')->andReturn( [ 'export_jobs_success' => 0, @@ -124,6 +137,8 @@ class UserControllerTest extends TestCase $repository->shouldReceive('changePassword')->once(); $repository->shouldReceive('changeStatus')->once(); $repository->shouldReceive('updateEmail')->once(); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'owner'])->once()->andReturn(true); $data = [ 'id' => 1, 'email' => 'test@example.com', diff --git a/tests/Feature/Controllers/BillControllerTest.php b/tests/Feature/Controllers/BillControllerTest.php index 5892a60dfc..67a2468328 100644 --- a/tests/Feature/Controllers/BillControllerTest.php +++ b/tests/Feature/Controllers/BillControllerTest.php @@ -243,19 +243,21 @@ class BillControllerTest extends TestCase } /** - * @covers \FireflyIII\Http\Controllers\BillController::store + * @covers \FireflyIII\Http\Controllers\BillController * @covers \FireflyIII\Http\Requests\BillFormRequest * @covers \FireflyIII\Http\Requests\Request */ public function testStore(): void { + $this->be($this->user()); + $bill = $this->user()->bills()->first(); // mock stuff $attachHelper = $this->mock(AttachmentHelperInterface::class); $journalRepos = $this->mock(JournalRepositoryInterface::class); $repository = $this->mock(BillRepositoryInterface::class); $ruleGroupRepos =$this->mock(RuleGroupRepositoryInterface::class); $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); - $repository->shouldReceive('store')->andReturn(new Bill); + $repository->shouldReceive('store')->andReturn($bill); $attachHelper->shouldReceive('saveAttachmentsForModel'); $attachHelper->shouldReceive('getMessages')->andReturn(new MessageBag); $ruleGroupRepos->shouldReceive('count')->andReturn(1); @@ -271,7 +273,7 @@ class BillControllerTest extends TestCase 'repeat_freq' => 'monthly', ]; $this->session(['bills.create.uri' => 'http://localhost']); - $this->be($this->user()); + $response = $this->post(route('bills.store'), $data); $response->assertStatus(302); $response->assertSessionHas('success'); @@ -289,8 +291,9 @@ class BillControllerTest extends TestCase $journalRepos = $this->mock(JournalRepositoryInterface::class); $repository = $this->mock(BillRepositoryInterface::class); $ruleGroupRepos =$this->mock(RuleGroupRepositoryInterface::class); + $bill = $this->user()->bills()->first(); $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); - $repository->shouldReceive('store')->andReturn(new Bill); + $repository->shouldReceive('store')->andReturn($bill); $attachHelper->shouldReceive('saveAttachmentsForModel'); $attachHelper->shouldReceive('getMessages')->andReturn(new MessageBag); $ruleGroupRepos->shouldReceive('count')->andReturn(1); diff --git a/tests/Feature/Controllers/CategoryControllerTest.php b/tests/Feature/Controllers/CategoryControllerTest.php index cbd8229807..3f6122bd90 100644 --- a/tests/Feature/Controllers/CategoryControllerTest.php +++ b/tests/Feature/Controllers/CategoryControllerTest.php @@ -60,6 +60,7 @@ class CategoryControllerTest extends TestCase */ public function testCreate(): void { + Log::debug('TestCreate()'); // mock stuff $categoryRepos = $this->mock(CategoryRepositoryInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); @@ -78,6 +79,7 @@ class CategoryControllerTest extends TestCase */ public function testDelete(): void { + Log::debug('Test Delete()'); // mock stuff $categoryRepos = $this->mock(CategoryRepositoryInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); @@ -96,6 +98,7 @@ class CategoryControllerTest extends TestCase */ public function testDestroy(): void { + Log::debug('Test destroy()'); // mock stuff $categoryRepos = $this->mock(CategoryRepositoryInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); @@ -116,6 +119,7 @@ class CategoryControllerTest extends TestCase */ public function testEdit(): void { + Log::debug('Test edit()'); // mock stuff $categoryRepos = $this->mock(CategoryRepositoryInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); @@ -135,6 +139,7 @@ class CategoryControllerTest extends TestCase */ public function testIndex(): void { + Log::debug('Test index()'); // mock stuff $category = factory(Category::class)->make(); $categoryRepos = $this->mock(CategoryRepositoryInterface::class); @@ -160,12 +165,17 @@ class CategoryControllerTest extends TestCase */ public function testNoCategory(string $range): void { + Log::debug(sprintf('Test noCategory(%s)', $range)); // mock stuff $collector = $this->mock(JournalCollectorInterface::class); $categoryRepos = $this->mock(CategoryRepositoryInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); $journalRepos = $this->mock(JournalRepositoryInterface::class); - $journalRepos->shouldReceive('firstNull')->twice()->andReturn(TransactionJournal::first()); + + + // get the journal with the most recent date for firstNull: + $journal = $this->user()->transactionJournals()->orderBy('date','DESC')->first(); + $journalRepos->shouldReceive('firstNull')->twice()->andReturn($journal); $collector->shouldReceive('setAllAssetAccounts')->andReturnSelf(); $collector->shouldReceive('setTypes')->andReturnSelf(); @@ -197,6 +207,7 @@ class CategoryControllerTest extends TestCase */ public function testNoCategoryAll(string $range): void { + Log::debug('Test nocategoryAll()'); // mock stuff $collector = $this->mock(JournalCollectorInterface::class); $categoryRepos = $this->mock(CategoryRepositoryInterface::class); @@ -233,6 +244,7 @@ class CategoryControllerTest extends TestCase */ public function testNoCategoryDate(string $range): void { + Log::debug('Test nocategorydate()'); // mock stuff $collector = $this->mock(JournalCollectorInterface::class); $categoryRepos = $this->mock(CategoryRepositoryInterface::class); @@ -277,6 +289,7 @@ class CategoryControllerTest extends TestCase */ public function testShow(string $range): void { + Log::debug('Test show()'); $transaction = factory(Transaction::class)->make(); $categoryRepos = $this->mock(CategoryRepositoryInterface::class); $accountRepos = $this->mock(AccountRepositoryInterface::class); @@ -326,6 +339,7 @@ class CategoryControllerTest extends TestCase */ public function testShowAll(string $range): void { + Log::debug('Test showAll()'); // mock stuff $transaction = factory(Transaction::class)->make(); $journalRepos = $this->mock(JournalRepositoryInterface::class); @@ -364,6 +378,7 @@ class CategoryControllerTest extends TestCase */ public function testShowByDate(string $range): void { + Log::debug('Test showbydate()'); // mock stuff $transaction = factory(Transaction::class)->make(); $repository = $this->mock(CategoryRepositoryInterface::class); @@ -412,6 +427,7 @@ class CategoryControllerTest extends TestCase */ public function testShowEmpty(string $range): void { + Log::debug('Test showempty()'); $journalRepos = $this->mock(JournalRepositoryInterface::class); $journalRepos->shouldReceive('firstNull')->twice()->andReturn(TransactionJournal::first()); @@ -451,6 +467,7 @@ class CategoryControllerTest extends TestCase */ public function testStore(): void { + Log::debug('Test store()'); $accountRepos = $this->mock(AccountRepositoryInterface::class); $repository = $this->mock(CategoryRepositoryInterface::class); $journalRepos = $this->mock(JournalRepositoryInterface::class); @@ -475,6 +492,7 @@ class CategoryControllerTest extends TestCase */ public function testUpdate(): void { + Log::debug('Test update()'); $category = Category::first(); $repository = $this->mock(CategoryRepositoryInterface::class); $journalRepos = $this->mock(JournalRepositoryInterface::class); diff --git a/tests/Feature/Controllers/Import/IndexControllerTest.php b/tests/Feature/Controllers/Import/IndexControllerTest.php index 10b8e6a942..e14c97e910 100644 --- a/tests/Feature/Controllers/Import/IndexControllerTest.php +++ b/tests/Feature/Controllers/Import/IndexControllerTest.php @@ -103,6 +103,7 @@ class IndexControllerTest extends TestCase $importJob = new ImportJob; $importJob->provider = 'fake'; $importJob->key = 'fake_job_1'; + $importJob->user_id = 1; // mock calls $userRepository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->andReturn(true)->once(); @@ -135,6 +136,7 @@ class IndexControllerTest extends TestCase $importJob = new ImportJob; $importJob->provider = 'fake'; $importJob->key = 'fake_job_2'; + $importJob->user_id = 1; // mock call: $userRepository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->andReturn(true)->once(); @@ -168,6 +170,7 @@ class IndexControllerTest extends TestCase $importJob = new ImportJob; $importJob->provider = 'file'; $importJob->key = 'file_job_1'; + $importJob->user_id =1; // mock calls $fakePrerequisites->shouldReceive('setUser')->once(); diff --git a/tests/Feature/Controllers/Json/ReconcileControllerTest.php b/tests/Feature/Controllers/Json/ReconcileControllerTest.php new file mode 100644 index 0000000000..25dd06716b --- /dev/null +++ b/tests/Feature/Controllers/Json/ReconcileControllerTest.php @@ -0,0 +1,122 @@ +. + */ + +declare(strict_types=1); + +namespace Tests\Feature\Controllers\Json; + + +use FireflyIII\Models\Transaction; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\Journal\JournalRepositoryInterface; +use Log; +use Tests\TestCase; + +/** + * + * Class ReconcileControllerTest + */ +class ReconcileControllerTest extends TestCase +{ + /** + * + */ + public function setUp() + { + parent::setUp(); + Log::debug(sprintf('Now in %s.', \get_class($this))); + } + + /** + * Test overview of reconciliation. + * + * @covers \FireflyIII\Http\Controllers\Json\ReconcileController + */ + public function testOverview(): void + { + $transactions = $this->user()->transactions()->inRandomOrder()->take(3)->get(); + $repository = $this->mock(JournalRepositoryInterface::class); + $repository->shouldReceive('firstNull')->andReturn(new TransactionJournal); + $repository->shouldReceive('getTransactionsById')->andReturn($transactions)->twice(); + + $parameters = [ + 'startBalance' => '0', + 'endBalance' => '10', + 'transactions' => [1, 2, 3], + 'cleared' => [4, 5, 6], + ]; + $this->be($this->user()); + $response = $this->get(route('accounts.reconcile.overview', [1, '20170101', '20170131']) . '?' . http_build_query($parameters)); + $response->assertStatus(200); + } + + /** + * Test overview when it's not an asset. + * + * @covers \FireflyIII\Http\Controllers\Json\ReconcileController + * @expectedExceptionMessage is not an asset account + */ + public function testOverviewNotAsset(): void + { + $account = $this->user()->accounts()->where('account_type_id', '!=', 3)->first(); + $parameters = [ + 'startBalance' => '0', + 'endBalance' => '10', + 'transactions' => [1, 2, 3], + 'cleared' => [4, 5, 6], + ]; + $this->be($this->user()); + $response = $this->get(route('accounts.reconcile.overview', [$account->id, '20170101', '20170131']) . '?' . http_build_query($parameters)); + $response->assertStatus(500); + } + + + /** + * List transactions for reconciliation view. + * + * @covers \FireflyIII\Http\Controllers\Json\ReconcileController + */ + public function testTransactions(): void + { + $repository = $this->mock(CurrencyRepositoryInterface::class); + $repository->shouldReceive('findNull')->once()->andReturn(TransactionCurrency::find(1)); + + $this->be($this->user()); + $response = $this->get(route('accounts.reconcile.transactions', [1, '20170101', '20170131'])); + $response->assertStatus(200); + } + + /** + * @covers \FireflyIII\Http\Controllers\Json\ReconcileController + */ + public function testTransactionsInitialBalance(): void + { + $transaction = Transaction::leftJoin('accounts', 'accounts.id', '=', 'transactions.account_id') + ->where('accounts.user_id', $this->user()->id)->where('accounts.account_type_id', 6)->first(['account_id']); + $this->be($this->user()); + $response = $this->get(route('accounts.reconcile.transactions', [$transaction->account_id, '20170101', '20170131'])); + $response->assertStatus(302); + } + + +} \ No newline at end of file diff --git a/tests/Feature/Controllers/Popup/ReportControllerTest.php b/tests/Feature/Controllers/Popup/ReportControllerTest.php index ab2366932d..3915aae03f 100644 --- a/tests/Feature/Controllers/Popup/ReportControllerTest.php +++ b/tests/Feature/Controllers/Popup/ReportControllerTest.php @@ -114,10 +114,10 @@ class ReportControllerTest extends TestCase $popupHelper = $this->mock(PopupReportInterface::class); $account = factory(Account::class)->make(); - $popupHelper->shouldReceive('balanceForNoBudget')->once()->andReturn(new Collection); + $popupHelper->shouldReceive('balanceForNoBudget')->andReturn(new Collection); $budgetRepos->shouldReceive('findNull')->andReturn(new Budget)->once()->withArgs([0]); $accountRepos->shouldReceive('findNull')->andReturn($account)->once()->withArgs([1]); - + $popupHelper->shouldReceive('balanceForBudget')->once()->andReturn(new Collection); $this->be($this->user()); $arguments = [ diff --git a/tests/Feature/Controllers/ProfileControllerTest.php b/tests/Feature/Controllers/ProfileControllerTest.php index d1d433b4aa..6f157eb889 100644 --- a/tests/Feature/Controllers/ProfileControllerTest.php +++ b/tests/Feature/Controllers/ProfileControllerTest.php @@ -158,27 +158,13 @@ class ProfileControllerTest extends TestCase $response->assertRedirect(route('profile.index')); } - /** - * @covers \FireflyIII\Http\Controllers\ProfileController - */ - public function testEnable2FADemo(): void - { - $repository = $this->mock(UserRepositoryInterface::class); - $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(true); - - $this->be($this->user()); - $response = $this->post(route('profile.enable2FA')); - $response->assertStatus(302); - $response->assertRedirect(route('profile.index')); - } - /** * @covers \FireflyIII\Http\Controllers\ProfileController */ public function testEnable2FANoSecret(): void { $repository = $this->mock(UserRepositoryInterface::class); - $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->twice()->andReturn(false); // ask about language: $langPreference = new Preference; @@ -220,7 +206,7 @@ class ProfileControllerTest extends TestCase public function testEnable2FASecret(): void { $repository = $this->mock(UserRepositoryInterface::class); - $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->twice()->andReturn(false); // ask about language: $langPreference = new Preference; @@ -291,6 +277,7 @@ class ProfileControllerTest extends TestCase $repository = $this->mock(UserRepositoryInterface::class); $repository->shouldReceive('findByEmail')->once()->andReturn(null); $repository->shouldReceive('changeEmail')->once()->andReturn(true); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $this->be($this->user()); $response = $this->post(route('profile.change-email.post'), $data); @@ -310,6 +297,7 @@ class ProfileControllerTest extends TestCase ]; $repository = $this->mock(UserRepositoryInterface::class); $repository->shouldReceive('findByEmail')->once()->andReturn(new User); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $this->be($this->user()); $response = $this->post(route('profile.change-email.post'), $data); @@ -324,6 +312,7 @@ class ProfileControllerTest extends TestCase public function testPostChangeEmailSame(): void { $repository = $this->mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $data = [ 'email' => $this->user()->email, ]; @@ -345,6 +334,7 @@ class ProfileControllerTest extends TestCase $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); $repository = $this->mock(UserRepositoryInterface::class); $repository->shouldReceive('changePassword'); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $data = [ 'current_password' => 'james', @@ -368,6 +358,7 @@ class ProfileControllerTest extends TestCase $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); $repository = $this->mock(UserRepositoryInterface::class); $repository->shouldReceive('changePassword'); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $data = [ 'current_password' => 'james3', @@ -391,6 +382,7 @@ class ProfileControllerTest extends TestCase $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); $repository = $this->mock(UserRepositoryInterface::class); $repository->shouldReceive('changePassword'); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $data = [ 'current_password' => 'james', @@ -440,6 +432,7 @@ class ProfileControllerTest extends TestCase $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); $repository = $this->mock(UserRepositoryInterface::class); $repository->shouldReceive('destroy')->once(); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $data = [ 'password' => 'james', ]; @@ -458,6 +451,7 @@ class ProfileControllerTest extends TestCase $repository = $this->mock(UserRepositoryInterface::class); $journalRepos = $this->mock(JournalRepositoryInterface::class); $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $data = [ 'password' => 'james2', ]; @@ -473,6 +467,8 @@ class ProfileControllerTest extends TestCase */ public function testRegenerate(): void { + $repository = $this->mock(UserRepositoryInterface::class); + $repository->shouldReceive('hasRole')->withArgs([Mockery::any(), 'demo'])->once()->andReturn(false); $token = ''; $currentToken = Preference::where('user_id', $this->user()->id)->where('name', 'access_token')->first(); if (null !== $currentToken) { diff --git a/tests/Feature/Controllers/TagControllerTest.php b/tests/Feature/Controllers/TagControllerTest.php index 7152e7fd48..2454b4bae9 100644 --- a/tests/Feature/Controllers/TagControllerTest.php +++ b/tests/Feature/Controllers/TagControllerTest.php @@ -264,7 +264,7 @@ class TagControllerTest extends TestCase $repository = $this->mock(TagRepositoryInterface::class); $journalRepos = $this->mock(JournalRepositoryInterface::class); $journalRepos->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); - $repository->shouldReceive('find')->andReturn(new Tag); + $repository->shouldReceive('findNull')->andReturn(null); $repository->shouldReceive('store')->andReturn(new Tag); $this->session(['tags.create.uri' => 'http://localhost']); @@ -299,7 +299,7 @@ class TagControllerTest extends TestCase ]; $repository->shouldReceive('update'); - $repository->shouldReceive('find')->andReturn(Tag::first()); + $repository->shouldReceive('findNull')->andReturn(Tag::first()); $this->be($this->user()); $response = $this->post(route('tags.update', [1]), $data); diff --git a/tests/Feature/Controllers/Transaction/MassControllerTest.php b/tests/Feature/Controllers/Transaction/MassControllerTest.php index ce6d3b0f01..202be2a26e 100644 --- a/tests/Feature/Controllers/Transaction/MassControllerTest.php +++ b/tests/Feature/Controllers/Transaction/MassControllerTest.php @@ -188,7 +188,7 @@ class MassControllerTest extends TestCase $repository = $this->mock(JournalRepositoryInterface::class); $repository->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); $repository->shouldReceive('update')->once(); - $repository->shouldReceive('find')->once()->andReturn($deposit); + $repository->shouldReceive('findNull')->once()->andReturn($deposit); $repository->shouldReceive('getTransactionType')->andReturn('Deposit'); $repository->shouldReceive('getNoteText')->andReturn('Some note'); diff --git a/tests/Feature/Controllers/Transaction/SingleControllerTest.php b/tests/Feature/Controllers/Transaction/SingleControllerTest.php index 486c4e0492..836ae75cf3 100644 --- a/tests/Feature/Controllers/Transaction/SingleControllerTest.php +++ b/tests/Feature/Controllers/Transaction/SingleControllerTest.php @@ -84,6 +84,8 @@ class SingleControllerTest extends TestCase $journalRepos->shouldReceive('getJournalBudgetId')->andReturn(0); $journalRepos->shouldReceive('getJournalCategoryName')->andReturn(''); $journalRepos->shouldReceive('getTags')->andReturn([]); + $journalRepos->shouldReceive('getMetaField')->andReturnNull(); + $note = new Note(); $note->id = 5; diff --git a/tests/Feature/Controllers/TransactionControllerTest.php b/tests/Feature/Controllers/TransactionControllerTest.php index db10f10d27..a9dedac278 100644 --- a/tests/Feature/Controllers/TransactionControllerTest.php +++ b/tests/Feature/Controllers/TransactionControllerTest.php @@ -323,7 +323,7 @@ class TransactionControllerTest extends TestCase $journal->date = new Carbon('2016-01-01'); $repository = $this->mock(JournalRepositoryInterface::class); $repository->shouldReceive('firstNull')->once()->andReturn(new TransactionJournal); - $repository->shouldReceive('find')->once()->andReturn($journal); + $repository->shouldReceive('findNull')->once()->andReturn($journal); $repository->shouldReceive('setOrder')->once()->andReturn(true); $data = [ diff --git a/tests/Unit/Factory/AccountFactoryTest.php b/tests/Unit/Factory/AccountFactoryTest.php index 951ec2bb92..8c3f61e24d 100644 --- a/tests/Unit/Factory/AccountFactoryTest.php +++ b/tests/Unit/Factory/AccountFactoryTest.php @@ -341,7 +341,7 @@ class AccountFactoryTest extends TestCase $data = [ 'account_type_id' => null, 'accountType' => 'asset', - 'iban' => 'NL18RABO0326747238', + 'iban' => 'NL02ABNA0870809585', 'name' => 'Basic asset account #' . random_int(1, 1000), 'virtualBalance' => null, 'active' => true, @@ -356,7 +356,7 @@ class AccountFactoryTest extends TestCase // assert stuff about account: $this->assertEquals($account->name, $data['name']); $this->assertEquals(AccountType::ASSET, $account->accountType->type); - $this->assertEquals('NL18RABO0326747238', $account->iban); + $this->assertEquals('NL02ABNA0870809585', $account->iban); $this->assertTrue($account->active); $this->assertEquals('0', $account->virtual_balance); diff --git a/tests/Unit/Factory/TransactionFactoryTest.php b/tests/Unit/Factory/TransactionFactoryTest.php index f31966fa75..f34ad9524c 100644 --- a/tests/Unit/Factory/TransactionFactoryTest.php +++ b/tests/Unit/Factory/TransactionFactoryTest.php @@ -705,7 +705,8 @@ class TransactionFactoryTest extends TestCase { // objects: $asset = $this->user()->accounts()->where('account_type_id', 3)->first(); - $opposing = $this->user()->accounts()->where('id', '!=', $asset->id)->where('account_type_id', 3)->first(); + $reconAccount = $this->user()->accounts()->where('account_type_id', 10)->first(); + //$opposing = $this->user()->accounts()->where('id', '!=', $asset->id)->where('account_type_id', 3)->first(); $euro = TransactionCurrency::first(); $foreign = TransactionCurrency::where('id', '!=', $euro->id)->first(); @@ -721,7 +722,7 @@ class TransactionFactoryTest extends TestCase 'description' => null, 'source_id' => $asset->id, 'source_name' => null, - 'destination_id' => $opposing->id, + 'destination_id' => $reconAccount->id, 'destination_name' => null, 'amount' => '10', 'reconciled' => false, @@ -740,7 +741,7 @@ class TransactionFactoryTest extends TestCase $budgetFactory->shouldReceive('setUser'); $categoryFactory->shouldReceive('setUser'); // first search action is for the asset account, second is for expense account. - $accountRepos->shouldReceive('findNull')->andReturn($asset, $opposing); + $accountRepos->shouldReceive('findNull')->andReturn($asset, $reconAccount); // factories return various stuff: $budgetFactory->shouldReceive('find')->andReturn(null); diff --git a/tests/Unit/Handlers/Events/UserEventHandlerTest.php b/tests/Unit/Handlers/Events/UserEventHandlerTest.php index a74ac77800..d3cfe0a348 100644 --- a/tests/Unit/Handlers/Events/UserEventHandlerTest.php +++ b/tests/Unit/Handlers/Events/UserEventHandlerTest.php @@ -92,6 +92,8 @@ class UserEventHandlerTest extends TestCase $listener = new UserEventHandler(); // mock stuff + + $repository->shouldReceive('hasRole')->once()->andReturn(false); $repository->shouldReceive('count')->once()->andReturn(1); $repository->shouldReceive('getRole')->once()->andReturn(null); $repository->shouldReceive('attachRole')->once()->withArgs([Mockery::any(), 'owner']); @@ -112,6 +114,7 @@ class UserEventHandlerTest extends TestCase $listener = new UserEventHandler(); // mock stuff + $repository->shouldReceive('hasRole')->once()->andReturn(false); $repository->shouldReceive('count')->once()->andReturn(1); $repository->shouldReceive('getRole')->once()->andReturn(new Role); $repository->shouldReceive('attachRole')->once()->withArgs([Mockery::any(), 'owner']); @@ -131,6 +134,7 @@ class UserEventHandlerTest extends TestCase $listener = new UserEventHandler(); // mock stuff + $repository->shouldReceive('hasRole')->once()->andReturn(true); $repository->shouldReceive('count')->once()->andReturn(1); $listener->checkSingleUserIsAdmin($event); diff --git a/tests/Unit/Handlers/Events/VersionCheckEventHandlerTest.php b/tests/Unit/Handlers/Events/VersionCheckEventHandlerTest.php index 41416cfe7b..1f4399ba6f 100644 --- a/tests/Unit/Handlers/Events/VersionCheckEventHandlerTest.php +++ b/tests/Unit/Handlers/Events/VersionCheckEventHandlerTest.php @@ -59,10 +59,11 @@ class VersionCheckEventHandlerTest extends TestCase // report on config variables: FireflyConfig::shouldReceive('get')->withArgs(['permission_update_check', -1])->once()->andReturn($updateConfig); FireflyConfig::shouldReceive('get')->withArgs(['last_update_check', Mockery::any()])->once()->andReturn($checkConfig); + FireflyConfig::shouldReceive('set')->withArgs(['last_update_check', Mockery::any()])->once()->andReturn($checkConfig); // request thing: - $request->shouldReceive('call')->once(); - $request->shouldReceive('getReleases')->once()->andThrow(new FireflyException('Errrr')); + $request->shouldReceive('call')->once()->andThrow(new FireflyException('Errrr')); + $request->shouldReceive('getReleases')->once(); $handler = new VersionCheckEventHandler; @@ -140,6 +141,7 @@ class VersionCheckEventHandlerTest extends TestCase // report on config variables: FireflyConfig::shouldReceive('get')->withArgs(['permission_update_check', -1])->once()->andReturn($updateConfig); FireflyConfig::shouldReceive('get')->withArgs(['last_update_check', Mockery::any()])->once()->andReturn($checkConfig); + FireflyConfig::shouldReceive('set')->withArgs(['last_update_check', Mockery::any()])->once()->andReturn($checkConfig); $handler = new VersionCheckEventHandler; $handler->checkForUpdates($event); @@ -164,6 +166,7 @@ class VersionCheckEventHandlerTest extends TestCase // report on config variables: FireflyConfig::shouldReceive('get')->withArgs(['permission_update_check', -1])->once()->andReturn($updateConfig); FireflyConfig::shouldReceive('get')->withArgs(['last_update_check', Mockery::any()])->once()->andReturn($checkConfig); + FireflyConfig::shouldReceive('set')->withArgs(['last_update_check', Mockery::any()])->once()->andReturn($checkConfig); $handler = new VersionCheckEventHandler; $handler->checkForUpdates($event); diff --git a/tests/Unit/Middleware/SandstormTest.php b/tests/Unit/Middleware/SandstormTest.php index e7afb03da5..47ff386cd5 100644 --- a/tests/Unit/Middleware/SandstormTest.php +++ b/tests/Unit/Middleware/SandstormTest.php @@ -127,8 +127,8 @@ class SandstormTest extends TestCase $repository = $this->mock(UserRepositoryInterface::class); $repository->shouldReceive('count')->twice()->andReturn(0); $repository->shouldReceive('store')->once()->andReturn($this->user()); - $repository->shouldReceive('attachRole')->twice()->andReturn(true); - $repository->shouldReceive('getRole')->once()->andReturn(new Role); + $repository->shouldReceive('attachRole')->once()->andReturn(true); + //$repository->shouldReceive('getRole')->once()->andReturn(new Role); $repository->shouldReceive('hasRole')->andReturn(false); $response = $this->get('/_test/sandstorm', ['X-Sandstorm-User-Id' => 'abcd']); diff --git a/tests/Unit/TransactionRules/Triggers/FromAccountStartsTest.php b/tests/Unit/TransactionRules/Triggers/FromAccountStartsTest.php index e411beae7f..7d5185ddb4 100644 --- a/tests/Unit/TransactionRules/Triggers/FromAccountStartsTest.php +++ b/tests/Unit/TransactionRules/Triggers/FromAccountStartsTest.php @@ -24,6 +24,7 @@ namespace Tests\Unit\TransactionRules\Triggers; use FireflyIII\Models\TransactionJournal; use FireflyIII\TransactionRules\Triggers\FromAccountStarts; +use Log; use Tests\TestCase; /** @@ -31,17 +32,35 @@ use Tests\TestCase; */ class FromAccountStartsTest extends TestCase { + /** + * + */ + public function setUp() + { + parent::setUp(); + Log::debug(sprintf('Now in %s.', \get_class($this))); + } + /** * @covers \FireflyIII\TransactionRules\Triggers\FromAccountStarts::triggered */ public function testTriggered(): void { - $transaction = null; + Log::debug('In testTriggered()'); + $loops = 0; // FINAL LOOP METHOD. do { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + /** @var TransactionJournal $journal */ + $journal = $this->user()->transactionJournals()->inRandomOrder()->whereNull('deleted_at')->first(); $transaction = $journal->transactions()->where('amount', '<', 0)->first(); - } while (null === $transaction); - $account = $transaction->account; + $account = $transaction->account; + $count = $journal->transactions()->count(); + + Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d', $loops, $count, (int)null===$account)); + + $loops++; + + // do this until: account is not null, journal has two transactions, loops is below 30 + } while (!(null !== $account && 2 === $count && $loops < 30)); $trigger = FromAccountStarts::makeFromStrings(substr($account->name, 0, -3), false); $result = $trigger->triggered($journal); @@ -53,13 +72,21 @@ class FromAccountStartsTest extends TestCase */ public function testTriggeredLonger(): void { - $transaction = null; + Log::debug('In testTriggeredLonger()'); + $loops = 0; // FINAL LOOP METHOD. do { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + /** @var TransactionJournal $journal */ + $journal = $this->user()->transactionJournals()->inRandomOrder()->whereNull('deleted_at')->first(); $transaction = $journal->transactions()->where('amount', '<', 0)->first(); - } while (null === $transaction); + $account = $transaction->account; + $count = $journal->transactions()->count(); - $account = $transaction->account; + Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d', $loops, $count, (int)null===$account)); + + $loops++; + + // do this until: account is not null, journal has two transactions, loops is below 30 + } while (!(null !== $account && 2 === $count && $loops < 30)); $trigger = FromAccountStarts::makeFromStrings('bla-bla-bla' . $account->name, false); $result = $trigger->triggered($journal); diff --git a/tests/Unit/TransactionRules/Triggers/HasNoBudgetTest.php b/tests/Unit/TransactionRules/Triggers/HasNoBudgetTest.php index f1eb119f9e..7ede15cd6b 100644 --- a/tests/Unit/TransactionRules/Triggers/HasNoBudgetTest.php +++ b/tests/Unit/TransactionRules/Triggers/HasNoBudgetTest.php @@ -37,7 +37,7 @@ class HasNoBudgetTest extends TestCase */ public function testTriggeredBudget(): void { - $journal = TransactionJournal::inRandomOrder()->where('transaction_type_id', 1)->whereNull('deleted_at')->first(); + $journal = $this->user()->transactionJournals()->inRandomOrder()->where('transaction_type_id', 1)->whereNull('deleted_at')->first(); $budget = $journal->user->budgets()->first(); $journal->budgets()->detach(); $journal->budgets()->save($budget); @@ -54,7 +54,7 @@ class HasNoBudgetTest extends TestCase public function testTriggeredNoBudget(): void { /** @var TransactionJournal $journal */ - $journal = TransactionJournal::inRandomOrder()->where('transaction_type_id', 1)->whereNull('deleted_at')->first(); + $journal = $this->user()->transactionJournals()->inRandomOrder()->where('transaction_type_id', 1)->whereNull('deleted_at')->first(); $journal->budgets()->detach(); /** @var Transaction $transaction */ foreach ($journal->transactions as $transaction) { @@ -72,8 +72,12 @@ class HasNoBudgetTest extends TestCase */ public function testTriggeredTransaction(): void { - /** @var TransactionJournal $journal */ - $journal = TransactionJournal::inRandomOrder()->where('transaction_type_id', 1)->whereNull('deleted_at')->first(); + $loopCount = 0; + do { + $journal = $this->user()->transactionJournals()->inRandomOrder()->whereNull('deleted_at')->first(); + $count = $journal->transactions()->count(); + } while ($loopCount < 30 && $count !== 2); + $transactions = $journal->transactions()->get(); $budget = $journal->user->budgets()->first(); diff --git a/tests/Unit/TransactionRules/Triggers/ToAccountContainsTest.php b/tests/Unit/TransactionRules/Triggers/ToAccountContainsTest.php index 0163d93b72..cfff2cd793 100644 --- a/tests/Unit/TransactionRules/Triggers/ToAccountContainsTest.php +++ b/tests/Unit/TransactionRules/Triggers/ToAccountContainsTest.php @@ -36,11 +36,18 @@ class ToAccountContainsTest extends TestCase */ public function testTriggered(): void { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); - $transaction = $journal->transactions()->where('amount', '>', 0)->first(); - $account = $transaction->account; - $trigger = ToAccountContains::makeFromStrings($account->name, false); - $result = $trigger->triggered($journal); + $count = 0; + do { + $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + $transaction = $journal->transactions()->where('amount', '>', 0)->first(); + $transactionCount = $journal->transactions()->count(); + $account = null === $transaction ? null : $transaction->account; + $count++; + } while ($account === null && $count < 30 && $transactionCount !== 2); + + + $trigger = ToAccountContains::makeFromStrings($account->name, false); + $result = $trigger->triggered($journal); $this->assertTrue($result); } @@ -49,7 +56,16 @@ class ToAccountContainsTest extends TestCase */ public function testTriggeredNot(): void { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + $count = 0; + do { + $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); + $transaction = $journal->transactions()->where('amount', '>', 0)->first(); + $transactionCount = $journal->transactions()->count(); + $account = null === $transaction ? null : $transaction->account; + $count++; + } while ($account === null && $count < 30 && $transactionCount !== 2); + + $trigger = ToAccountContains::makeFromStrings('some name' . random_int(1, 234), false); $result = $trigger->triggered($journal); $this->assertFalse($result); diff --git a/tests/Unit/TransactionRules/Triggers/ToAccountIsTest.php b/tests/Unit/TransactionRules/Triggers/ToAccountIsTest.php index c06e0ccf1f..5f06021fd1 100644 --- a/tests/Unit/TransactionRules/Triggers/ToAccountIsTest.php +++ b/tests/Unit/TransactionRules/Triggers/ToAccountIsTest.php @@ -25,6 +25,7 @@ namespace Tests\Unit\TransactionRules\Triggers; use FireflyIII\Models\TransactionJournal; use FireflyIII\TransactionRules\Triggers\ToAccountIs; use Tests\TestCase; +use Log; /** * Class ToAccountIsTest @@ -36,15 +37,22 @@ class ToAccountIsTest extends TestCase */ public function testTriggered(): void { - $count = 0; - $transactionCount = 0; + $loops = 0; // FINAL LOOP METHOD. do { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); - $transaction = $journal->transactions()->where('amount', '>', 0)->first(); - $transactionCount = $journal->transactions()->count(); - $account = $transaction->account; - $count++; - } while ($account === null && $count < 30 && $transactionCount !== 2); + /** @var TransactionJournal $journal */ + $journal = $this->user()->transactionJournals()->inRandomOrder()->whereNull('deleted_at')->first(); + $transaction = $journal->transactions()->where('amount', '>', 0)->first(); + $account = $transaction->account; + $count = $journal->transactions()->count(); + + Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d', $loops, $count, (int)null===$account)); + + $loops++; + + // do this until: account is not null, journal has two transactions, loops is below 30 + } while (!(null !== $account && 2 === $count && $loops < 30)); + + $trigger = ToAccountIs::makeFromStrings($account->name, false); $result = $trigger->triggered($journal); @@ -56,15 +64,20 @@ class ToAccountIsTest extends TestCase */ public function testTriggeredNot(): void { - $count = 0; - $transactionCount = 0; + $loops = 0; // FINAL LOOP METHOD. do { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); - $transaction = $journal->transactions()->where('amount', '>', 0)->first(); - $transactionCount = $journal->transactions()->count(); - $account = $transaction->account; - $count++; - } while ($account === null && $count < 30 && $transactionCount !== 2); + /** @var TransactionJournal $journal */ + $journal = $this->user()->transactionJournals()->inRandomOrder()->whereNull('deleted_at')->first(); + $transaction = $journal->transactions()->where('amount', '>', 0)->first(); + $account = $transaction->account; + $count = $journal->transactions()->count(); + + Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d', $loops, $count, (int)null===$account)); + + $loops++; + + // do this until: account is not null, journal has two transactions, loops is below 30 + } while (!(null !== $account && 2 === $count && $loops < 30)); $trigger = ToAccountIs::makeFromStrings('some name' . random_int(1, 234), false); $result = $trigger->triggered($journal); diff --git a/tests/Unit/TransactionRules/Triggers/ToAccountStartsTest.php b/tests/Unit/TransactionRules/Triggers/ToAccountStartsTest.php index fc24e98010..78c0ef1efe 100644 --- a/tests/Unit/TransactionRules/Triggers/ToAccountStartsTest.php +++ b/tests/Unit/TransactionRules/Triggers/ToAccountStartsTest.php @@ -24,6 +24,7 @@ namespace Tests\Unit\TransactionRules\Triggers; use FireflyIII\Models\TransactionJournal; use FireflyIII\TransactionRules\Triggers\ToAccountStarts; +use Log; use Tests\TestCase; /** @@ -36,14 +37,22 @@ class ToAccountStartsTest extends TestCase */ public function testTriggered(): void { - $count = 0; - $account = null; - while ($count !== 0 && $account !== null) { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); - $count = $journal->transactions()->where('amount', '>', 0)->count(); + Log::debug('Now in testTriggered'); + + $loops = 0; // FINAL LOOP METHOD. + do { + /** @var TransactionJournal $journal */ + $journal = $this->user()->transactionJournals()->inRandomOrder()->whereNull('deleted_at')->first(); $transaction = $journal->transactions()->where('amount', '>', 0)->first(); $account = $transaction->account; - } + $count = $journal->transactions()->count(); + + Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d', $loops, $count, (int)null===$account)); + + $loops++; + + // do this until: account is not null, journal has two transactions, loops is below 30 + } while (!(null !== $account && 2 === $count && $loops < 30)); $trigger = ToAccountStarts::makeFromStrings(substr($account->name, 0, -3), false); @@ -56,14 +65,23 @@ class ToAccountStartsTest extends TestCase */ public function testTriggeredLonger(): void { - $count = 0; - $account = null; - while ($count !== 0 && $account !== null) { - $journal = TransactionJournal::inRandomOrder()->whereNull('deleted_at')->first(); - $count = $journal->transactions()->where('amount', '>', 0)->count(); + Log::debug('Now in testTriggeredLonger'); + + + $loops = 0; // FINAL LOOP METHOD. + do { + /** @var TransactionJournal $journal */ + $journal = $this->user()->transactionJournals()->inRandomOrder()->whereNull('deleted_at')->first(); $transaction = $journal->transactions()->where('amount', '>', 0)->first(); $account = $transaction->account; - } + $count = $journal->transactions()->count(); + + Log::debug(sprintf('Loop: %d, transaction count: %d, account is null: %d', $loops, $count, (int)null===$account)); + + $loops++; + + // do this until: account is not null, journal has two transactions, loops is below 30 + } while (!(null !== $account && 2 === $count && $loops < 30)); $trigger = ToAccountStarts::makeFromStrings('bla-bla-bla' . $account->name, false); $result = $trigger->triggered($journal);