diff --git a/.ci/php-cs-fixer/.gitignore b/.ci/php-cs-fixer/.gitignore new file mode 100644 index 0000000000..22d0d82f80 --- /dev/null +++ b/.ci/php-cs-fixer/.gitignore @@ -0,0 +1 @@ +vendor diff --git a/.ci/php-cs-fixer/.php-cs-fixer.php b/.ci/php-cs-fixer/.php-cs-fixer.php new file mode 100644 index 0000000000..b20dd1d8d0 --- /dev/null +++ b/.ci/php-cs-fixer/.php-cs-fixer.php @@ -0,0 +1,44 @@ +. + */ + +$current = __DIR__; + +$paths = [ + $current . '/../../app', + $current . '/../../config', + $current . '/../../database', + $current . '/../../routes', + $current . '/../../tests', + $current . '/../../resources/lang', +]; + +$finder = PhpCsFixer\Finder::create() + ->in($paths); + + +$config = new PhpCsFixer\Config(); +return $config->setRules([ + '@PSR12' => true, + 'strict_param' => true, + 'array_syntax' => ['syntax' => 'short'], +]) + ->setFinder($finder) + ; diff --git a/.ci/php-cs-fixer/composer.json b/.ci/php-cs-fixer/composer.json new file mode 100644 index 0000000000..9795354e5e --- /dev/null +++ b/.ci/php-cs-fixer/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "friendsofphp/php-cs-fixer": "^3.12" + } +} diff --git a/.ci/php-cs-fixer/composer.lock b/.ci/php-cs-fixer/composer.lock new file mode 100644 index 0000000000..39ab1c8877 --- /dev/null +++ b/.ci/php-cs-fixer/composer.lock @@ -0,0 +1,2096 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "f1e0b38af4ded66da271a99d2bff5be8", + "packages": [ + { + "name": "composer/pcre", + "version": "3.1.0", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2", + "shasum": "" + }, + "require": { + "php": "^7.4 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.3", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/3.1.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-11-17T09:50:14+00:00" + }, + { + "name": "composer/semver", + "version": "3.3.2", + "source": { + "type": "git", + "url": "https://github.com/composer/semver.git", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", + "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Semver\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nils Adermann", + "email": "naderman@naderman.de", + "homepage": "http://www.naderman.de" + }, + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + }, + { + "name": "Rob Bast", + "email": "rob.bast@gmail.com", + "homepage": "http://robbast.nl" + } + ], + "description": "Semver library that offers utilities, version constraint parsing and validation.", + "keywords": [ + "semantic", + "semver", + "validation", + "versioning" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/semver/issues", + "source": "https://github.com/composer/semver/tree/3.3.2" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-04-01T19:23:25+00:00" + }, + { + "name": "composer/xdebug-handler", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/composer/xdebug-handler.git", + "reference": "ced299686f41dce890debac69273b47ffe98a40c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", + "reference": "ced299686f41dce890debac69273b47ffe98a40c", + "shasum": "" + }, + "require": { + "composer/pcre": "^1 || ^2 || ^3", + "php": "^7.2.5 || ^8.0", + "psr/log": "^1 || ^2 || ^3" + }, + "require-dev": { + "phpstan/phpstan": "^1.0", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Composer\\XdebugHandler\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "John Stevenson", + "email": "john-stevenson@blueyonder.co.uk" + } + ], + "description": "Restarts a process without Xdebug.", + "keywords": [ + "Xdebug", + "performance" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/xdebug-handler/issues", + "source": "https://github.com/composer/xdebug-handler/tree/3.0.3" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2022-02-25T21:32:43+00:00" + }, + { + "name": "doctrine/annotations", + "version": "1.14.2", + "source": { + "type": "git", + "url": "https://github.com/doctrine/annotations.git", + "reference": "ad785217c1e9555a7d6c6c8c9f406395a5e2882b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/annotations/zipball/ad785217c1e9555a7d6c6c8c9f406395a5e2882b", + "reference": "ad785217c1e9555a7d6c6c8c9f406395a5e2882b", + "shasum": "" + }, + "require": { + "doctrine/lexer": "^1 || ^2", + "ext-tokenizer": "*", + "php": "^7.1 || ^8.0", + "psr/cache": "^1 || ^2 || ^3" + }, + "require-dev": { + "doctrine/cache": "^1.11 || ^2.0", + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "~1.4.10 || ^1.8.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "symfony/cache": "^4.4 || ^5.4 || ^6", + "vimeo/psalm": "^4.10" + }, + "suggest": { + "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Benjamin Eberlei", + "email": "kontakt@beberlei.de" + }, + { + "name": "Jonathan Wage", + "email": "jonwage@gmail.com" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "Docblock Annotations Parser", + "homepage": "https://www.doctrine-project.org/projects/annotations.html", + "keywords": [ + "annotations", + "docblock", + "parser" + ], + "support": { + "issues": "https://github.com/doctrine/annotations/issues", + "source": "https://github.com/doctrine/annotations/tree/1.14.2" + }, + "time": "2022-12-15T06:48:22+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpunit/phpunit": "^7.5|^8.5|^9.5", + "psr/log": "^1|^2|^3" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.0.0" + }, + "time": "2022-05-02T15:47:09+00:00" + }, + { + "name": "doctrine/lexer", + "version": "2.1.0", + "source": { + "type": "git", + "url": "https://github.com/doctrine/lexer.git", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9 || ^10", + "phpstan/phpstan": "^1.3", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.18.3", + "vimeo/psalm": "^4.11 || ^5.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Common\\Lexer\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Guilherme Blanco", + "email": "guilhermeblanco@gmail.com" + }, + { + "name": "Roman Borschel", + "email": "roman@code-factory.org" + }, + { + "name": "Johannes Schmitt", + "email": "schmittjoh@gmail.com" + } + ], + "description": "PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.", + "homepage": "https://www.doctrine-project.org/projects/lexer.html", + "keywords": [ + "annotations", + "docblock", + "lexer", + "parser", + "php" + ], + "support": { + "issues": "https://github.com/doctrine/lexer/issues", + "source": "https://github.com/doctrine/lexer/tree/2.1.0" + }, + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Flexer", + "type": "tidelift" + } + ], + "time": "2022-12-14T08:49:07+00:00" + }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v3.13.1", + "source": { + "type": "git", + "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", + "reference": "78d2251dd86b49c609a0fd37c20dcf0a00aea5a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/78d2251dd86b49c609a0fd37c20dcf0a00aea5a7", + "reference": "78d2251dd86b49c609a0fd37c20dcf0a00aea5a7", + "shasum": "" + }, + "require": { + "composer/semver": "^3.2", + "composer/xdebug-handler": "^3.0.3", + "doctrine/annotations": "^1.13", + "ext-json": "*", + "ext-tokenizer": "*", + "php": "^7.4 || ^8.0", + "sebastian/diff": "^4.0", + "symfony/console": "^5.4 || ^6.0", + "symfony/event-dispatcher": "^5.4 || ^6.0", + "symfony/filesystem": "^5.4 || ^6.0", + "symfony/finder": "^5.4 || ^6.0", + "symfony/options-resolver": "^5.4 || ^6.0", + "symfony/polyfill-mbstring": "^1.23", + "symfony/polyfill-php80": "^1.25", + "symfony/polyfill-php81": "^1.25", + "symfony/process": "^5.4 || ^6.0", + "symfony/stopwatch": "^5.4 || ^6.0" + }, + "require-dev": { + "justinrainbow/json-schema": "^5.2", + "keradus/cli-executor": "^2.0", + "mikey179/vfsstream": "^1.6.10", + "php-coveralls/php-coveralls": "^2.5.2", + "php-cs-fixer/accessible-object": "^1.1", + "php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.2", + "php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.2.1", + "phpspec/prophecy": "^1.15", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "phpunitgoodpractices/polyfill": "^1.6", + "phpunitgoodpractices/traits": "^1.9.2", + "symfony/phpunit-bridge": "^6.0", + "symfony/yaml": "^5.4 || ^6.0" + }, + "suggest": { + "ext-dom": "For handling output formats in XML", + "ext-mbstring": "For handling non-UTF8 characters." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Dariusz RumiƄski", + "email": "dariusz.ruminski@gmail.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "support": { + "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.13.1" + }, + "funding": [ + { + "url": "https://github.com/keradus", + "type": "github" + } + ], + "time": "2022-12-18T00:47:22+00:00" + }, + { + "name": "psr/cache", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/cache.git", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/cache/zipball/aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "reference": "aa5030cfa5405eccfdcb1083ce040c2cb8d253bf", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Cache\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for caching libraries", + "keywords": [ + "cache", + "psr", + "psr-6" + ], + "support": { + "source": "https://github.com/php-fig/cache/tree/3.0.0" + }, + "time": "2021-02-03T23:26:27+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", + "reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.0" + }, + "time": "2021-07-14T16:46:02+00:00" + }, + { + "name": "sebastian/diff", + "version": "4.0.4", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "reference": "3461e3fccc7cfdfc2720be910d3bd73c69be590d", + "shasum": "" + }, + "require": { + "php": ">=7.3" + }, + "require-dev": { + "phpunit/phpunit": "^9.3", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/4.0.4" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2020-10-26T13:10:38+00:00" + }, + { + "name": "symfony/console", + "version": "v6.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "0f579613e771dba2dbb8211c382342a641f5da06" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/0f579613e771dba2dbb8211c382342a641f5da06", + "reference": "0f579613e771dba2dbb8211c382342a641f5da06", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.2.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-12-28T14:26:22+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3", + "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-25T10:21:52+00:00" + }, + { + "name": "symfony/event-dispatcher", + "version": "v6.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher.git", + "reference": "3ffeb31139b49bf6ef0bc09d1db95eac053388d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3ffeb31139b49bf6ef0bc09d1db95eac053388d1", + "reference": "3ffeb31139b49bf6ef0bc09d1db95eac053388d1", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/event-dispatcher-contracts": "^2|^3" + }, + "conflict": { + "symfony/dependency-injection": "<5.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/error-handler": "^5.4|^6.0", + "symfony/expression-language": "^5.4|^6.0", + "symfony/http-foundation": "^5.4|^6.0", + "symfony/service-contracts": "^1.1|^2|^3", + "symfony/stopwatch": "^5.4|^6.0" + }, + "suggest": { + "symfony/dependency-injection": "", + "symfony/http-kernel": "" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\EventDispatcher\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-12-14T16:11:27+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "0782b0b52a737a05b4383d0df35a474303cabdae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0782b0b52a737a05b4383d0df35a474303cabdae", + "reference": "0782b0b52a737a05b4383d0df35a474303cabdae", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/event-dispatcher": "^1" + }, + "suggest": { + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-25T10:21:52+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v6.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "50b2523c874605cf3d4acf7a9e2b30b6a440a016" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/50b2523c874605cf3d4acf7a9e2b30b6a440a016", + "reference": "50b2523c874605cf3d4acf7a9e2b30b6a440a016", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v6.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-20T13:01:27+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.2.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/81eefbddfde282ee33b437ba5e13d7753211ae8e", + "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v6.2.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-12-22T17:55:15+00:00" + }, + { + "name": "symfony/options-resolver", + "version": "v6.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "d28f02acde71ff75e957082cd36e973df395f626" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d28f02acde71ff75e957082cd36e973df395f626", + "reference": "d28f02acde71ff75e957082cd36e973df395f626", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an improved replacement for the array_replace PHP function", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "support": { + "source": "https://github.com/symfony/options-resolver/tree/v6.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-02T09:08:04+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-php81", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php81.git", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", + "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Php81\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/process", + "version": "v6.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/ba6e55359f8f755fe996c58a81e00eaa67a35877", + "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-02T09:08:04+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/aac98028c69df04ee77eb69b96b86ee51fbf4b75", + "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "suggest": { + "symfony/service-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.3-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-25T10:21:52+00:00" + }, + { + "name": "symfony/stopwatch", + "version": "v6.2.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/stopwatch.git", + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/stopwatch/zipball/266636bb8f3fbdccc302491df7b3a1b9a8c238a7", + "reference": "266636bb8f3fbdccc302491df7b3a1b9a8c238a7", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/service-contracts": "^1|^2|^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Stopwatch\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides a way to profile code", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/stopwatch/tree/v6.2.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-09-28T16:00:52+00:00" + }, + { + "name": "symfony/string", + "version": "v6.2.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "863219fd713fa41cbcd285a79723f94672faff4d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/863219fd713fa41cbcd285a79723f94672faff4d", + "reference": "863219fd713fa41cbcd285a79723f94672faff4d", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.0" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.0|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.2.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-12-14T16:11:27+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/.ci/phpcs.sh b/.ci/phpcs.sh new file mode 100755 index 0000000000..fd0877199f --- /dev/null +++ b/.ci/phpcs.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +# +# phpstan.sh +# Copyright (c) 2021 james@firefly-iii.org +# +# This file is part of Firefly III (https://github.com/firefly-iii). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# + +# Install composer packages +#composer install --no-scripts --no-ansi + +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + +# enable test .env file. +# cp .ci/.env.ci .env + +# clean up php code +cd $SCRIPT_DIR/php-cs-fixer +composer update +./vendor/bin/php-cs-fixer fix --config $SCRIPT_DIR/php-cs-fixer/.php-cs-fixer.php --allow-risky=yes +cd $SCRIPT_DIR/.. + +exit 0 diff --git a/.ci/phpstan.neon b/.ci/phpstan.neon index 12c4a66b9d..f846b62d11 100644 --- a/.ci/phpstan.neon +++ b/.ci/phpstan.neon @@ -8,26 +8,63 @@ parameters: ignoreErrors: - '#is not allowed to extend#' - '#is neither abstract nor final#' - - '#Control structures using switch should not be used\.#' - '#has a nullable return type declaration#' - '#with a nullable type declaration#' - '#with null as default value#' - - '#Constructor in [a-zA-Z0-9\\_]+ has parameter \$[a-zA-Z0-9\\_]+ with default value#' + - '#is not covariant with PHPDoc type array#' - - message: '#Function compact\(\) should not be used.#' + message: '#but containers should not be injected#' paths: - - ../app/Http/Controllers - - ../app/Support/Http/Controllers/RenderPartialViews.php - - ../app/Support/Form/FormSupport.php - - ../app/Support/Form/CurrencyForm.php - - ../app/Support/Form/AccountForm.php + - ../app/Support/Authentication/RemoteUserGuard.php + - + message: '#Control structures using switch should not be used.#' + paths: + - ../app/Api/V1/Controllers/Data/DestroyController.php + - ../app/Console/Commands/Correction/FixAccountTypes.php + - ../app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php + - ../app/Exceptions/GracefulNotFoundHandler.php + - ../app/Generator/Webhook/StandardMessageGenerator.php + - ../app/Support/Amount.php + - ../app/Support/Navigation.php + - ../app/Support/ParseDateString.php + - ../app/Support/Search/AccountSearch.php + - ../app/Support/Search/OperatorQuerySearch.php + - ../app/Support/Twig/General.php + - ../app/Transformers/RecurrenceTransformer.php + - ../app/Validation/AccountValidator.php + - ../app/Validation/RecurrenceValidation.php + - ../app/Validation/TransactionValidation.php + + - + message: '#Function compact\(\) should not be used#' + paths: + - ../app/Generator/Report/Account/MonthReportGenerator.php + - ../app/Generator/Report/Audit/MonthReportGenerator.php + - ../app/Generator/Report/Budget/MonthReportGenerator.php + - ../app/Generator/Report/Category/MonthReportGenerator.php + - ../app/Generator/Report/Standard/MonthReportGenerator.php + - ../app/Generator/Report/Standard/MultiYearReportGenerator.php + - ../app/Generator/Report/Standard/YearReportGenerator.php + - ../app/Generator/Report/Tag/MonthReportGenerator.php + - ../app/Http/Controllers/Account/*.php + - ../app/Http/Controllers/Admin/*.php + - ../app/Http/Controllers/*.php - ../app/Support/ExpandedForm.php - - ../app/Generator/Report + - ../app/Support/Form/AccountForm.php + - ../app/Support/Form/CurrencyForm.php + - ../app/Support/Form/FormSupport.php + - + message: '#Either catch a more specific exception#' + paths: + - ../app/Support/Form/FormSupport.php + paths: - ../app - ../database - ../routes + - ../config - ../bootstrap/app.php # The level 8 is the highest level. original was 5 - level: 3 + level: 4 + diff --git a/.ci/phpstan.sh b/.ci/phpstan.sh index 4ffaffe5a4..4efa51ed6c 100755 --- a/.ci/phpstan.sh +++ b/.ci/phpstan.sh @@ -23,11 +23,11 @@ # Install composer packages #composer install --no-scripts --no-ansi +SCRIPT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + # enable test .env file. -cp .ci/.env.ci .env +# cp .ci/.env.ci .env # Do static code analysis. # ./vendor/bin/phpstan analyse -c .ci/phpstan.neon --no-progress -./vendor/bin/phpstan analyse -c .ci/phpstan.neon - -exit 0 \ No newline at end of file +./vendor/bin/phpstan analyse -c .ci/phpstan.neon --xdebug --error-format=table > phpstan-report.txt diff --git a/.env.example b/.env.example index 3a5465cffd..0c7a01fcc8 100644 --- a/.env.example +++ b/.env.example @@ -7,6 +7,7 @@ APP_DEBUG=false # This should be your email address. # If you use Docker or similar, you can set this variable from a file by using SITE_OWNER_FILE +# The variable is used in some errors shown to users who aren't admin. SITE_OWNER=mail@example.com # The encryption key for your sessions. Keep this very secure. @@ -169,6 +170,12 @@ SEND_REPORT_JOURNALS=true # and disabled by default. ENABLE_EXTERNAL_MAP=false +# Set this value to true if you want Firefly III to download currency exchange rates +# from the internet. These rates are hosted by the creator of Firefly III inside +# an Azure Storage Container. +# Not all currencies may be available. Rates may be wrong. +ENABLE_EXTERNAL_RATES=false + # The map will default to this location: MAP_DEFAULT_LAT=51.983333 MAP_DEFAULT_LONG=5.916667 diff --git a/app/Api/V1/Controllers/Autocomplete/AccountController.php b/app/Api/V1/Controllers/Autocomplete/AccountController.php index 7fe5b418cf..1bb4f62100 100644 --- a/app/Api/V1/Controllers/Autocomplete/AccountController.php +++ b/app/Api/V1/Controllers/Autocomplete/AccountController.php @@ -67,7 +67,7 @@ class AccountController extends Controller * Documentation for this endpoint: * https://api-docs.firefly-iii.org/#/autocomplete/getAccountsAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse * @throws JsonException @@ -82,7 +82,7 @@ class AccountController extends Controller $date = $data['date'] ?? today(config('app.timezone')); $return = []; - $result = $this->repository->searchAccount((string) $query, $types, $data['limit']); + $result = $this->repository->searchAccount((string)$query, $types, $data['limit']); $defaultCurrency = app('amount')->getDefaultCurrency(); /** @var Account $account */ @@ -96,7 +96,7 @@ class AccountController extends Controller } $return[] = [ - 'id' => (string) $account->id, + 'id' => (string)$account->id, 'name' => $account->name, 'name_with_balance' => $nameWithBalance, 'type' => $account->accountType->type, @@ -111,12 +111,13 @@ class AccountController extends Controller // custom order. $order = [AccountType::ASSET, AccountType::REVENUE, AccountType::EXPENSE]; usort( - $return, function ($a, $b) use ($order) { - $pos_a = array_search($a['type'], $order); - $pos_b = array_search($b['type'], $order); + $return, + function ($a, $b) use ($order) { + $pos_a = array_search($a['type'], $order, true); + $pos_b = array_search($b['type'], $order, true); - return $pos_a - $pos_b; - } + return $pos_a - $pos_b; + } ); return response()->json($return); diff --git a/app/Api/V1/Controllers/Autocomplete/BillController.php b/app/Api/V1/Controllers/Autocomplete/BillController.php index 7b4270b725..bd1caa2478 100644 --- a/app/Api/V1/Controllers/Autocomplete/BillController.php +++ b/app/Api/V1/Controllers/Autocomplete/BillController.php @@ -58,8 +58,9 @@ class BillController extends Controller /** * Documentation for this endpoint is at: * https://api-docs.firefly-iii.org/#/autocomplete/getBillsAC + * TODO expand API to add active field. * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -70,13 +71,13 @@ class BillController extends Controller $filtered = $result->map( static function (Bill $item) { return [ - 'id' => (string) $item->id, + 'id' => (string)$item->id, 'name' => $item->name, + 'active' => $item->active ]; } ); return response()->json($filtered->toArray()); } - } diff --git a/app/Api/V1/Controllers/Autocomplete/BudgetController.php b/app/Api/V1/Controllers/Autocomplete/BudgetController.php index 60d56f7fb0..48f6b69f2a 100644 --- a/app/Api/V1/Controllers/Autocomplete/BudgetController.php +++ b/app/Api/V1/Controllers/Autocomplete/BudgetController.php @@ -59,7 +59,7 @@ class BudgetController extends Controller * Documentation for this endpoint is at: * https://api-docs.firefly-iii.org/#/autocomplete/getBudgetsAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -70,7 +70,7 @@ class BudgetController extends Controller $filtered = $result->map( static function (Budget $item) { return [ - 'id' => (string) $item->id, + 'id' => (string)$item->id, 'name' => $item->name, ]; } diff --git a/app/Api/V1/Controllers/Autocomplete/CategoryController.php b/app/Api/V1/Controllers/Autocomplete/CategoryController.php index 3e29a7aa33..e98a20e4e1 100644 --- a/app/Api/V1/Controllers/Autocomplete/CategoryController.php +++ b/app/Api/V1/Controllers/Autocomplete/CategoryController.php @@ -59,7 +59,7 @@ class CategoryController extends Controller * Documentation for this endpoint is at: * https://api-docs.firefly-iii.org/#/autocomplete/getCategoriesAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -70,7 +70,7 @@ class CategoryController extends Controller $filtered = $result->map( static function (Category $item) { return [ - 'id' => (string) $item->id, + 'id' => (string)$item->id, 'name' => $item->name, ]; } diff --git a/app/Api/V1/Controllers/Autocomplete/CurrencyController.php b/app/Api/V1/Controllers/Autocomplete/CurrencyController.php index e0eef2e62a..50fd139f90 100644 --- a/app/Api/V1/Controllers/Autocomplete/CurrencyController.php +++ b/app/Api/V1/Controllers/Autocomplete/CurrencyController.php @@ -59,7 +59,7 @@ class CurrencyController extends Controller * Documentation for this endpoint is at: * https://api-docs.firefly-iii.org/#/autocomplete/getCurrenciesAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -72,7 +72,7 @@ class CurrencyController extends Controller /** @var TransactionCurrency $currency */ foreach ($collection as $currency) { $result[] = [ - 'id' => (string) $currency->id, + 'id' => (string)$currency->id, 'name' => $currency->name, 'code' => $currency->code, 'symbol' => $currency->symbol, @@ -87,7 +87,7 @@ class CurrencyController extends Controller * Documentation for this endpoint is at: * https://api-docs.firefly-iii.org/#/autocomplete/getCurrenciesCodeAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse * @deprecated @@ -101,7 +101,7 @@ class CurrencyController extends Controller /** @var TransactionCurrency $currency */ foreach ($collection as $currency) { $result[] = [ - 'id' => (string) $currency->id, + 'id' => (string)$currency->id, 'name' => sprintf('%s (%s)', $currency->name, $currency->code), 'code' => $currency->code, 'symbol' => $currency->symbol, diff --git a/app/Api/V1/Controllers/Autocomplete/ObjectGroupController.php b/app/Api/V1/Controllers/Autocomplete/ObjectGroupController.php index aaab2e1594..10b119dd71 100644 --- a/app/Api/V1/Controllers/Autocomplete/ObjectGroupController.php +++ b/app/Api/V1/Controllers/Autocomplete/ObjectGroupController.php @@ -59,7 +59,7 @@ class ObjectGroupController extends Controller * Documentation for this endpoint is at: * https://api-docs.firefly-iii.org/#/autocomplete/getObjectGroupsAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -72,7 +72,7 @@ class ObjectGroupController extends Controller /** @var ObjectGroup $objectGroup */ foreach ($result as $objectGroup) { $return[] = [ - 'id' => (string) $objectGroup->id, + 'id' => (string)$objectGroup->id, 'name' => $objectGroup->title, 'title' => $objectGroup->title, ]; @@ -80,5 +80,4 @@ class ObjectGroupController extends Controller return response()->json($return); } - } diff --git a/app/Api/V1/Controllers/Autocomplete/PiggyBankController.php b/app/Api/V1/Controllers/Autocomplete/PiggyBankController.php index 6efbe495cf..65d784f501 100644 --- a/app/Api/V1/Controllers/Autocomplete/PiggyBankController.php +++ b/app/Api/V1/Controllers/Autocomplete/PiggyBankController.php @@ -63,7 +63,7 @@ class PiggyBankController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/autocomplete/getPiggiesAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -78,7 +78,7 @@ class PiggyBankController extends Controller foreach ($piggies as $piggy) { $currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency; $response[] = [ - 'id' => (string) $piggy->id, + 'id' => (string)$piggy->id, 'name' => $piggy->name, 'currency_id' => $currency->id, 'currency_name' => $currency->name, @@ -95,7 +95,7 @@ class PiggyBankController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/autocomplete/getPiggiesBalanceAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -110,10 +110,12 @@ class PiggyBankController extends Controller $currency = $this->accountRepository->getAccountCurrency($piggy->account) ?? $defaultCurrency; $currentAmount = $this->piggyRepository->getRepetition($piggy)->currentamount ?? '0'; $response[] = [ - 'id' => (string) $piggy->id, + 'id' => (string)$piggy->id, 'name' => $piggy->name, 'name_with_balance' => sprintf( - '%s (%s / %s)', $piggy->name, app('amount')->formatAnything($currency, $currentAmount, false), + '%s (%s / %s)', + $piggy->name, + app('amount')->formatAnything($currency, $currentAmount, false), app('amount')->formatAnything($currency, $piggy->targetamount, false), ), 'currency_id' => $currency->id, @@ -126,5 +128,4 @@ class PiggyBankController extends Controller return response()->json($response); } - } diff --git a/app/Api/V1/Controllers/Autocomplete/RecurrenceController.php b/app/Api/V1/Controllers/Autocomplete/RecurrenceController.php index 93e6bbd315..79a104ac91 100644 --- a/app/Api/V1/Controllers/Autocomplete/RecurrenceController.php +++ b/app/Api/V1/Controllers/Autocomplete/RecurrenceController.php @@ -56,7 +56,7 @@ class RecurrenceController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/autocomplete/getRecurringAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -69,7 +69,7 @@ class RecurrenceController extends Controller /** @var Recurrence $recurrence */ foreach ($recurrences as $recurrence) { $response[] = [ - 'id' => (string) $recurrence->id, + 'id' => (string)$recurrence->id, 'name' => $recurrence->title, 'description' => $recurrence->description, ]; @@ -77,5 +77,4 @@ class RecurrenceController extends Controller return response()->json($response); } - } diff --git a/app/Api/V1/Controllers/Autocomplete/RuleController.php b/app/Api/V1/Controllers/Autocomplete/RuleController.php index 47c24795ea..1ab2cd1399 100644 --- a/app/Api/V1/Controllers/Autocomplete/RuleController.php +++ b/app/Api/V1/Controllers/Autocomplete/RuleController.php @@ -56,7 +56,7 @@ class RuleController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/autocomplete/getRulesAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -69,7 +69,7 @@ class RuleController extends Controller /** @var Rule $rule */ foreach ($rules as $rule) { $response[] = [ - 'id' => (string) $rule->id, + 'id' => (string)$rule->id, 'name' => $rule->title, 'description' => $rule->description, ]; @@ -77,5 +77,4 @@ class RuleController extends Controller return response()->json($response); } - } diff --git a/app/Api/V1/Controllers/Autocomplete/RuleGroupController.php b/app/Api/V1/Controllers/Autocomplete/RuleGroupController.php index d5f88aa3cf..10e6fd3697 100644 --- a/app/Api/V1/Controllers/Autocomplete/RuleGroupController.php +++ b/app/Api/V1/Controllers/Autocomplete/RuleGroupController.php @@ -56,7 +56,7 @@ class RuleGroupController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/autocomplete/getRuleGroupsAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -69,7 +69,7 @@ class RuleGroupController extends Controller /** @var RuleGroup $group */ foreach ($groups as $group) { $response[] = [ - 'id' => (string) $group->id, + 'id' => (string)$group->id, 'name' => $group->title, 'description' => $group->description, ]; diff --git a/app/Api/V1/Controllers/Autocomplete/TagController.php b/app/Api/V1/Controllers/Autocomplete/TagController.php index 95e031ebf7..0175aa138c 100644 --- a/app/Api/V1/Controllers/Autocomplete/TagController.php +++ b/app/Api/V1/Controllers/Autocomplete/TagController.php @@ -59,7 +59,7 @@ class TagController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/autocomplete/getTagAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -72,7 +72,7 @@ class TagController extends Controller /** @var Tag $tag */ foreach ($result as $tag) { $array[] = [ - 'id' => (string) $tag->id, + 'id' => (string)$tag->id, 'name' => $tag->tag, 'tag' => $tag->tag, ]; diff --git a/app/Api/V1/Controllers/Autocomplete/TransactionController.php b/app/Api/V1/Controllers/Autocomplete/TransactionController.php index d24902ae89..dfb9f00f22 100644 --- a/app/Api/V1/Controllers/Autocomplete/TransactionController.php +++ b/app/Api/V1/Controllers/Autocomplete/TransactionController.php @@ -64,7 +64,7 @@ class TransactionController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/autocomplete/getTransactionsAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ @@ -80,8 +80,8 @@ class TransactionController extends Controller /** @var TransactionJournal $journal */ foreach ($filtered as $journal) { $array[] = [ - 'id' => (string) $journal->id, - 'transaction_group_id' => (string) $journal->transaction_group_id, + 'id' => (string)$journal->id, + 'transaction_group_id' => (string)$journal->transaction_group_id, 'name' => $journal->description, 'description' => $journal->description, ]; @@ -94,17 +94,17 @@ class TransactionController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/autocomplete/getTransactionsIDAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse */ public function transactionsWithID(AutocompleteRequest $request): JsonResponse { $data = $request->getData(); - $result = new Collection; + $result = new Collection(); if (is_numeric($data['query'])) { // search for group, not journal. - $firstResult = $this->groupRepository->find((int) $data['query']); + $firstResult = $this->groupRepository->find((int)$data['query']); if (null !== $firstResult) { // group may contain multiple journals, each a result: foreach ($firstResult->transactionJournals as $journal) { @@ -122,8 +122,8 @@ class TransactionController extends Controller /** @var TransactionJournal $journal */ foreach ($result as $journal) { $array[] = [ - 'id' => (string) $journal->id, - 'transaction_group_id' => (string) $journal->transaction_group_id, + 'id' => (string)$journal->id, + 'transaction_group_id' => (string)$journal->transaction_group_id, 'name' => sprintf('#%d: %s', $journal->transaction_group_id, $journal->description), 'description' => sprintf('#%d: %s', $journal->transaction_group_id, $journal->description), ]; diff --git a/app/Api/V1/Controllers/Autocomplete/TransactionTypeController.php b/app/Api/V1/Controllers/Autocomplete/TransactionTypeController.php index 24d09276f8..036b614cad 100644 --- a/app/Api/V1/Controllers/Autocomplete/TransactionTypeController.php +++ b/app/Api/V1/Controllers/Autocomplete/TransactionTypeController.php @@ -55,7 +55,7 @@ class TransactionTypeController extends Controller * This endpoint is documented at * https://api-docs.firefly-iii.org/#/autocomplete/getTransactionTypesAC * - * @param AutocompleteRequest $request + * @param AutocompleteRequest $request * * @return JsonResponse * @codeCoverageIgnore @@ -70,7 +70,7 @@ class TransactionTypeController extends Controller foreach ($types as $type) { // different key for consistency. $array[] = [ - 'id' => (string) $type->id, + 'id' => (string)$type->id, 'name' => $type->type, 'type' => $type->type, ]; diff --git a/app/Api/V1/Controllers/Chart/AccountController.php b/app/Api/V1/Controllers/Chart/AccountController.php index 463803a488..abbc314245 100644 --- a/app/Api/V1/Controllers/Chart/AccountController.php +++ b/app/Api/V1/Controllers/Chart/AccountController.php @@ -76,7 +76,7 @@ class AccountController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/charts/getChartAccountOverview * - * @param DateRequest $request + * @param DateRequest $request * * @return JsonResponse * @throws FireflyException @@ -98,7 +98,7 @@ class AccountController extends Controller $frontPage = app('preferences')->get('frontPageAccounts', $defaultSet); $default = app('amount')->getDefaultCurrency(); - if (empty($frontPage->data)) { + if (!(is_array($frontPage->data) && count($frontPage->data) > 0)) { $frontPage->data = $defaultSet; $frontPage->save(); } @@ -115,7 +115,7 @@ class AccountController extends Controller } $currentSet = [ 'label' => $account->name, - 'currency_id' => (string) $currency->id, + 'currency_id' => (string)$currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, 'currency_decimal_places' => $currency->decimal_places, @@ -127,7 +127,8 @@ class AccountController extends Controller ]; $currentStart = clone $start; $range = app('steam')->balanceInRange($account, $start, clone $end); - $previous = $range[0] ?? '0'; + // 2022-10-11 this method no longer converts to float. + $previous = array_values($range)[0]; while ($currentStart <= $end) { $format = $currentStart->format('Y-m-d'); $label = $currentStart->toAtomString(); diff --git a/app/Api/V1/Controllers/Controller.php b/app/Api/V1/Controllers/Controller.php index 9250a7cc2a..75a5f01407 100644 --- a/app/Api/V1/Controllers/Controller.php +++ b/app/Api/V1/Controllers/Controller.php @@ -33,7 +33,6 @@ use Illuminate\Foundation\Validation\ValidatesRequests; use Illuminate\Routing\Controller as BaseController; use League\Fractal\Manager; use League\Fractal\Serializer\JsonApiSerializer; -use Log; use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Symfony\Component\HttpFoundation\ParameterBag; @@ -45,7 +44,9 @@ use Symfony\Component\HttpFoundation\ParameterBag; */ abstract class Controller extends BaseController { - use AuthorizesRequests, DispatchesJobs, ValidatesRequests; + use AuthorizesRequests; + use DispatchesJobs; + use ValidatesRequests; protected const CONTENT_TYPE = 'application/vnd.api+json'; protected array $allowedSort; @@ -69,7 +70,6 @@ abstract class Controller extends BaseController return $next($request); } ); - } /** @@ -81,11 +81,15 @@ abstract class Controller extends BaseController */ private function getParameters(): ParameterBag { - $bag = new ParameterBag; + $bag = new ParameterBag(); $page = (int)request()->get('page'); - if (0 === $page) { + + if ($page < 1) { $page = 1; } + if ($page > (2 ^ 16)) { + $page = (2 ^ 16); + } $bag->set('page', $page); // some date fields: @@ -96,9 +100,9 @@ abstract class Controller extends BaseController if (null !== $date) { try { $obj = Carbon::parse($date); - } catch (InvalidDateException | InvalidFormatException $e) { + } catch (InvalidDateException|InvalidFormatException $e) { // don't care - Log::warning(sprintf('Ignored invalid date "%s" in API controller parameter check: %s', $date, $e->getMessage())); + app('log')->warning(sprintf('Ignored invalid date "%s" in API controller parameter check: %s', $date, $e->getMessage())); } } $bag->set($field, $obj); @@ -118,7 +122,7 @@ abstract class Controller extends BaseController } /** - * @param ParameterBag $bag + * @param ParameterBag $bag * * @return ParameterBag */ @@ -167,7 +171,7 @@ abstract class Controller extends BaseController $params[$key] = $value; } - return $return . http_build_query($params); + return $return.http_build_query($params); } /** @@ -176,8 +180,8 @@ abstract class Controller extends BaseController final protected function getManager(): Manager { // create some objects: - $manager = new Manager; - $baseUrl = request()->getSchemeAndHttpHost() . '/api/v1'; + $manager = new Manager(); + $baseUrl = request()->getSchemeAndHttpHost().'/api/v1'; $manager->setSerializer(new JsonApiSerializer($baseUrl)); return $manager; diff --git a/app/Api/V1/Controllers/Data/Bulk/AccountController.php b/app/Api/V1/Controllers/Data/Bulk/AccountController.php index 3d80897e83..defb3596c5 100644 --- a/app/Api/V1/Controllers/Data/Bulk/AccountController.php +++ b/app/Api/V1/Controllers/Data/Bulk/AccountController.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers\Data\Bulk; - use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\Data\Bulk\MoveTransactionsRequest; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -59,7 +58,7 @@ class AccountController extends Controller /** * This endpoint is deprecated and not documented. * - * @param MoveTransactionsRequest $request + * @param MoveTransactionsRequest $request * * @return JsonResponse * @deprecated @@ -75,7 +74,5 @@ class AccountController extends Controller $service->moveTransactions($original, $destination); return response()->json([], 204); - } - } diff --git a/app/Api/V1/Controllers/Data/Bulk/TransactionController.php b/app/Api/V1/Controllers/Data/Bulk/TransactionController.php index f04e698b97..77e898306c 100644 --- a/app/Api/V1/Controllers/Data/Bulk/TransactionController.php +++ b/app/Api/V1/Controllers/Data/Bulk/TransactionController.php @@ -63,7 +63,7 @@ class TransactionController extends Controller /** * This endpoint is documented at: * - * @param TransactionRequest $request + * @param TransactionRequest $request * * @return JsonResponse */ @@ -76,8 +76,8 @@ class TransactionController extends Controller // to respond to what is in the $query. // this is OK because only one thing can be in the query at the moment. if ($this->updatesTransactionAccount($params)) { - $original = $this->repository->find((int) $params['where']['account_id']); - $destination = $this->repository->find((int) $params['update']['account_id']); + $original = $this->repository->find((int)$params['where']['account_id']); + $destination = $this->repository->find((int)$params['update']['account_id']); /** @var AccountDestroyService $service */ $service = app(AccountDestroyService::class); @@ -88,7 +88,7 @@ class TransactionController extends Controller } /** - * @param array $params + * @param array $params * * @return bool */ @@ -96,5 +96,4 @@ class TransactionController extends Controller { return array_key_exists('account_id', $params['where']) && array_key_exists('account_id', $params['update']); } - } diff --git a/app/Api/V1/Controllers/Data/DestroyController.php b/app/Api/V1/Controllers/Data/DestroyController.php index 40b39a5be3..8154301663 100644 --- a/app/Api/V1/Controllers/Data/DestroyController.php +++ b/app/Api/V1/Controllers/Data/DestroyController.php @@ -45,25 +45,28 @@ use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Services\Internal\Destroy\AccountDestroyService; use FireflyIII\Services\Internal\Destroy\JournalDestroyService; use Illuminate\Http\JsonResponse; +use Illuminate\Support\Facades\Log; /** * Class DestroyController */ class DestroyController extends Controller { + private bool $unused; + /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/destroyData * - * @param DestroyRequest $request + * @param DestroyRequest $request * * @return JsonResponse * @throws FireflyException */ public function destroy(DestroyRequest $request): JsonResponse { - $objects = $request->getObjects(); - + $objects = $request->getObjects(); + $this->unused = $request->boolean('unused', false); switch ($objects) { default: throw new FireflyException(sprintf('This endpoint can\'t handle object "%s"', $objects)); @@ -94,24 +97,32 @@ class DestroyController extends Controller case 'accounts': $this->destroyAccounts( [ - AccountType::ASSET, AccountType::DEFAULT, - AccountType::BENEFICIARY, AccountType::EXPENSE, - AccountType::REVENUE, AccountType::INITIAL_BALANCE, - AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD, + AccountType::ASSET, + AccountType::DEFAULT, + AccountType::BENEFICIARY, + AccountType::EXPENSE, + AccountType::REVENUE, + AccountType::INITIAL_BALANCE, + AccountType::DEBT, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::CREDITCARD, ] ); break; case 'asset_accounts': $this->destroyAccounts( [ - AccountType::ASSET, AccountType::DEFAULT, + AccountType::ASSET, + AccountType::DEFAULT, ] ); break; case 'expense_accounts': $this->destroyAccounts( [ - AccountType::BENEFICIARY, AccountType::EXPENSE, + AccountType::BENEFICIARY, + AccountType::EXPENSE, ] ); break; @@ -125,7 +136,10 @@ class DestroyController extends Controller case 'liabilities': $this->destroyAccounts( [ - AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD, + AccountType::DEBT, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::CREDITCARD, ] ); break; @@ -253,7 +267,7 @@ class DestroyController extends Controller } /** - * @param array $types + * @param array $types */ private function destroyAccounts(array $types): void { @@ -261,14 +275,24 @@ class DestroyController extends Controller $repository = app(AccountRepositoryInterface::class); $collection = $repository->getAccountsByType($types); $service = app(AccountDestroyService::class); + /** @var Account $account */ foreach ($collection as $account) { - $service->destroy($account, null); + $count = $account->transactions()->count(); + if (true === $this->unused && 0 === $count) { + Log::info(sprintf('Deleted unused account #%d "%s"', $account->id, $account->name)); + $service->destroy($account, null); + continue; + } + if (false === $this->unused) { + Log::info(sprintf('Deleting account #%d "%s"', $account->id, $account->name)); + $service->destroy($account, null); + } } } /** - * @param array $types + * @param array $types */ private function destroyTransactions(array $types): void { @@ -281,5 +305,4 @@ class DestroyController extends Controller $service->destroy($journal); } } - } diff --git a/app/Api/V1/Controllers/Data/Export/ExportController.php b/app/Api/V1/Controllers/Data/Export/ExportController.php index c6eef16cef..187ef28c4d 100644 --- a/app/Api/V1/Controllers/Data/Export/ExportController.php +++ b/app/Api/V1/Controllers/Data/Export/ExportController.php @@ -57,7 +57,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportAccounts * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -67,11 +67,10 @@ class ExportController extends Controller $this->exporter->setExportAccounts(true); return $this->returnExport('accounts'); - } /** - * @param string $key + * @param string $key * * @return LaravelResponse * @throws FireflyException @@ -87,13 +86,13 @@ class ExportController extends Controller $response ->header('Content-Description', 'File Transfer') ->header('Content-Type', 'application/octet-stream') - ->header('Content-Disposition', 'attachment; filename=' . $fileName) + ->header('Content-Disposition', 'attachment; filename='.$fileName) ->header('Content-Transfer-Encoding', 'binary') ->header('Connection', 'Keep-Alive') ->header('Expires', '0') ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') ->header('Pragma', 'public') - ->header('Content-Length', (string) strlen($data[$key])); + ->header('Content-Length', (string)strlen($data[$key])); return $response; } @@ -102,7 +101,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportBills * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -118,7 +117,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportBudgets * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -134,7 +133,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportCategories * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -150,7 +149,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportPiggies * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -166,7 +165,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportRecurring * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -182,7 +181,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportRules * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -198,7 +197,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportTags * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -214,7 +213,7 @@ class ExportController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/data/exportTransactions * - * @param ExportRequest $request + * @param ExportRequest $request * * @return LaravelResponse * @throws FireflyException @@ -229,5 +228,4 @@ class ExportController extends Controller return $this->returnExport('transactions'); } - } diff --git a/app/Api/V1/Controllers/Data/PurgeController.php b/app/Api/V1/Controllers/Data/PurgeController.php new file mode 100644 index 0000000000..b8db2215b6 --- /dev/null +++ b/app/Api/V1/Controllers/Data/PurgeController.php @@ -0,0 +1,93 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V1\Controllers\Data; + +use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Models\Account; +use FireflyIII\Models\Bill; +use FireflyIII\Models\Budget; +use FireflyIII\Models\Category; +use FireflyIII\Models\PiggyBank; +use FireflyIII\Models\Recurrence; +use FireflyIII\Models\Rule; +use FireflyIII\Models\RuleGroup; +use FireflyIII\Models\Tag; +use FireflyIII\Models\TransactionGroup; +use FireflyIII\Models\TransactionJournal; +use Illuminate\Http\JsonResponse; + +class PurgeController extends Controller +{ + /** + * @return JsonResponse + */ + public function purge(): JsonResponse + { + $user = auth()->user(); + + // some manual code, too lazy to call all repositories. + //,transactions,withdrawals,deposits,transfers'; + + // budgets: + Budget::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + // bills + Bill::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + // piggies + $set = PiggyBank::leftJoin('accounts', 'accounts.id', 'piggy_banks.account_id') + ->where('accounts.user_id', $user->id)->onlyTrashed()->get(['piggy_banks.*']); + /** @var PiggyBank $piggy */ + foreach ($set as $piggy) { + $piggy->forceDelete(); + } + + // rule group + RuleGroup::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + // rules + Rule::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + // recurring transactions + Recurrence::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + // categories + Category::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + // tags + Tag::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + + // accounts + Account::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + // transaction groups + TransactionGroup::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + // transaction journals + TransactionJournal::whereUserId($user->id)->onlyTrashed()->forceDelete(); + + return response()->json([], 204); + } +} diff --git a/app/Api/V1/Controllers/Insight/Expense/AccountController.php b/app/Api/V1/Controllers/Insight/Expense/AccountController.php index 5cf8835f90..1f9510e262 100644 --- a/app/Api/V1/Controllers/Insight/Expense/AccountController.php +++ b/app/Api/V1/Controllers/Insight/Expense/AccountController.php @@ -76,7 +76,7 @@ class AccountController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightExpenseAsset * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -91,11 +91,11 @@ class AccountController extends Controller /** @var array $expense */ foreach ($expenses as $expense) { $result[] = [ - 'id' => (string) $expense['id'], + 'id' => (string)$expense['id'], 'name' => $expense['name'], 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], // intentional float - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], // intentional float + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } @@ -107,7 +107,7 @@ class AccountController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightExpenseExpense * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -123,16 +123,15 @@ class AccountController extends Controller /** @var array $expense */ foreach ($expenses as $expense) { $result[] = [ - 'id' => (string) $expense['id'], + 'id' => (string)$expense['id'], 'name' => $expense['name'], 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], // intentional float - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], // intentional float + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } return response()->json($result); } - } diff --git a/app/Api/V1/Controllers/Insight/Expense/BillController.php b/app/Api/V1/Controllers/Insight/Expense/BillController.php index 9b4872b84f..84b40d3ba2 100644 --- a/app/Api/V1/Controllers/Insight/Expense/BillController.php +++ b/app/Api/V1/Controllers/Insight/Expense/BillController.php @@ -61,7 +61,7 @@ class BillController extends Controller * * Expenses per bill, possibly filtered by bill and account. * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -85,33 +85,33 @@ class BillController extends Controller $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { - $billId = (int) $journal['bill_id']; - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $billId = (int)$journal['bill_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; $key = sprintf('%d-%d', $billId, $currencyId); $foreignKey = sprintf('%d-%d', $billId, $foreignCurrencyId); if (0 !== $currencyId) { $response[$key] = $response[$key] ?? [ - 'id' => (string) $billId, - 'name' => $journal['bill_name'], - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'id' => (string)$billId, + 'name' => $journal['bill_name'], + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$key]['difference'] = bcadd($response[$key]['difference'], $journal['amount']); - $response[$key]['difference_float'] = (float) $response[$key]['difference']; // intentional float + $response[$key]['difference_float'] = (float)$response[$key]['difference']; // intentional float } if (0 !== $foreignCurrencyId) { $response[$foreignKey] = $response[$foreignKey] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignKey]['difference'] = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']); - $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float + $response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // intentional float } } @@ -124,7 +124,7 @@ class BillController extends Controller * * Expenses for no bill filtered by account. * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -143,32 +143,31 @@ class BillController extends Controller $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; if (0 !== $currencyId) { $response[$currencyId] = $response[$currencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']); - $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float + $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // intentional float } if (0 !== $foreignCurrencyId) { $response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']); - $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // intentional float + $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // intentional float } } return response()->json(array_values($response)); } - } diff --git a/app/Api/V1/Controllers/Insight/Expense/BudgetController.php b/app/Api/V1/Controllers/Insight/Expense/BudgetController.php index cc9fc38593..fc0578a002 100644 --- a/app/Api/V1/Controllers/Insight/Expense/BudgetController.php +++ b/app/Api/V1/Controllers/Insight/Expense/BudgetController.php @@ -68,7 +68,7 @@ class BudgetController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightExpenseBudget * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -88,11 +88,11 @@ class BudgetController extends Controller /** @var array $expense */ foreach ($expenses as $expense) { $result[] = [ - 'id' => (string) $budget->id, + 'id' => (string)$budget->id, 'name' => $budget->name, 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], // intentional float - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], // intentional float + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } @@ -105,7 +105,7 @@ class BudgetController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightExpenseNoBudget * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -120,14 +120,12 @@ class BudgetController extends Controller foreach ($expenses as $expense) { $result[] = [ 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], // intentional float - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], // intentional float + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } return response()->json($result); - } - } diff --git a/app/Api/V1/Controllers/Insight/Expense/CategoryController.php b/app/Api/V1/Controllers/Insight/Expense/CategoryController.php index 121c45d635..32a60c321f 100644 --- a/app/Api/V1/Controllers/Insight/Expense/CategoryController.php +++ b/app/Api/V1/Controllers/Insight/Expense/CategoryController.php @@ -69,7 +69,7 @@ class CategoryController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightTransferCategory * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -89,11 +89,11 @@ class CategoryController extends Controller /** @var array $expense */ foreach ($expenses as $expense) { $result[] = [ - 'id' => (string) $category->id, + 'id' => (string)$category->id, 'name' => $category->name, 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], // intentional float - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], // intentional float + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } @@ -106,7 +106,7 @@ class CategoryController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightTransferNoCategory * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -121,13 +121,12 @@ class CategoryController extends Controller foreach ($expenses as $expense) { $result[] = [ 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], // intentional float - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], // intentional float + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } return response()->json($result); - } } diff --git a/app/Api/V1/Controllers/Insight/Expense/PeriodController.php b/app/Api/V1/Controllers/Insight/Expense/PeriodController.php index 4a7e321cf4..4a97dea7bb 100644 --- a/app/Api/V1/Controllers/Insight/Expense/PeriodController.php +++ b/app/Api/V1/Controllers/Insight/Expense/PeriodController.php @@ -34,12 +34,11 @@ use Illuminate\Http\JsonResponse; */ class PeriodController extends Controller { - /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightExpenseTotal * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -55,32 +54,31 @@ class PeriodController extends Controller $collector->setTypes([TransactionType::WITHDRAWAL])->setRange($start, $end)->setSourceAccounts($accounts); $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; if (0 !== $currencyId) { $response[$currencyId] = $response[$currencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']); - $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; // intentional float + $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // intentional float } if (0 !== $foreignCurrencyId) { $response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']); - $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; // intentional float + $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // intentional float } } return response()->json(array_values($response)); } - } diff --git a/app/Api/V1/Controllers/Insight/Expense/TagController.php b/app/Api/V1/Controllers/Insight/Expense/TagController.php index 9ea0a0fa04..76aa7bd795 100644 --- a/app/Api/V1/Controllers/Insight/Expense/TagController.php +++ b/app/Api/V1/Controllers/Insight/Expense/TagController.php @@ -60,7 +60,7 @@ class TagController extends Controller * * Expenses for no tag filtered by account. * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -79,28 +79,28 @@ class TagController extends Controller $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; if (0 !== $currencyId) { $response[$currencyId] = $response[$currencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], $journal['amount']); - $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; + $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // float but on purpose. } if (0 !== $foreignCurrencyId) { $response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignCurrencyId]['difference'] = bcadd($response[$foreignCurrencyId]['difference'], $journal['foreign_amount']); - $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; + $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose. } } @@ -113,7 +113,7 @@ class TagController extends Controller * * Expenses per tag, possibly filtered by tag and account. * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -137,8 +137,8 @@ class TagController extends Controller $genericSet = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; /** @var array $tag */ foreach ($journal['tags'] as $tag) { @@ -149,32 +149,31 @@ class TagController extends Controller // on currency ID if (0 !== $currencyId) { $response[$key] = $response[$key] ?? [ - 'id' => (string) $tagId, - 'name' => $tag['name'], - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'id' => (string)$tagId, + 'name' => $tag['name'], + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$key]['difference'] = bcadd($response[$key]['difference'], $journal['amount']); - $response[$key]['difference_float'] = (float) $response[$key]['difference']; + $response[$key]['difference_float'] = (float)$response[$key]['difference']; // float but on purpose. } // on foreign ID if (0 !== $foreignCurrencyId) { $response[$foreignKey] = $journal[$foreignKey] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignKey]['difference'] = bcadd($response[$foreignKey]['difference'], $journal['foreign_amount']); - $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; + $response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // float but on purpose. } } } return response()->json(array_values($response)); } - } diff --git a/app/Api/V1/Controllers/Insight/Income/AccountController.php b/app/Api/V1/Controllers/Insight/Income/AccountController.php index ecad08b6b4..4ea6a591cc 100644 --- a/app/Api/V1/Controllers/Insight/Income/AccountController.php +++ b/app/Api/V1/Controllers/Insight/Income/AccountController.php @@ -76,7 +76,7 @@ class AccountController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightIncomeAsset * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -90,11 +90,11 @@ class AccountController extends Controller /** @var array $entry */ foreach ($income as $entry) { $result[] = [ - 'id' => (string) $entry['id'], + 'id' => (string)$entry['id'], 'name' => $entry['name'], 'difference' => $entry['sum'], - 'difference_float' => (float) $entry['sum'], - 'currency_id' => (string) $entry['currency_id'], + 'difference_float' => (float)$entry['sum'], // float but on purpose. + 'currency_id' => (string)$entry['currency_id'], 'currency_code' => $entry['currency_code'], ]; } @@ -106,7 +106,7 @@ class AccountController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightIncomeRevenue * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -122,16 +122,15 @@ class AccountController extends Controller /** @var array $entry */ foreach ($income as $entry) { $result[] = [ - 'id' => (string) $entry['id'], + 'id' => (string)$entry['id'], 'name' => $entry['name'], 'difference' => $entry['sum'], - 'difference_float' => (float) $entry['sum'], - 'currency_id' => (string) $entry['currency_id'], + 'difference_float' => (float)$entry['sum'], // float but on purpose. + 'currency_id' => (string)$entry['currency_id'], 'currency_code' => $entry['currency_code'], ]; } return response()->json($result); } - } diff --git a/app/Api/V1/Controllers/Insight/Income/CategoryController.php b/app/Api/V1/Controllers/Insight/Income/CategoryController.php index 79f0c4bf79..898bcac9c7 100644 --- a/app/Api/V1/Controllers/Insight/Income/CategoryController.php +++ b/app/Api/V1/Controllers/Insight/Income/CategoryController.php @@ -69,7 +69,7 @@ class CategoryController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightIncomeCategory * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -89,11 +89,11 @@ class CategoryController extends Controller /** @var array $expense */ foreach ($expenses as $expense) { $result[] = [ - 'id' => (string) $category->id, + 'id' => (string)$category->id, 'name' => $category->name, 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], // float but on purpose. + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } @@ -106,7 +106,7 @@ class CategoryController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightIncomeNoCategory * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -121,13 +121,12 @@ class CategoryController extends Controller foreach ($expenses as $expense) { $result[] = [ 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], // float but on purpose. + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } return response()->json($result); - } } diff --git a/app/Api/V1/Controllers/Insight/Income/PeriodController.php b/app/Api/V1/Controllers/Insight/Income/PeriodController.php index 41aa682337..e748b4a5db 100644 --- a/app/Api/V1/Controllers/Insight/Income/PeriodController.php +++ b/app/Api/V1/Controllers/Insight/Income/PeriodController.php @@ -34,12 +34,11 @@ use Illuminate\Http\JsonResponse; */ class PeriodController extends Controller { - /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightIncomeTotal * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -55,34 +54,34 @@ class PeriodController extends Controller $collector->setTypes([TransactionType::DEPOSIT])->setRange($start, $end)->setDestinationAccounts($accounts); $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; if (0 !== $currencyId) { $response[$currencyId] = $response[$currencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount'])); - $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; + $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; // float but on purpose. } if (0 !== $foreignCurrencyId) { $response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignCurrencyId]['difference'] = bcadd( - $response[$foreignCurrencyId]['difference'], app('steam')->positive($journal['foreign_amount']) + $response[$foreignCurrencyId]['difference'], + app('steam')->positive($journal['foreign_amount']) ); - $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; + $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; // float but on purpose. } } return response()->json(array_values($response)); } - } diff --git a/app/Api/V1/Controllers/Insight/Income/TagController.php b/app/Api/V1/Controllers/Insight/Income/TagController.php index 10ea364f8c..31e61ade91 100644 --- a/app/Api/V1/Controllers/Insight/Income/TagController.php +++ b/app/Api/V1/Controllers/Insight/Income/TagController.php @@ -61,7 +61,7 @@ class TagController extends Controller * * Expenses for no tag filtered by account. * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -80,30 +80,31 @@ class TagController extends Controller $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; if (0 !== $currencyId) { $response[$currencyId] = $response[$currencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount'])); - $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; + $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; } if (0 !== $foreignCurrencyId) { $response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignCurrencyId]['difference'] = bcadd( - $response[$foreignCurrencyId]['difference'], app('steam')->positive($journal['foreign_amount']) + $response[$foreignCurrencyId]['difference'], + app('steam')->positive($journal['foreign_amount']) ); - $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; + $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; } } @@ -116,7 +117,7 @@ class TagController extends Controller * * Expenses per tag, possibly filtered by tag and account. * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -140,8 +141,8 @@ class TagController extends Controller $genericSet = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; /** @var array $tag */ foreach ($journal['tags'] as $tag) { @@ -152,34 +153,34 @@ class TagController extends Controller // on currency ID if (0 !== $currencyId) { $response[$key] = $response[$key] ?? [ - 'id' => (string) $tagId, - 'name' => $tag['name'], - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'id' => (string)$tagId, + 'name' => $tag['name'], + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$key]['difference'] = bcadd($response[$key]['difference'], app('steam')->positive($journal['amount'])); - $response[$key]['difference_float'] = (float) $response[$key]['difference']; + $response[$key]['difference_float'] = (float)$response[$key]['difference']; } // on foreign ID if (0 !== $foreignCurrencyId) { $response[$foreignKey] = $journal[$foreignKey] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignKey]['difference'] = bcadd( - $response[$foreignKey]['difference'], app('steam')->positive($journal['foreign_amount']) + $response[$foreignKey]['difference'], + app('steam')->positive($journal['foreign_amount']) ); - $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; + $response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; } } } return response()->json(array_values($response)); } - } diff --git a/app/Api/V1/Controllers/Insight/Transfer/AccountController.php b/app/Api/V1/Controllers/Insight/Transfer/AccountController.php index 19dc00a0fc..451bc60c5a 100644 --- a/app/Api/V1/Controllers/Insight/Transfer/AccountController.php +++ b/app/Api/V1/Controllers/Insight/Transfer/AccountController.php @@ -61,7 +61,7 @@ class AccountController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightTransfers * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Insight/Transfer/CategoryController.php b/app/Api/V1/Controllers/Insight/Transfer/CategoryController.php index d42772f9be..93e24ee0d0 100644 --- a/app/Api/V1/Controllers/Insight/Transfer/CategoryController.php +++ b/app/Api/V1/Controllers/Insight/Transfer/CategoryController.php @@ -68,7 +68,7 @@ class CategoryController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightTransferCategory * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -88,11 +88,11 @@ class CategoryController extends Controller /** @var array $expense */ foreach ($expenses as $expense) { $result[] = [ - 'id' => (string) $category->id, + 'id' => (string)$category->id, 'name' => $category->name, 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } @@ -105,7 +105,7 @@ class CategoryController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightTransferNoCategory * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -120,13 +120,12 @@ class CategoryController extends Controller foreach ($expenses as $expense) { $result[] = [ 'difference' => $expense['sum'], - 'difference_float' => (float) $expense['sum'], - 'currency_id' => (string) $expense['currency_id'], + 'difference_float' => (float)$expense['sum'], + 'currency_id' => (string)$expense['currency_id'], 'currency_code' => $expense['currency_code'], ]; } return response()->json($result); - } } diff --git a/app/Api/V1/Controllers/Insight/Transfer/PeriodController.php b/app/Api/V1/Controllers/Insight/Transfer/PeriodController.php index 8f8eab7428..7f57c15593 100644 --- a/app/Api/V1/Controllers/Insight/Transfer/PeriodController.php +++ b/app/Api/V1/Controllers/Insight/Transfer/PeriodController.php @@ -34,12 +34,11 @@ use Illuminate\Http\JsonResponse; */ class PeriodController extends Controller { - /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightTransferTotal * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -55,34 +54,34 @@ class PeriodController extends Controller $collector->setTypes([TransactionType::TRANSFER])->setRange($start, $end)->setDestinationAccounts($accounts); $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; if (0 !== $currencyId) { $response[$currencyId] = $response[$currencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount'])); - $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; + $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; } if (0 !== $foreignCurrencyId) { $response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignCurrencyId]['difference'] = bcadd( - $response[$foreignCurrencyId]['difference'], app('steam')->positive($journal['foreign_amount']) + $response[$foreignCurrencyId]['difference'], + app('steam')->positive($journal['foreign_amount']) ); - $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; + $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; } } return response()->json(array_values($response)); } - } diff --git a/app/Api/V1/Controllers/Insight/Transfer/TagController.php b/app/Api/V1/Controllers/Insight/Transfer/TagController.php index bae49e777c..78d5b5e282 100644 --- a/app/Api/V1/Controllers/Insight/Transfer/TagController.php +++ b/app/Api/V1/Controllers/Insight/Transfer/TagController.php @@ -58,7 +58,7 @@ class TagController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/insight/insightTransferNoTag * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -77,30 +77,31 @@ class TagController extends Controller $genericSet = $collector->getExtractedJournals(); foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; if (0 !== $currencyId) { $response[$currencyId] = $response[$currencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$currencyId]['difference'] = bcadd($response[$currencyId]['difference'], app('steam')->positive($journal['amount'])); - $response[$currencyId]['difference_float'] = (float) $response[$currencyId]['difference']; + $response[$currencyId]['difference_float'] = (float)$response[$currencyId]['difference']; } if (0 !== $foreignCurrencyId) { $response[$foreignCurrencyId] = $response[$foreignCurrencyId] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignCurrencyId]['difference'] = bcadd( - $response[$foreignCurrencyId]['difference'], app('steam')->positive($journal['foreign_amount']) + $response[$foreignCurrencyId]['difference'], + app('steam')->positive($journal['foreign_amount']) ); - $response[$foreignCurrencyId]['difference_float'] = (float) $response[$foreignCurrencyId]['difference']; + $response[$foreignCurrencyId]['difference_float'] = (float)$response[$foreignCurrencyId]['difference']; } } @@ -113,7 +114,7 @@ class TagController extends Controller * * Transfers per tag, possibly filtered by tag and account. * - * @param GenericRequest $request + * @param GenericRequest $request * * @return JsonResponse */ @@ -137,8 +138,8 @@ class TagController extends Controller $genericSet = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($genericSet as $journal) { - $currencyId = (int) $journal['currency_id']; - $foreignCurrencyId = (int) $journal['foreign_currency_id']; + $currencyId = (int)$journal['currency_id']; + $foreignCurrencyId = (int)$journal['foreign_currency_id']; /** @var array $tag */ foreach ($journal['tags'] as $tag) { @@ -149,29 +150,30 @@ class TagController extends Controller // on currency ID if (0 !== $currencyId) { $response[$key] = $response[$key] ?? [ - 'id' => (string) $tagId, - 'name' => $tag['name'], - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'id' => (string)$tagId, + 'name' => $tag['name'], + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; $response[$key]['difference'] = bcadd($response[$key]['difference'], app('steam')->positive($journal['amount'])); - $response[$key]['difference_float'] = (float) $response[$key]['difference']; + $response[$key]['difference_float'] = (float)$response[$key]['difference']; } // on foreign ID if (0 !== $foreignCurrencyId) { $response[$foreignKey] = $journal[$foreignKey] ?? [ - 'difference' => '0', - 'difference_float' => 0, - 'currency_id' => (string) $foreignCurrencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'difference' => '0', + 'difference_float' => 0, + 'currency_id' => (string)$foreignCurrencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; $response[$foreignKey]['difference'] = bcadd( - $response[$foreignKey]['difference'], app('steam')->positive($journal['foreign_amount']) + $response[$foreignKey]['difference'], + app('steam')->positive($journal['foreign_amount']) ); - $response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float + $response[$foreignKey]['difference_float'] = (float)$response[$foreignKey]['difference']; // intentional float } } } diff --git a/app/Api/V1/Controllers/Models/Account/DestroyController.php b/app/Api/V1/Controllers/Models/Account/DestroyController.php index 739a65fec2..5430bd68df 100644 --- a/app/Api/V1/Controllers/Models/Account/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Account/DestroyController.php @@ -61,7 +61,7 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param Account $account + * @param Account $account * * @codeCoverageIgnore * @return JsonResponse diff --git a/app/Api/V1/Controllers/Models/Account/ListController.php b/app/Api/V1/Controllers/Models/Account/ListController.php index a56131a639..866779725a 100644 --- a/app/Api/V1/Controllers/Models/Account/ListController.php +++ b/app/Api/V1/Controllers/Models/Account/ListController.php @@ -73,7 +73,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/accounts/listAttachmentByAccount * - * @param Account $account + * @param Account $account * * @return JsonResponse * @codeCoverageIgnore @@ -82,7 +82,7 @@ class ListController extends Controller public function attachments(Account $account): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getAttachments($account); $count = $collection->count(); @@ -90,7 +90,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.accounts.attachments', [$account->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.accounts.attachments', [$account->id]).$this->buildParams()); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -106,7 +106,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/accounts/listPiggyBankByAccount * - * @param Account $account + * @param Account $account * * @return JsonResponse * @throws FireflyException @@ -118,7 +118,7 @@ class ListController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->repository->getPiggyBanks($account); @@ -127,7 +127,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.accounts.piggy_banks', [$account->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.accounts.piggy_banks', [$account->id]).$this->buildParams()); /** @var PiggyBankTransformer $transformer */ $transformer = app(PiggyBankTransformer::class); @@ -137,7 +137,6 @@ class ListController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -148,15 +147,15 @@ class ListController extends Controller * * @codeCoverageIgnore * - * @param Request $request - * @param Account $account + * @param Request $request + * @param Account $account * * @return JsonResponse * @throws FireflyException */ public function transactions(Request $request, Account $account): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -181,7 +180,7 @@ class ListController extends Controller } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.accounts.transactions', [$account->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.accounts.transactions', [$account->id]).$this->buildParams()); $groups = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ diff --git a/app/Api/V1/Controllers/Models/Account/ShowController.php b/app/Api/V1/Controllers/Models/Account/ShowController.php index 3ad5c13933..f251faaf4f 100644 --- a/app/Api/V1/Controllers/Models/Account/ShowController.php +++ b/app/Api/V1/Controllers/Models/Account/ShowController.php @@ -71,7 +71,7 @@ class ShowController extends Controller * * Display a listing of the resource. * - * @param Request $request + * @param Request $request * * @return JsonResponse * @throws FireflyException @@ -85,7 +85,7 @@ class ShowController extends Controller // types to get, page size: $types = $this->mapAccountTypes($this->parameters->get('type')); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of accounts. Count it and split it. $this->repository->resetAccountOrder(); @@ -99,7 +99,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.accounts.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.accounts.index').$this->buildParams()); /** @var AccountTransformer $transformer */ $transformer = app(AccountTransformer::class); @@ -117,7 +117,7 @@ class ShowController extends Controller * * Show single instance. * - * @param Account $account + * @param Account $account * * @return JsonResponse */ @@ -135,5 +135,4 @@ class ShowController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/Account/StoreController.php b/app/Api/V1/Controllers/Models/Account/StoreController.php index c18f94be4c..0e4d530018 100644 --- a/app/Api/V1/Controllers/Models/Account/StoreController.php +++ b/app/Api/V1/Controllers/Models/Account/StoreController.php @@ -63,7 +63,7 @@ class StoreController extends Controller * * Store a new instance. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse */ @@ -82,5 +82,4 @@ class StoreController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/Account/UpdateController.php b/app/Api/V1/Controllers/Models/Account/UpdateController.php index 65221bbeda..5c90221b79 100644 --- a/app/Api/V1/Controllers/Models/Account/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Account/UpdateController.php @@ -66,8 +66,8 @@ class UpdateController extends Controller * * Update account. * - * @param UpdateRequest $request - * @param Account $account + * @param UpdateRequest $request + * @param Account $account * * @return JsonResponse */ @@ -75,7 +75,7 @@ class UpdateController extends Controller { Log::debug(sprintf('Now in %s', __METHOD__)); $data = $request->getUpdateData(); - $data['type'] = config('firefly.shortNamesByFullName.' . $account->accountType->type); + $data['type'] = config('firefly.shortNamesByFullName.'.$account->accountType->type); $account = $this->repository->update($account, $data); $manager = $this->getManager(); $account->refresh(); diff --git a/app/Api/V1/Controllers/Models/Attachment/DestroyController.php b/app/Api/V1/Controllers/Models/Attachment/DestroyController.php index 4150728688..287f621df8 100644 --- a/app/Api/V1/Controllers/Models/Attachment/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Attachment/DestroyController.php @@ -66,7 +66,7 @@ class DestroyController extends Controller * * @codeCoverageIgnore * - * @param Attachment $attachment + * @param Attachment $attachment * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/Attachment/ShowController.php b/app/Api/V1/Controllers/Models/Attachment/ShowController.php index 55537851c8..aacb5b461f 100644 --- a/app/Api/V1/Controllers/Models/Attachment/ShowController.php +++ b/app/Api/V1/Controllers/Models/Attachment/ShowController.php @@ -71,7 +71,7 @@ class ShowController extends Controller * * Download an attachment. * - * @param Attachment $attachment + * @param Attachment $attachment * * @codeCoverageIgnore * @return LaravelResponse @@ -97,13 +97,13 @@ class ShowController extends Controller $response ->header('Content-Description', 'File Transfer') ->header('Content-Type', 'application/octet-stream') - ->header('Content-Disposition', 'attachment; filename=' . $quoted) + ->header('Content-Disposition', 'attachment; filename='.$quoted) ->header('Content-Transfer-Encoding', 'binary') ->header('Connection', 'Keep-Alive') ->header('Expires', '0') ->header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') ->header('Pragma', 'public') - ->header('Content-Length', (string) strlen($content)); + ->header('Content-Length', (string)strlen($content)); return $response; } @@ -125,7 +125,7 @@ class ShowController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of attachments. Count it and split it. $collection = $this->repository->get(); @@ -134,7 +134,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.attachments.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.attachments.index').$this->buildParams()); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -152,7 +152,7 @@ class ShowController extends Controller * * Display the specified resource. * - * @param Attachment $attachment + * @param Attachment $attachment * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/Attachment/StoreController.php b/app/Api/V1/Controllers/Models/Attachment/StoreController.php index 2469b68938..8fd517f65c 100644 --- a/app/Api/V1/Controllers/Models/Attachment/StoreController.php +++ b/app/Api/V1/Controllers/Models/Attachment/StoreController.php @@ -71,7 +71,7 @@ class StoreController extends Controller * * Store a newly created resource in storage. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException @@ -97,8 +97,8 @@ class StoreController extends Controller * * @codeCoverageIgnore * - * @param Request $request - * @param Attachment $attachment + * @param Request $request + * @param Attachment $attachment * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/Attachment/UpdateController.php b/app/Api/V1/Controllers/Models/Attachment/UpdateController.php index f5d350b1e4..fc33e64d85 100644 --- a/app/Api/V1/Controllers/Models/Attachment/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Attachment/UpdateController.php @@ -67,8 +67,8 @@ class UpdateController extends Controller * * Update the specified resource in storage. * - * @param UpdateRequest $request - * @param Attachment $attachment + * @param UpdateRequest $request + * @param Attachment $attachment * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/AvailableBudget/DestroyController.php b/app/Api/V1/Controllers/Models/AvailableBudget/DestroyController.php deleted file mode 100644 index f3c5faab6e..0000000000 --- a/app/Api/V1/Controllers/Models/AvailableBudget/DestroyController.php +++ /dev/null @@ -1,78 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V1\Controllers\Models\AvailableBudget; - -use FireflyIII\Api\V1\Controllers\Controller; -use FireflyIII\Models\AvailableBudget; -use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; -use FireflyIII\User; -use Illuminate\Http\JsonResponse; - -/** - * Class DestroyController - */ -class DestroyController extends Controller -{ - private AvailableBudgetRepositoryInterface $abRepository; - - /** - * AvailableBudgetController constructor. - * - * @codeCoverageIgnore - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - /** @var User $user */ - $user = auth()->user(); - $this->abRepository = app(AvailableBudgetRepositoryInterface::class); - $this->abRepository->setUser($user); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/#/available_budgets/listAvailableBudget - * - * Remove the specified resource from storage. - * - * @param AvailableBudget $availableBudget - * - * @codeCoverageIgnore - * - * @return JsonResponse - */ - public function destroy(AvailableBudget $availableBudget): JsonResponse - { - $this->abRepository->destroyAvailableBudget($availableBudget); - app('preferences')->mark(); - - return response()->json([], 204); - } -} diff --git a/app/Api/V1/Controllers/Models/AvailableBudget/ShowController.php b/app/Api/V1/Controllers/Models/AvailableBudget/ShowController.php index 210648d109..fef07373de 100644 --- a/app/Api/V1/Controllers/Models/AvailableBudget/ShowController.php +++ b/app/Api/V1/Controllers/Models/AvailableBudget/ShowController.php @@ -77,7 +77,7 @@ class ShowController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $start = $this->parameters->get('start'); $end = $this->parameters->get('end'); @@ -89,7 +89,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.available_budgets.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.available_budgets.index').$this->buildParams()); /** @var AvailableBudgetTransformer $transformer */ $transformer = app(AvailableBudgetTransformer::class); @@ -107,7 +107,7 @@ class ShowController extends Controller * * Display the specified resource. * - * @param AvailableBudget $availableBudget + * @param AvailableBudget $availableBudget * * @return JsonResponse * @codeCoverageIgnore @@ -124,5 +124,4 @@ class ShowController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/AvailableBudget/StoreController.php b/app/Api/V1/Controllers/Models/AvailableBudget/StoreController.php deleted file mode 100644 index 38deff3b1f..0000000000 --- a/app/Api/V1/Controllers/Models/AvailableBudget/StoreController.php +++ /dev/null @@ -1,105 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V1\Controllers\Models\AvailableBudget; - -use FireflyIII\Api\V1\Controllers\Controller; -use FireflyIII\Api\V1\Requests\Models\AvailableBudget\Request; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Factory\TransactionCurrencyFactory; -use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; -use FireflyIII\Transformers\AvailableBudgetTransformer; -use FireflyIII\User; -use Illuminate\Http\JsonResponse; -use JsonException; -use League\Fractal\Resource\Item; - -/** - * Class StoreController - */ -class StoreController extends Controller -{ - private AvailableBudgetRepositoryInterface $abRepository; - - /** - * AvailableBudgetController constructor. - * - * @codeCoverageIgnore - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - /** @var User $user */ - $user = auth()->user(); - $this->abRepository = app(AvailableBudgetRepositoryInterface::class); - $this->abRepository->setUser($user); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/#/available_budgets/storeAvailableBudget - * - * Store a newly created resource in storage. - * - * @param Request $request - * - * @return JsonResponse - * @throws FireflyException - * @throws JsonException - */ - public function store(Request $request): JsonResponse - { - $data = $request->getAll(); - $data['start']->startOfDay(); - $data['end']->endOfDay(); - - // currency is not mandatory: - if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { - $factory = app(TransactionCurrencyFactory::class); - $currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null); - $data['currency_id'] = $currency->id; - unset($data['currency_code']); - } - if (!array_key_exists('currency_id', $data)) { - $currency = app('amount')->getDefaultCurrencyByUser(auth()->user()); - $data['currency_id'] = $currency->id; - } - - $availableBudget = $this->abRepository->store($data); - $manager = $this->getManager(); - - /** @var AvailableBudgetTransformer $transformer */ - $transformer = app(AvailableBudgetTransformer::class); - $transformer->setParameters($this->parameters); - - $resource = new Item($availableBudget, $transformer, 'available_budgets'); - - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } -} diff --git a/app/Api/V1/Controllers/Models/AvailableBudget/UpdateController.php b/app/Api/V1/Controllers/Models/AvailableBudget/UpdateController.php deleted file mode 100644 index bb0969260c..0000000000 --- a/app/Api/V1/Controllers/Models/AvailableBudget/UpdateController.php +++ /dev/null @@ -1,100 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Api\V1\Controllers\Models\AvailableBudget; - -use FireflyIII\Api\V1\Controllers\Controller; -use FireflyIII\Api\V1\Requests\Models\AvailableBudget\Request; -use FireflyIII\Factory\TransactionCurrencyFactory; -use FireflyIII\Models\AvailableBudget; -use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; -use FireflyIII\Transformers\AvailableBudgetTransformer; -use FireflyIII\User; -use Illuminate\Http\JsonResponse; -use League\Fractal\Resource\Item; - -/** - * Class UpdateController - */ -class UpdateController extends Controller -{ - private AvailableBudgetRepositoryInterface $abRepository; - - /** - * AvailableBudgetController constructor. - * - * @codeCoverageIgnore - */ - public function __construct() - { - parent::__construct(); - $this->middleware( - function ($request, $next) { - /** @var User $user */ - $user = auth()->user(); - $this->abRepository = app(AvailableBudgetRepositoryInterface::class); - $this->abRepository->setUser($user); - - return $next($request); - } - ); - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/#/available_budgets/updateAvailableBudget - * - * Update the specified resource in storage. - * - * @param Request $request - * @param AvailableBudget $availableBudget - * - * @return JsonResponse - */ - public function update(Request $request, AvailableBudget $availableBudget): JsonResponse - { - $data = $request->getAll(); - - // find and validate currency ID - if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { - $factory = app(TransactionCurrencyFactory::class); - $currency = $factory->find($data['currency_id'] ?? null, $data['currency_code'] ?? null) ?? app('amount')->getDefaultCurrency(); - $currency->enabled = true; - $currency->save(); - unset($data['currency_code']); - $data['currency_id'] = $currency->id; - } - - $this->abRepository->updateAvailableBudget($availableBudget, $data); - $manager = $this->getManager(); - - /** @var AvailableBudgetTransformer $transformer */ - $transformer = app(AvailableBudgetTransformer::class); - $transformer->setParameters($this->parameters); - - $resource = new Item($availableBudget, $transformer, 'available_budgets'); - - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - - } -} diff --git a/app/Api/V1/Controllers/Models/Bill/DestroyController.php b/app/Api/V1/Controllers/Models/Bill/DestroyController.php index b3a375f3b3..bffce79962 100644 --- a/app/Api/V1/Controllers/Models/Bill/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Bill/DestroyController.php @@ -59,7 +59,7 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param Bill $bill + * @param Bill $bill * * @return JsonResponse * @codeCoverageIgnore @@ -71,5 +71,4 @@ class DestroyController extends Controller return response()->json([], 204); } - } diff --git a/app/Api/V1/Controllers/Models/Bill/ListController.php b/app/Api/V1/Controllers/Models/Bill/ListController.php index 686277b718..eb39fff345 100644 --- a/app/Api/V1/Controllers/Models/Bill/ListController.php +++ b/app/Api/V1/Controllers/Models/Bill/ListController.php @@ -72,7 +72,7 @@ class ListController extends Controller * * Display a listing of the resource. * - * @param Bill $bill + * @param Bill $bill * * @return JsonResponse * @throws FireflyException @@ -81,7 +81,7 @@ class ListController extends Controller public function attachments(Bill $bill): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getAttachments($bill); $count = $collection->count(); @@ -89,7 +89,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.bills.attachments', [$bill->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.bills.attachments', [$bill->id]).$this->buildParams()); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -107,7 +107,7 @@ class ListController extends Controller * * List all of them. * - * @param Bill $bill + * @param Bill $bill * * @return JsonResponse * @throws FireflyException @@ -118,7 +118,7 @@ class ListController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->repository->getRulesForBill($bill); @@ -127,7 +127,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.bills.rules', [$bill->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.bills.rules', [$bill->id]).$this->buildParams()); /** @var RuleTransformer $transformer */ $transformer = app(RuleTransformer::class); @@ -136,7 +136,6 @@ class ListController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -145,9 +144,9 @@ class ListController extends Controller * * Show all transactions. * - * @param Request $request + * @param Request $request * - * @param Bill $bill + * @param Bill $bill * * @return JsonResponse * @throws FireflyException @@ -155,7 +154,7 @@ class ListController extends Controller */ public function transactions(Request $request, Bill $bill): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -188,7 +187,7 @@ class ListController extends Controller // get paginator. $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.bills.transactions', [$bill->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.bills.transactions', [$bill->id]).$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ @@ -200,5 +199,4 @@ class ListController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/Bill/ShowController.php b/app/Api/V1/Controllers/Models/Bill/ShowController.php index 2fba6af816..43bd076f5a 100644 --- a/app/Api/V1/Controllers/Models/Bill/ShowController.php +++ b/app/Api/V1/Controllers/Models/Bill/ShowController.php @@ -74,7 +74,7 @@ class ShowController extends Controller $this->repository->correctOrder(); $bills = $this->repository->getBills(); $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $count = $bills->count(); $bills = $bills->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); @@ -95,7 +95,7 @@ class ShowController extends Controller * * Show the specified bill. * - * @param Bill $bill + * @param Bill $bill * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/Bill/StoreController.php b/app/Api/V1/Controllers/Models/Bill/StoreController.php index 7c5cd8b3b5..1e05b2eccf 100644 --- a/app/Api/V1/Controllers/Models/Bill/StoreController.php +++ b/app/Api/V1/Controllers/Models/Bill/StoreController.php @@ -65,7 +65,7 @@ class StoreController extends Controller * * Store a bill. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/Bill/UpdateController.php b/app/Api/V1/Controllers/Models/Bill/UpdateController.php index 2705e62263..d02eba7979 100644 --- a/app/Api/V1/Controllers/Models/Bill/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Bill/UpdateController.php @@ -62,8 +62,8 @@ class UpdateController extends Controller * * Update a bill. * - * @param UpdateRequest $request - * @param Bill $bill + * @param UpdateRequest $request + * @param Bill $bill * * @return JsonResponse */ @@ -80,7 +80,5 @@ class UpdateController extends Controller $resource = new Item($bill, $transformer, 'bills'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } - } diff --git a/app/Api/V1/Controllers/Models/Budget/DestroyController.php b/app/Api/V1/Controllers/Models/Budget/DestroyController.php index 706ce3d82b..a8119c1e93 100644 --- a/app/Api/V1/Controllers/Models/Budget/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Budget/DestroyController.php @@ -59,7 +59,7 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param Budget $budget + * @param Budget $budget * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/Budget/ListController.php b/app/Api/V1/Controllers/Models/Budget/ListController.php index ca2f2fe078..7f8911b7c7 100644 --- a/app/Api/V1/Controllers/Models/Budget/ListController.php +++ b/app/Api/V1/Controllers/Models/Budget/ListController.php @@ -74,7 +74,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/budgets/listAttachmentByBudget * - * @param Budget $budget + * @param Budget $budget * * @return JsonResponse * @throws FireflyException @@ -83,7 +83,7 @@ class ListController extends Controller public function attachments(Budget $budget): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getAttachments($budget); $count = $collection->count(); @@ -91,7 +91,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.budgets.attachments', [$budget->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.budgets.attachments', [$budget->id]).$this->buildParams()); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -109,7 +109,7 @@ class ListController extends Controller * * Display a listing of the resource. * - * @param Budget $budget + * @param Budget $budget * * @return JsonResponse * @throws FireflyException @@ -118,13 +118,13 @@ class ListController extends Controller public function budgetLimits(Budget $budget): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $this->parameters->set('budget_id', $budget->id); $collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end')); $count = $collection->count(); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.budgets.budget_limits', [$budget->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.budgets.budget_limits', [$budget->id]).$this->buildParams()); /** @var BudgetLimitTransformer $transformer */ $transformer = app(BudgetLimitTransformer::class); @@ -141,9 +141,9 @@ class ListController extends Controller * * Show all transactions. * - * @param Request $request + * @param Request $request * - * @param Budget $budget + * @param Budget $budget * * @return JsonResponse * @throws FireflyException @@ -151,7 +151,7 @@ class ListController extends Controller */ public function transactions(Request $request, Budget $budget): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // user can overrule page size with limit parameter. $limit = $this->parameters->get('limit'); @@ -189,7 +189,7 @@ class ListController extends Controller } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.budgets.transactions', [$budget->id]).$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ @@ -207,7 +207,7 @@ class ListController extends Controller * * Show all transactions. * - * @param Request $request + * @param Request $request * * @return JsonResponse * @throws FireflyException @@ -215,7 +215,7 @@ class ListController extends Controller */ public function withoutBudget(Request $request): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // user can overrule page size with limit parameter. $limit = $this->parameters->get('limit'); @@ -253,7 +253,7 @@ class ListController extends Controller } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.budgets.without-budget') . $this->buildParams()); + $paginator->setPath(route('api.v1.budgets.without-budget').$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ @@ -264,5 +264,4 @@ class ListController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/Budget/ShowController.php b/app/Api/V1/Controllers/Models/Budget/ShowController.php index d408bccf5e..80f413acf2 100644 --- a/app/Api/V1/Controllers/Models/Budget/ShowController.php +++ b/app/Api/V1/Controllers/Models/Budget/ShowController.php @@ -78,7 +78,7 @@ class ShowController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->repository->getBudgets(); @@ -87,7 +87,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($budgets, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.budgets.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.budgets.index').$this->buildParams()); /** @var BudgetTransformer $transformer */ $transformer = app(BudgetTransformer::class); @@ -102,7 +102,7 @@ class ShowController extends Controller /** * Show a budget. * - * @param Budget $budget + * @param Budget $budget * * @return JsonResponse * @codeCoverageIgnore @@ -119,5 +119,4 @@ class ShowController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/Budget/StoreController.php b/app/Api/V1/Controllers/Models/Budget/StoreController.php index af1d80251b..e8bc6269ca 100644 --- a/app/Api/V1/Controllers/Models/Budget/StoreController.php +++ b/app/Api/V1/Controllers/Models/Budget/StoreController.php @@ -62,7 +62,7 @@ class StoreController extends Controller * * Store a budget. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/Budget/UpdateController.php b/app/Api/V1/Controllers/Models/Budget/UpdateController.php index ce40281086..a8efcd80bb 100644 --- a/app/Api/V1/Controllers/Models/Budget/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Budget/UpdateController.php @@ -62,8 +62,8 @@ class UpdateController extends Controller * * Update a budget. * - * @param UpdateRequest $request - * @param Budget $budget + * @param UpdateRequest $request + * @param Budget $budget * * @return JsonResponse */ @@ -80,6 +80,5 @@ class UpdateController extends Controller $resource = new Item($budget, $transformer, 'budgets'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/BudgetLimit/DestroyController.php b/app/Api/V1/Controllers/Models/BudgetLimit/DestroyController.php index 6bbd40c7bc..2f1b55e2c2 100644 --- a/app/Api/V1/Controllers/Models/BudgetLimit/DestroyController.php +++ b/app/Api/V1/Controllers/Models/BudgetLimit/DestroyController.php @@ -64,8 +64,8 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param Budget $budget - * @param BudgetLimit $budgetLimit + * @param Budget $budget + * @param BudgetLimit $budgetLimit * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/BudgetLimit/ListController.php b/app/Api/V1/Controllers/Models/BudgetLimit/ListController.php index 8b2b2276e4..e4860564b2 100644 --- a/app/Api/V1/Controllers/Models/BudgetLimit/ListController.php +++ b/app/Api/V1/Controllers/Models/BudgetLimit/ListController.php @@ -71,9 +71,9 @@ class ListController extends Controller * https://api-docs.firefly-iii.org/#/budgets/listTransactionByBudgetLimit * Show all transactions. * - * @param Request $request - * @param Budget $budget - * @param BudgetLimit $budgetLimit + * @param Request $request + * @param Budget $budget + * @param BudgetLimit $budgetLimit * * @return JsonResponse * @throws FireflyException @@ -81,7 +81,7 @@ class ListController extends Controller */ public function transactions(Request $request, Budget $budget, BudgetLimit $budgetLimit): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -110,7 +110,7 @@ class ListController extends Controller $collector->setRange($budgetLimit->start_date, $budgetLimit->end_date); $collector->setTypes($types); $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.budgets.limits.transactions', [$budget->id, $budgetLimit->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.budgets.limits.transactions', [$budget->id, $budgetLimit->id]).$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ diff --git a/app/Api/V1/Controllers/Models/BudgetLimit/ShowController.php b/app/Api/V1/Controllers/Models/BudgetLimit/ShowController.php index ac628b3550..a4e812fedd 100644 --- a/app/Api/V1/Controllers/Models/BudgetLimit/ShowController.php +++ b/app/Api/V1/Controllers/Models/BudgetLimit/ShowController.php @@ -75,8 +75,8 @@ class ShowController extends Controller * * Display a listing of the budget limits for this budget. * - * @param Request $request - * @param Budget $budget + * @param Request $request + * @param Budget $budget * * @return JsonResponse * @throws FireflyException @@ -86,12 +86,12 @@ class ShowController extends Controller { $manager = $this->getManager(); $manager->parseIncludes('budget'); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->blRepository->getBudgetLimits($budget, $this->parameters->get('start'), $this->parameters->get('end')); $count = $collection->count(); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.budgets.limits.index', [$budget->id]).$this->buildParams()); /** @var BudgetLimitTransformer $transformer */ $transformer = app(BudgetLimitTransformer::class); @@ -109,7 +109,7 @@ class ShowController extends Controller * * Display a listing of the budget limits for this budget. * - * @param DateRequest $request + * @param DateRequest $request * * @return JsonResponse * @throws FireflyException @@ -119,12 +119,12 @@ class ShowController extends Controller { $manager = $this->getManager(); $manager->parseIncludes('budget'); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->blRepository->getAllBudgetLimits($this->parameters->get('start'), $this->parameters->get('end')); $count = $collection->count(); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.budget-limits.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.budget-limits.index').$this->buildParams()); /** @var BudgetLimitTransformer $transformer */ $transformer = app(BudgetLimitTransformer::class); @@ -140,16 +140,16 @@ class ShowController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/budgets/getBudgetLimit * - * @param Request $request - * @param Budget $budget - * @param BudgetLimit $budgetLimit + * @param Request $request + * @param Budget $budget + * @param BudgetLimit $budgetLimit * * @return JsonResponse * @throws FireflyException */ public function show(Request $request, Budget $budget, BudgetLimit $budgetLimit): JsonResponse { - if ((int) $budget->id !== (int) $budgetLimit->budget_id) { + if ((int)$budget->id !== (int)$budgetLimit->budget_id) { throw new FireflyException('20028: The budget limit does not belong to the budget.'); } // continue! @@ -163,5 +163,4 @@ class ShowController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/BudgetLimit/StoreController.php b/app/Api/V1/Controllers/Models/BudgetLimit/StoreController.php index d5630273fd..d868777485 100644 --- a/app/Api/V1/Controllers/Models/BudgetLimit/StoreController.php +++ b/app/Api/V1/Controllers/Models/BudgetLimit/StoreController.php @@ -65,8 +65,8 @@ class StoreController extends Controller * * Store a newly created resource in storage. * - * @param StoreRequest $request - * @param Budget $budget + * @param StoreRequest $request + * @param Budget $budget * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/BudgetLimit/UpdateController.php b/app/Api/V1/Controllers/Models/BudgetLimit/UpdateController.php index 9325d3297d..baa0217a80 100644 --- a/app/Api/V1/Controllers/Models/BudgetLimit/UpdateController.php +++ b/app/Api/V1/Controllers/Models/BudgetLimit/UpdateController.php @@ -67,17 +67,16 @@ class UpdateController extends Controller /** * Update the specified resource in storage. * - * @param UpdateRequest $request - * @param Budget $budget - * @param BudgetLimit $budgetLimit + * @param UpdateRequest $request + * @param Budget $budget + * @param BudgetLimit $budgetLimit * * @return JsonResponse * @throws FireflyException */ public function update(UpdateRequest $request, Budget $budget, BudgetLimit $budgetLimit): JsonResponse { - - if ((int) $budget->id !== (int) $budgetLimit->budget_id) { + if ((int)$budget->id !== (int)$budgetLimit->budget_id) { throw new FireflyException('20028: The budget limit does not belong to the budget.'); } $data = $request->getAll(); @@ -92,6 +91,5 @@ class UpdateController extends Controller $resource = new Item($budgetLimit, $transformer, 'budget_limits'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/Category/DestroyController.php b/app/Api/V1/Controllers/Models/Category/DestroyController.php index 1136bd2df8..c28e976324 100644 --- a/app/Api/V1/Controllers/Models/Category/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Category/DestroyController.php @@ -59,7 +59,7 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param Category $category + * @param Category $category * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/Category/ListController.php b/app/Api/V1/Controllers/Models/Category/ListController.php index 1cfdf8e268..4c0c8b2acd 100644 --- a/app/Api/V1/Controllers/Models/Category/ListController.php +++ b/app/Api/V1/Controllers/Models/Category/ListController.php @@ -69,7 +69,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/categories/listAttachmentByCategory * - * @param Category $category + * @param Category $category * * @return JsonResponse * @throws FireflyException @@ -78,7 +78,7 @@ class ListController extends Controller public function attachments(Category $category): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getAttachments($category); $count = $collection->count(); @@ -86,7 +86,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.categories.attachments', [$category->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.categories.attachments', [$category->id]).$this->buildParams()); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -104,9 +104,9 @@ class ListController extends Controller * * Show all transactions. * - * @param Request $request + * @param Request $request * - * @param Category $category + * @param Category $category * * @return JsonResponse * @throws FireflyException @@ -114,7 +114,7 @@ class ListController extends Controller */ public function transactions(Request $request, Category $category): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -145,7 +145,7 @@ class ListController extends Controller } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.categories.transactions', [$category->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.categories.transactions', [$category->id]).$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ @@ -157,5 +157,4 @@ class ListController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/Category/ShowController.php b/app/Api/V1/Controllers/Models/Category/ShowController.php index 0f18d8f831..009739d4a8 100644 --- a/app/Api/V1/Controllers/Models/Category/ShowController.php +++ b/app/Api/V1/Controllers/Models/Category/ShowController.php @@ -74,7 +74,7 @@ class ShowController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->repository->getCategories(); @@ -83,7 +83,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($categories, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.categories.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.categories.index').$this->buildParams()); /** @var CategoryTransformer $transformer */ $transformer = app(CategoryTransformer::class); @@ -100,7 +100,7 @@ class ShowController extends Controller * * Show the category. * - * @param Category $category + * @param Category $category * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/Category/StoreController.php b/app/Api/V1/Controllers/Models/Category/StoreController.php index 3b93112db7..80918e0c54 100644 --- a/app/Api/V1/Controllers/Models/Category/StoreController.php +++ b/app/Api/V1/Controllers/Models/Category/StoreController.php @@ -62,7 +62,7 @@ class StoreController extends Controller * * Store new category. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException @@ -80,5 +80,4 @@ class StoreController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/Category/UpdateController.php b/app/Api/V1/Controllers/Models/Category/UpdateController.php index f7d3532da0..d72794be9a 100644 --- a/app/Api/V1/Controllers/Models/Category/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Category/UpdateController.php @@ -62,8 +62,8 @@ class UpdateController extends Controller * * Update the category. * - * @param UpdateRequest $request - * @param Category $category + * @param UpdateRequest $request + * @param Category $category * * @return JsonResponse */ @@ -80,6 +80,5 @@ class UpdateController extends Controller $resource = new Item($category, $transformer, 'categories'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/ObjectGroup/DestroyController.php b/app/Api/V1/Controllers/Models/ObjectGroup/DestroyController.php index 1ba20dd668..72bbb5665b 100644 --- a/app/Api/V1/Controllers/Models/ObjectGroup/DestroyController.php +++ b/app/Api/V1/Controllers/Models/ObjectGroup/DestroyController.php @@ -62,7 +62,7 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @codeCoverageIgnore * @return JsonResponse diff --git a/app/Api/V1/Controllers/Models/ObjectGroup/ListController.php b/app/Api/V1/Controllers/Models/ObjectGroup/ListController.php index 907500a309..f82a2ad335 100644 --- a/app/Api/V1/Controllers/Models/ObjectGroup/ListController.php +++ b/app/Api/V1/Controllers/Models/ObjectGroup/ListController.php @@ -68,7 +68,7 @@ class ListController extends Controller * * List all bills in this object group * - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return JsonResponse * @throws FireflyException @@ -78,7 +78,7 @@ class ListController extends Controller { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of piggy banks. Count it and split it. $collection = $this->repository->getBills($objectGroup); $count = $collection->count(); @@ -86,7 +86,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.currencies.bills', [$objectGroup->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.currencies.bills', [$objectGroup->id]).$this->buildParams()); /** @var BillTransformer $transformer */ $transformer = app(BillTransformer::class); @@ -104,7 +104,7 @@ class ListController extends Controller * * List all piggies under the object group. * - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return JsonResponse * @throws FireflyException @@ -116,7 +116,7 @@ class ListController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of piggy banks. Count it and split it. $collection = $this->repository->getPiggyBanks($objectGroup); @@ -125,7 +125,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.object-groups.piggy_banks', [$objectGroup->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.object-groups.piggy_banks', [$objectGroup->id]).$this->buildParams()); /** @var PiggyBankTransformer $transformer */ $transformer = app(PiggyBankTransformer::class); @@ -135,6 +135,5 @@ class ListController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/ObjectGroup/ShowController.php b/app/Api/V1/Controllers/Models/ObjectGroup/ShowController.php index bfc001fa93..3fe8b0b41a 100644 --- a/app/Api/V1/Controllers/Models/ObjectGroup/ShowController.php +++ b/app/Api/V1/Controllers/Models/ObjectGroup/ShowController.php @@ -69,7 +69,7 @@ class ShowController extends Controller * * Display a listing of the resource. * - * @param Request $request + * @param Request $request * * @return JsonResponse * @throws FireflyException @@ -80,7 +80,7 @@ class ShowController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $this->repository->resetOrder(); $collection = $this->repository->get(); @@ -89,7 +89,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($objectGroups, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.object-groups.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.object-groups.index').$this->buildParams()); /** @var ObjectGroupTransformer $transformer */ $transformer = app(ObjectGroupTransformer::class); @@ -107,7 +107,7 @@ class ShowController extends Controller * * Show single instance. * - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/ObjectGroup/UpdateController.php b/app/Api/V1/Controllers/Models/ObjectGroup/UpdateController.php index ceb2e32dc9..a9d5ce11c8 100644 --- a/app/Api/V1/Controllers/Models/ObjectGroup/UpdateController.php +++ b/app/Api/V1/Controllers/Models/ObjectGroup/UpdateController.php @@ -63,8 +63,8 @@ class UpdateController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/object_groups/updateObjectGroup * - * @param UpdateRequest $request - * @param ObjectGroup $objectGroup + * @param UpdateRequest $request + * @param ObjectGroup $objectGroup * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/PiggyBank/DestroyController.php b/app/Api/V1/Controllers/Models/PiggyBank/DestroyController.php index 5ea137b509..87d78ebc8d 100644 --- a/app/Api/V1/Controllers/Models/PiggyBank/DestroyController.php +++ b/app/Api/V1/Controllers/Models/PiggyBank/DestroyController.php @@ -59,7 +59,7 @@ class DestroyController extends Controller * * Delete the resource. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/PiggyBank/ListController.php b/app/Api/V1/Controllers/Models/PiggyBank/ListController.php index d7537df365..8ae793aba3 100644 --- a/app/Api/V1/Controllers/Models/PiggyBank/ListController.php +++ b/app/Api/V1/Controllers/Models/PiggyBank/ListController.php @@ -63,7 +63,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/piggy_banks/listAttachmentByPiggyBank * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return JsonResponse * @throws FireflyException @@ -72,7 +72,7 @@ class ListController extends Controller public function attachments(PiggyBank $piggyBank): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getAttachments($piggyBank); $count = $collection->count(); @@ -80,7 +80,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.piggy_banks.attachments', [$piggyBank->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.piggy_banks.attachments', [$piggyBank->id]).$this->buildParams()); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -98,7 +98,7 @@ class ListController extends Controller * * List single resource. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return JsonResponse * @throws FireflyException @@ -107,7 +107,7 @@ class ListController extends Controller public function piggyBankEvents(PiggyBank $piggyBank): JsonResponse { // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $manager = $this->getManager(); $collection = $this->repository->getEvents($piggyBank); @@ -116,7 +116,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.piggy_banks.events', [$piggyBank->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.piggy_banks.events', [$piggyBank->id]).$this->buildParams()); /** @var PiggyBankEventTransformer $transformer */ $transformer = app(PiggyBankEventTransformer::class); @@ -126,6 +126,5 @@ class ListController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/PiggyBank/ShowController.php b/app/Api/V1/Controllers/Models/PiggyBank/ShowController.php index ccdcaeebf5..748607cc51 100644 --- a/app/Api/V1/Controllers/Models/PiggyBank/ShowController.php +++ b/app/Api/V1/Controllers/Models/PiggyBank/ShowController.php @@ -73,7 +73,7 @@ class ShowController extends Controller { $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->repository->getPiggyBanks(); @@ -82,7 +82,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.piggy_banks.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.piggy_banks.index').$this->buildParams()); /** @var PiggyBankTransformer $transformer */ $transformer = app(PiggyBankTransformer::class); @@ -92,7 +92,6 @@ class ShowController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -101,7 +100,7 @@ class ShowController extends Controller * * List single resource. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return JsonResponse * @codeCoverageIgnore @@ -117,6 +116,5 @@ class ShowController extends Controller $resource = new Item($piggyBank, $transformer, 'piggy_banks'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/PiggyBank/StoreController.php b/app/Api/V1/Controllers/Models/PiggyBank/StoreController.php index a1bdd1dfc1..b24ce9c958 100644 --- a/app/Api/V1/Controllers/Models/PiggyBank/StoreController.php +++ b/app/Api/V1/Controllers/Models/PiggyBank/StoreController.php @@ -62,7 +62,7 @@ class StoreController extends Controller * * Store new object. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/PiggyBank/UpdateController.php b/app/Api/V1/Controllers/Models/PiggyBank/UpdateController.php index 41d69b904b..b4da94b7d1 100644 --- a/app/Api/V1/Controllers/Models/PiggyBank/UpdateController.php +++ b/app/Api/V1/Controllers/Models/PiggyBank/UpdateController.php @@ -62,8 +62,8 @@ class UpdateController extends Controller * * Update piggy bank. * - * @param UpdateRequest $request - * @param PiggyBank $piggyBank + * @param UpdateRequest $request + * @param PiggyBank $piggyBank * * @return JsonResponse */ @@ -84,6 +84,5 @@ class UpdateController extends Controller $resource = new Item($piggyBank, $transformer, 'piggy_banks'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/Recurrence/DestroyController.php b/app/Api/V1/Controllers/Models/Recurrence/DestroyController.php index 01d175eb1d..f623884984 100644 --- a/app/Api/V1/Controllers/Models/Recurrence/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Recurrence/DestroyController.php @@ -59,7 +59,7 @@ class DestroyController extends Controller * * Delete the resource. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/Recurrence/ListController.php b/app/Api/V1/Controllers/Models/Recurrence/ListController.php index 9b13fc88d7..04617cd30a 100644 --- a/app/Api/V1/Controllers/Models/Recurrence/ListController.php +++ b/app/Api/V1/Controllers/Models/Recurrence/ListController.php @@ -69,8 +69,8 @@ class ListController extends Controller * * Show transactions for this recurrence. * - * @param Request $request - * @param Recurrence $recurrence + * @param Request $request + * @param Recurrence $recurrence * * @return JsonResponse * @throws FireflyException @@ -78,7 +78,7 @@ class ListController extends Controller */ public function transactions(Request $request, Recurrence $recurrence): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -110,7 +110,7 @@ class ListController extends Controller $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ diff --git a/app/Api/V1/Controllers/Models/Recurrence/ShowController.php b/app/Api/V1/Controllers/Models/Recurrence/ShowController.php index 1d53b2528a..fe42cb7374 100644 --- a/app/Api/V1/Controllers/Models/Recurrence/ShowController.php +++ b/app/Api/V1/Controllers/Models/Recurrence/ShowController.php @@ -74,7 +74,7 @@ class ShowController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->repository->get(); @@ -83,7 +83,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.recurrences.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.recurrences.index').$this->buildParams()); /** @var RecurrenceTransformer $transformer */ $transformer = app(RecurrenceTransformer::class); @@ -93,7 +93,6 @@ class ShowController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -102,7 +101,7 @@ class ShowController extends Controller * * List single resource. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/Recurrence/StoreController.php b/app/Api/V1/Controllers/Models/Recurrence/StoreController.php index 8ca5672b2a..f7a2f33a26 100644 --- a/app/Api/V1/Controllers/Models/Recurrence/StoreController.php +++ b/app/Api/V1/Controllers/Models/Recurrence/StoreController.php @@ -62,7 +62,7 @@ class StoreController extends Controller * * Store new object. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/Recurrence/UpdateController.php b/app/Api/V1/Controllers/Models/Recurrence/UpdateController.php index 8e0ec86815..d77aaa6928 100644 --- a/app/Api/V1/Controllers/Models/Recurrence/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Recurrence/UpdateController.php @@ -62,8 +62,8 @@ class UpdateController extends Controller * * Update single recurrence. * - * @param UpdateRequest $request - * @param Recurrence $recurrence + * @param UpdateRequest $request + * @param Recurrence $recurrence * * @return JsonResponse */ @@ -80,6 +80,5 @@ class UpdateController extends Controller $resource = new Item($recurrence, $transformer, 'recurrences'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/Rule/DestroyController.php b/app/Api/V1/Controllers/Models/Rule/DestroyController.php index 70e8f88dd0..a7ad885b96 100644 --- a/app/Api/V1/Controllers/Models/Rule/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Rule/DestroyController.php @@ -63,7 +63,7 @@ class DestroyController extends Controller * * Delete the resource. * - * @param Rule $rule + * @param Rule $rule * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/Rule/ShowController.php b/app/Api/V1/Controllers/Models/Rule/ShowController.php index c633aac828..8b12d1c3f6 100644 --- a/app/Api/V1/Controllers/Models/Rule/ShowController.php +++ b/app/Api/V1/Controllers/Models/Rule/ShowController.php @@ -78,7 +78,7 @@ class ShowController extends Controller $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->ruleRepository->getAll(); @@ -87,7 +87,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.rules.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.rules.index').$this->buildParams()); /** @var RuleTransformer $transformer */ $transformer = app(RuleTransformer::class); @@ -97,7 +97,6 @@ class ShowController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -106,7 +105,7 @@ class ShowController extends Controller * * List single resource. * - * @param Rule $rule + * @param Rule $rule * * @return JsonResponse * @codeCoverageIgnore @@ -121,6 +120,5 @@ class ShowController extends Controller $resource = new Item($rule, $transformer, 'rules'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/Rule/StoreController.php b/app/Api/V1/Controllers/Models/Rule/StoreController.php index 322cf814d5..4cfe601f7f 100644 --- a/app/Api/V1/Controllers/Models/Rule/StoreController.php +++ b/app/Api/V1/Controllers/Models/Rule/StoreController.php @@ -65,7 +65,7 @@ class StoreController extends Controller * * Store new object. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/Rule/TriggerController.php b/app/Api/V1/Controllers/Models/Rule/TriggerController.php index 528f1e6755..f3eef085b5 100644 --- a/app/Api/V1/Controllers/Models/Rule/TriggerController.php +++ b/app/Api/V1/Controllers/Models/Rule/TriggerController.php @@ -69,8 +69,8 @@ class TriggerController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/rules/testRule * - * @param TestRequest $request - * @param Rule $rule + * @param TestRequest $request + * @param Rule $rule * * @return JsonResponse */ @@ -101,7 +101,7 @@ class TriggerController extends Controller $count = $transactions->count(); $paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.rules.test', [$rule->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.rules.test', [$rule->id]).$this->buildParams()); // resulting list is presented as JSON thing. $manager = $this->getManager(); @@ -121,8 +121,8 @@ class TriggerController extends Controller * * Execute the given rule group on a set of existing transactions. * - * @param TriggerRequest $request - * @param Rule $rule + * @param TriggerRequest $request + * @param Rule $rule * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/Rule/UpdateController.php b/app/Api/V1/Controllers/Models/Rule/UpdateController.php index b8e3996e8b..df81811814 100644 --- a/app/Api/V1/Controllers/Models/Rule/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Rule/UpdateController.php @@ -66,8 +66,8 @@ class UpdateController extends Controller * * Update a rule. * - * @param UpdateRequest $request - * @param Rule $rule + * @param UpdateRequest $request + * @param Rule $rule * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/RuleGroup/DestroyController.php b/app/Api/V1/Controllers/Models/RuleGroup/DestroyController.php index b1e9e9610c..a137a56ac8 100644 --- a/app/Api/V1/Controllers/Models/RuleGroup/DestroyController.php +++ b/app/Api/V1/Controllers/Models/RuleGroup/DestroyController.php @@ -63,7 +63,7 @@ class DestroyController extends Controller * * Delete the resource. * - * @param RuleGroup $ruleGroup + * @param RuleGroup $ruleGroup * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/RuleGroup/ListController.php b/app/Api/V1/Controllers/Models/RuleGroup/ListController.php index f730025352..73027a0e6e 100644 --- a/app/Api/V1/Controllers/Models/RuleGroup/ListController.php +++ b/app/Api/V1/Controllers/Models/RuleGroup/ListController.php @@ -66,7 +66,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/rule_groups/listRuleByGroup * - * @param RuleGroup $group + * @param RuleGroup $group * * @return JsonResponse * @throws FireflyException @@ -76,7 +76,7 @@ class ListController extends Controller { $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->ruleGroupRepository->getRules($group); @@ -85,7 +85,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.rule_groups.rules', [$group->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.rule_groups.rules', [$group->id]).$this->buildParams()); /** @var RuleTransformer $transformer */ $transformer = app(RuleTransformer::class); @@ -95,6 +95,5 @@ class ListController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/RuleGroup/ShowController.php b/app/Api/V1/Controllers/Models/RuleGroup/ShowController.php index da714489aa..ed525de037 100644 --- a/app/Api/V1/Controllers/Models/RuleGroup/ShowController.php +++ b/app/Api/V1/Controllers/Models/RuleGroup/ShowController.php @@ -76,7 +76,7 @@ class ShowController extends Controller { $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of rule groups. Count it and split it. $collection = $this->ruleGroupRepository->get(); @@ -85,7 +85,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($ruleGroups, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.rule_groups.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.rule_groups.index').$this->buildParams()); /** @var RuleGroupTransformer $transformer */ $transformer = app(RuleGroupTransformer::class); @@ -103,7 +103,7 @@ class ShowController extends Controller * * List single resource. * - * @param RuleGroup $ruleGroup + * @param RuleGroup $ruleGroup * * @return JsonResponse * @codeCoverageIgnore @@ -118,7 +118,5 @@ class ShowController extends Controller $resource = new Item($ruleGroup, $transformer, 'rule_groups'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } - } diff --git a/app/Api/V1/Controllers/Models/RuleGroup/StoreController.php b/app/Api/V1/Controllers/Models/RuleGroup/StoreController.php index 5f87c6866f..34455a4cf6 100644 --- a/app/Api/V1/Controllers/Models/RuleGroup/StoreController.php +++ b/app/Api/V1/Controllers/Models/RuleGroup/StoreController.php @@ -37,7 +37,6 @@ use League\Fractal\Resource\Item; */ class StoreController extends Controller { - private AccountRepositoryInterface $accountRepository; private RuleGroupRepositoryInterface $ruleGroupRepository; @@ -71,7 +70,7 @@ class StoreController extends Controller * * Store new object. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse */ @@ -87,6 +86,5 @@ class StoreController extends Controller $resource = new Item($ruleGroup, $transformer, 'rule_groups'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/RuleGroup/TriggerController.php b/app/Api/V1/Controllers/Models/RuleGroup/TriggerController.php index 98c4d37793..c909f736c0 100644 --- a/app/Api/V1/Controllers/Models/RuleGroup/TriggerController.php +++ b/app/Api/V1/Controllers/Models/RuleGroup/TriggerController.php @@ -70,8 +70,8 @@ class TriggerController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/rule_groups/testRuleGroup * - * @param TestRequest $request - * @param RuleGroup $group + * @param TestRequest $request + * @param RuleGroup $group * * @return JsonResponse * @throws FireflyException @@ -108,7 +108,7 @@ class TriggerController extends Controller $count = $transactions->count(); $paginator = new LengthAwarePaginator($transactions, $count, 31337, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.rule_groups.test', [$group->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.rule_groups.test', [$group->id]).$this->buildParams()); // resulting list is presented as JSON thing. $manager = $this->getManager(); @@ -128,8 +128,8 @@ class TriggerController extends Controller * * Execute the given rule group on a set of existing transactions. * - * @param TriggerRequest $request - * @param RuleGroup $group + * @param TriggerRequest $request + * @param RuleGroup $group * * @return JsonResponse * @throws Exception @@ -167,5 +167,4 @@ class TriggerController extends Controller return response()->json([], 204); } - } diff --git a/app/Api/V1/Controllers/Models/RuleGroup/UpdateController.php b/app/Api/V1/Controllers/Models/RuleGroup/UpdateController.php index 2cb39726ac..8a8115c991 100644 --- a/app/Api/V1/Controllers/Models/RuleGroup/UpdateController.php +++ b/app/Api/V1/Controllers/Models/RuleGroup/UpdateController.php @@ -37,7 +37,6 @@ use League\Fractal\Resource\Item; */ class UpdateController extends Controller { - private RuleGroupRepositoryInterface $ruleGroupRepository; /** @@ -67,8 +66,8 @@ class UpdateController extends Controller * * Update a rule group. * - * @param UpdateRequest $request - * @param RuleGroup $ruleGroup + * @param UpdateRequest $request + * @param RuleGroup $ruleGroup * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Models/Tag/DestroyController.php b/app/Api/V1/Controllers/Models/Tag/DestroyController.php index cbcecf0be9..ba83bae637 100644 --- a/app/Api/V1/Controllers/Models/Tag/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Tag/DestroyController.php @@ -63,7 +63,7 @@ class DestroyController extends Controller * * Delete the resource. * - * @param Tag $tag + * @param Tag $tag * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Models/Tag/ListController.php b/app/Api/V1/Controllers/Models/Tag/ListController.php index 855a7169f2..7f4196ea52 100644 --- a/app/Api/V1/Controllers/Models/Tag/ListController.php +++ b/app/Api/V1/Controllers/Models/Tag/ListController.php @@ -72,7 +72,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/tags/listAttachmentByTag * - * @param Tag $tag + * @param Tag $tag * * @return JsonResponse * @throws FireflyException @@ -81,7 +81,7 @@ class ListController extends Controller public function attachments(Tag $tag): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getAttachments($tag); $count = $collection->count(); @@ -89,7 +89,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.tags.attachments', [$tag->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.tags.attachments', [$tag->id]).$this->buildParams()); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -107,8 +107,8 @@ class ListController extends Controller * * Show all transactions. * - * @param Request $request - * @param Tag $tag + * @param Request $request + * @param Tag $tag * * @return JsonResponse * @throws FireflyException @@ -116,7 +116,7 @@ class ListController extends Controller */ public function transactions(Request $request, Tag $tag): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -145,7 +145,7 @@ class ListController extends Controller $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.tags.transactions', [$tag->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.tags.transactions', [$tag->id]).$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ diff --git a/app/Api/V1/Controllers/Models/Tag/ShowController.php b/app/Api/V1/Controllers/Models/Tag/ShowController.php index 3aede9926f..17620e0fcd 100644 --- a/app/Api/V1/Controllers/Models/Tag/ShowController.php +++ b/app/Api/V1/Controllers/Models/Tag/ShowController.php @@ -77,7 +77,7 @@ class ShowController extends Controller { $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. $collection = $this->repository->get(); @@ -86,7 +86,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.tags.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.tags.index').$this->buildParams()); /** @var TagTransformer $transformer */ $transformer = app(TagTransformer::class); @@ -104,7 +104,7 @@ class ShowController extends Controller * * List single resource. * - * @param Tag $tag + * @param Tag $tag * * @return JsonResponse * @codeCoverageIgnore @@ -119,6 +119,5 @@ class ShowController extends Controller $resource = new Item($tag, $transformer, 'tags'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/Tag/StoreController.php b/app/Api/V1/Controllers/Models/Tag/StoreController.php index 9b2dcff1c5..ab277913a9 100644 --- a/app/Api/V1/Controllers/Models/Tag/StoreController.php +++ b/app/Api/V1/Controllers/Models/Tag/StoreController.php @@ -65,7 +65,7 @@ class StoreController extends Controller * * Store new object. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse */ @@ -82,4 +82,3 @@ class StoreController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } } - diff --git a/app/Api/V1/Controllers/Models/Tag/UpdateController.php b/app/Api/V1/Controllers/Models/Tag/UpdateController.php index 5646a4b302..952b2ac513 100644 --- a/app/Api/V1/Controllers/Models/Tag/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Tag/UpdateController.php @@ -66,8 +66,8 @@ class UpdateController extends Controller * * Update a rule. * - * @param UpdateRequest $request - * @param Tag $tag + * @param UpdateRequest $request + * @param Tag $tag * * @return JsonResponse */ @@ -82,7 +82,5 @@ class UpdateController extends Controller $resource = new Item($rule, $transformer, 'tags'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } - } diff --git a/app/Api/V1/Controllers/Models/Transaction/DestroyController.php b/app/Api/V1/Controllers/Models/Transaction/DestroyController.php index d7d9bccfe3..e78c5b676a 100644 --- a/app/Api/V1/Controllers/Models/Transaction/DestroyController.php +++ b/app/Api/V1/Controllers/Models/Transaction/DestroyController.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers\Models\Transaction; use FireflyIII\Api\V1\Controllers\Controller; -use FireflyIII\Events\DestroyedTransactionGroup; use FireflyIII\Events\UpdatedAccount; use FireflyIII\Models\Account; use FireflyIII\Models\Transaction; @@ -41,8 +40,8 @@ use Log; */ class DestroyController extends Controller { - private JournalRepositoryInterface $repository; private TransactionGroupRepository $groupRepository; + private JournalRepositoryInterface $repository; /** * TransactionController constructor. @@ -74,22 +73,23 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return JsonResponse * @codeCoverageIgnore */ public function destroy(TransactionGroup $transactionGroup): JsonResponse { + Log::debug(sprintf('Now in %s', __METHOD__)); // grab asset account(s) from group: $accounts = []; /** @var TransactionJournal $journal */ - foreach($transactionGroup->transactionJournals as $journal) { + foreach ($transactionGroup->transactionJournals as $journal) { /** @var Transaction $transaction */ - foreach($journal->transactions as $transaction) { + foreach ($journal->transactions as $transaction) { $type = $transaction->account->accountType->type; // if is valid liability, trigger event! - if(in_array($type, config('firefly.valid_liabilities'))) { + if (in_array($type, config('firefly.valid_liabilities'), true)) { $accounts[] = $transaction->account; } } @@ -100,7 +100,7 @@ class DestroyController extends Controller app('preferences')->mark(); /** @var Account $account */ - foreach($accounts as $account) { + foreach ($accounts as $account) { Log::debug(sprintf('Now going to trigger updated account event for account #%d', $account->id)); event(new UpdatedAccount($account)); } @@ -114,7 +114,7 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param TransactionJournal $transactionJournal + * @param TransactionJournal $transactionJournal * * @codeCoverageIgnore * @return JsonResponse diff --git a/app/Api/V1/Controllers/Models/Transaction/ListController.php b/app/Api/V1/Controllers/Models/Transaction/ListController.php index 025836433b..0da0a2b5b4 100644 --- a/app/Api/V1/Controllers/Models/Transaction/ListController.php +++ b/app/Api/V1/Controllers/Models/Transaction/ListController.php @@ -70,7 +70,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/transactions/listAttachmentByTransaction * - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return JsonResponse * @throws FireflyException @@ -79,8 +79,8 @@ class ListController extends Controller public function attachments(TransactionGroup $transactionGroup): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; - $collection = new Collection; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $collection = new Collection(); foreach ($transactionGroup->transactionJournals as $transactionJournal) { $collection = $this->journalAPIRepository->getAttachments($transactionJournal)->merge($collection); } @@ -90,7 +90,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($attachments, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.transactions.attachments', [$transactionGroup->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.transactions.attachments', [$transactionGroup->id]).$this->buildParams()); /** @var AttachmentTransformer $transformer */ $transformer = app(AttachmentTransformer::class); @@ -106,7 +106,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/transactions/listEventByTransaction * - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return JsonResponse * @throws FireflyException @@ -115,8 +115,8 @@ class ListController extends Controller public function piggyBankEvents(TransactionGroup $transactionGroup): JsonResponse { $manager = $this->getManager(); - $collection = new Collection; - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $collection = new Collection(); + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; foreach ($transactionGroup->transactionJournals as $transactionJournal) { $collection = $this->journalAPIRepository->getPiggyBankEvents($transactionJournal)->merge($collection); } @@ -124,7 +124,7 @@ class ListController extends Controller $events = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); // make paginator: $paginator = new LengthAwarePaginator($events, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.transactions.piggy_bank_events', [$transactionGroup->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.transactions.piggy_bank_events', [$transactionGroup->id]).$this->buildParams()); /** @var PiggyBankEventTransformer $transformer */ $transformer = app(PiggyBankEventTransformer::class); @@ -145,7 +145,7 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/transactions/listLinksByJournal * - * @param TransactionJournal $transactionJournal + * @param TransactionJournal $transactionJournal * * @return JsonResponse * @throws FireflyException @@ -155,13 +155,13 @@ class ListController extends Controller { $manager = $this->getManager(); $collection = $this->journalAPIRepository->getJournalLinks($transactionJournal); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $count = $collection->count(); $journalLinks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); // make paginator: $paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.transaction-journals.transaction_links', [$transactionJournal->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.transaction-journals.transaction_links', [$transactionJournal->id]).$this->buildParams()); /** @var TransactionLinkTransformer $transformer */ $transformer = app(TransactionLinkTransformer::class); diff --git a/app/Api/V1/Controllers/Models/Transaction/ShowController.php b/app/Api/V1/Controllers/Models/Transaction/ShowController.php index c86af23b9b..383796dae2 100644 --- a/app/Api/V1/Controllers/Models/Transaction/ShowController.php +++ b/app/Api/V1/Controllers/Models/Transaction/ShowController.php @@ -51,7 +51,7 @@ class ShowController extends Controller * * Show all transactions. * - * @param Request $request + * @param Request $request * * @return JsonResponse * @throws FireflyException @@ -59,7 +59,7 @@ class ShowController extends Controller */ public function index(Request $request): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -85,7 +85,7 @@ class ShowController extends Controller $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ @@ -104,7 +104,7 @@ class ShowController extends Controller * * Show a single transaction, by transaction journal. * - * @param TransactionJournal $transactionJournal + * @param TransactionJournal $transactionJournal * * @return JsonResponse * @codeCoverageIgnore @@ -120,7 +120,7 @@ class ShowController extends Controller * * Show a single transaction. * - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return JsonResponse * @codeCoverageIgnore @@ -151,5 +151,4 @@ class ShowController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/Transaction/StoreController.php b/app/Api/V1/Controllers/Models/Transaction/StoreController.php index 4595ee55c4..5f1bbcda96 100644 --- a/app/Api/V1/Controllers/Models/Transaction/StoreController.php +++ b/app/Api/V1/Controllers/Models/Transaction/StoreController.php @@ -76,7 +76,7 @@ class StoreController extends Controller * * Store a new transaction. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException|ValidationException @@ -93,16 +93,17 @@ class StoreController extends Controller try { $transactionGroup = $this->groupRepository->store($data); } catch (DuplicateTransactionException $e) { - Log::warning('Caught a duplicate transaction. Return error message.'); + app('log')->warning('Caught a duplicate transaction. Return error message.'); $validator = Validator::make( - ['transactions' => [['description' => $e->getMessage()]]], ['transactions.0.description' => new IsDuplicateTransaction] + ['transactions' => [['description' => $e->getMessage()]]], + ['transactions.0.description' => new IsDuplicateTransaction()] ); throw new ValidationException($validator, 0, $e); } catch (FireflyException $e) { - Log::warning('Caught an exception. Return error message.'); + app('log')->warning('Caught an exception. Return error message.'); Log::error($e->getMessage()); $message = sprintf('Internal exception: %s', $e->getMessage()); - $validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction]); + $validator = Validator::make(['transactions' => [['description' => $message]]], ['transactions.0.description' => new IsDuplicateTransaction()]); throw new ValidationException($validator, 0, $e); } app('preferences')->mark(); diff --git a/app/Api/V1/Controllers/Models/Transaction/UpdateController.php b/app/Api/V1/Controllers/Models/Transaction/UpdateController.php index 500ad0d508..9e5c8978a4 100644 --- a/app/Api/V1/Controllers/Models/Transaction/UpdateController.php +++ b/app/Api/V1/Controllers/Models/Transaction/UpdateController.php @@ -70,8 +70,8 @@ class UpdateController extends Controller * * Update a transaction. * - * @param UpdateRequest $request - * @param TransactionGroup $transactionGroup + * @param UpdateRequest $request + * @param TransactionGroup $transactionGroup * * @return JsonResponse */ @@ -110,5 +110,4 @@ class UpdateController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/TransactionCurrency/DestroyController.php b/app/Api/V1/Controllers/Models/TransactionCurrency/DestroyController.php index b9a7396caf..3b16508dd5 100644 --- a/app/Api/V1/Controllers/Models/TransactionCurrency/DestroyController.php +++ b/app/Api/V1/Controllers/Models/TransactionCurrency/DestroyController.php @@ -28,7 +28,6 @@ use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Illuminate\Http\JsonResponse; @@ -38,7 +37,6 @@ use Illuminate\Http\JsonResponse; class DestroyController extends Controller { private CurrencyRepositoryInterface $repository; - private UserRepositoryInterface $userRepository; /** * CurrencyRepository constructor. @@ -50,8 +48,7 @@ class DestroyController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { - $this->repository = app(CurrencyRepositoryInterface::class); - $this->userRepository = app(UserRepositoryInterface::class); + $this->repository = app(CurrencyRepositoryInterface::class); $this->repository->setUser(auth()->user()); return $next($request); @@ -65,7 +62,7 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/TransactionCurrency/ListController.php b/app/Api/V1/Controllers/Models/TransactionCurrency/ListController.php index 50d4e3c704..fbe18135eb 100644 --- a/app/Api/V1/Controllers/Models/TransactionCurrency/ListController.php +++ b/app/Api/V1/Controllers/Models/TransactionCurrency/ListController.php @@ -63,11 +63,10 @@ use League\Fractal\Resource\Collection as FractalCollection; */ class ListController extends Controller { - use AccountFilter, TransactionFilter; + use AccountFilter; + use TransactionFilter; private CurrencyRepositoryInterface $repository; - private UserRepositoryInterface $userRepository; - /** * CurrencyRepository constructor. * @@ -79,7 +78,6 @@ class ListController extends Controller $this->middleware( function ($request, $next) { $this->repository = app(CurrencyRepositoryInterface::class); - $this->userRepository = app(UserRepositoryInterface::class); $this->repository->setUser(auth()->user()); return $next($request); @@ -92,8 +90,8 @@ class ListController extends Controller * https://api-docs.firefly-iii.org/#/currencies/listAccountByCurrency * Display a list of accounts. * - * @param Request $request - * @param TransactionCurrency $currency + * @param Request $request + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -109,7 +107,7 @@ class ListController extends Controller // types to get, page size: $types = $this->mapAccountTypes($this->parameters->get('type')); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of accounts. Count it and split it. /** @var AccountRepositoryInterface $accountRepository */ @@ -119,7 +117,7 @@ class ListController extends Controller // filter list on currency preference: $collection = $unfiltered->filter( static function (Account $account) use ($currency, $accountRepository) { - $currencyId = (int) $accountRepository->getMetaValue($account, 'currency_id'); + $currencyId = (int)$accountRepository->getMetaValue($account, 'currency_id'); return $currencyId === $currency->id; } @@ -130,7 +128,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($accounts, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]) . $this->buildParams()); + $paginator->setPath(route('api.v1.currencies.accounts', [$currency->code]).$this->buildParams()); /** @var AccountTransformer $transformer */ $transformer = app(AccountTransformer::class); @@ -147,7 +145,7 @@ class ListController extends Controller * * Display a listing of the resource. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -157,7 +155,7 @@ class ListController extends Controller { $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of available budgets. Count it and split it. /** @var AvailableBudgetRepositoryInterface $abRepository */ @@ -168,7 +166,7 @@ class ListController extends Controller $availableBudgets = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); // make paginator: $paginator = new LengthAwarePaginator($availableBudgets, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.currencies.available_budgets', [$currency->code]) . $this->buildParams()); + $paginator->setPath(route('api.v1.currencies.available_budgets', [$currency->code]).$this->buildParams()); /** @var AvailableBudgetTransformer $transformer */ $transformer = app(AvailableBudgetTransformer::class); @@ -186,7 +184,7 @@ class ListController extends Controller * * List all bills * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -198,7 +196,7 @@ class ListController extends Controller /** @var BillRepositoryInterface $billRepos */ $billRepos = app(BillRepositoryInterface::class); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $unfiltered = $billRepos->getBills(); // filter and paginate list: @@ -212,7 +210,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($bills, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.currencies.bills', [$currency->code]) . $this->buildParams()); + $paginator->setPath(route('api.v1.currencies.bills', [$currency->code]).$this->buildParams()); /** @var BillTransformer $transformer */ $transformer = app(BillTransformer::class); @@ -230,7 +228,7 @@ class ListController extends Controller * * List all budget limits * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -242,12 +240,12 @@ class ListController extends Controller $blRepository = app(BudgetLimitRepositoryInterface::class); $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $blRepository->getAllBudgetLimitsByCurrency($currency, $this->parameters->get('start'), $this->parameters->get('end')); $count = $collection->count(); $budgetLimits = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $paginator = new LengthAwarePaginator($budgetLimits, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.currencies.budget_limits', [$currency->code]) . $this->buildParams()); + $paginator->setPath(route('api.v1.currencies.budget_limits', [$currency->code]).$this->buildParams()); /** @var BudgetLimitTransformer $transformer */ $transformer = app(BudgetLimitTransformer::class); @@ -265,7 +263,7 @@ class ListController extends Controller * * List all recurring transactions. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -275,7 +273,7 @@ class ListController extends Controller { $manager = $this->getManager(); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. /** @var RecurringRepositoryInterface $recurringRepos */ @@ -300,7 +298,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($piggyBanks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]) . $this->buildParams()); + $paginator->setPath(route('api.v1.currencies.recurrences', [$currency->code]).$this->buildParams()); /** @var RecurrenceTransformer $transformer */ $transformer = app(RecurrenceTransformer::class); @@ -310,7 +308,6 @@ class ListController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -319,7 +316,7 @@ class ListController extends Controller * * List all of them. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -328,7 +325,7 @@ class ListController extends Controller public function rules(TransactionCurrency $currency): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of budgets. Count it and split it. /** @var RuleRepositoryInterface $ruleRepos */ @@ -353,7 +350,7 @@ class ListController extends Controller // make paginator: $paginator = new LengthAwarePaginator($rules, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.rules.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.rules.index').$this->buildParams()); /** @var RuleTransformer $transformer */ $transformer = app(RuleTransformer::class); @@ -363,7 +360,6 @@ class ListController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -372,9 +368,9 @@ class ListController extends Controller * * Show all transactions. * - * @param Request $request + * @param Request $request * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -382,7 +378,7 @@ class ListController extends Controller */ public function transactions(Request $request, TransactionCurrency $currency): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -411,7 +407,7 @@ class ListController extends Controller $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]) . $this->buildParams()); + $paginator->setPath(route('api.v1.currencies.transactions', [$currency->code]).$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ diff --git a/app/Api/V1/Controllers/Models/TransactionCurrency/ShowController.php b/app/Api/V1/Controllers/Models/TransactionCurrency/ShowController.php index 2cc7c99838..98dc10efef 100644 --- a/app/Api/V1/Controllers/Models/TransactionCurrency/ShowController.php +++ b/app/Api/V1/Controllers/Models/TransactionCurrency/ShowController.php @@ -43,7 +43,8 @@ use League\Fractal\Resource\Item; */ class ShowController extends Controller { - use AccountFilter, TransactionFilter; + use AccountFilter; + use TransactionFilter; private CurrencyRepositoryInterface $repository; @@ -78,13 +79,13 @@ class ShowController extends Controller */ public function index(): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getAll(); $count = $collection->count(); // slice them: $currencies = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); $paginator = new LengthAwarePaginator($currencies, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.currencies.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.currencies.index').$this->buildParams()); $manager = $this->getManager(); $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); $this->parameters->set('defaultCurrency', $defaultCurrency); @@ -105,7 +106,7 @@ class ShowController extends Controller * * Show a currency. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/TransactionCurrency/StoreController.php b/app/Api/V1/Controllers/Models/TransactionCurrency/StoreController.php index e85ed2ab05..04f1489512 100644 --- a/app/Api/V1/Controllers/Models/TransactionCurrency/StoreController.php +++ b/app/Api/V1/Controllers/Models/TransactionCurrency/StoreController.php @@ -28,7 +28,6 @@ use FireflyIII\Api\V1\Controllers\Controller; use FireflyIII\Api\V1\Requests\Models\TransactionCurrency\StoreRequest; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\Support\Http\Api\AccountFilter; use FireflyIII\Support\Http\Api\TransactionFilter; use FireflyIII\Transformers\CurrencyTransformer; @@ -41,10 +40,10 @@ use League\Fractal\Resource\Item; */ class StoreController extends Controller { - use AccountFilter, TransactionFilter; + use AccountFilter; + use TransactionFilter; private CurrencyRepositoryInterface $repository; - private UserRepositoryInterface $userRepository; /** * CurrencyRepository constructor. @@ -56,8 +55,7 @@ class StoreController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { - $this->repository = app(CurrencyRepositoryInterface::class); - $this->userRepository = app(UserRepositoryInterface::class); + $this->repository = app(CurrencyRepositoryInterface::class); $this->repository->setUser(auth()->user()); return $next($request); @@ -71,7 +69,7 @@ class StoreController extends Controller * * Store new currency. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/TransactionCurrency/UpdateController.php b/app/Api/V1/Controllers/Models/TransactionCurrency/UpdateController.php index d81fed2b5a..8ab744ea78 100644 --- a/app/Api/V1/Controllers/Models/TransactionCurrency/UpdateController.php +++ b/app/Api/V1/Controllers/Models/TransactionCurrency/UpdateController.php @@ -42,10 +42,10 @@ use League\Fractal\Resource\Item; */ class UpdateController extends Controller { - use AccountFilter, TransactionFilter; + use AccountFilter; + use TransactionFilter; private CurrencyRepositoryInterface $repository; - private UserRepositoryInterface $userRepository; /** * CurrencyRepository constructor. @@ -57,8 +57,7 @@ class UpdateController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { - $this->repository = app(CurrencyRepositoryInterface::class); - $this->userRepository = app(UserRepositoryInterface::class); + $this->repository = app(CurrencyRepositoryInterface::class); $this->repository->setUser(auth()->user()); return $next($request); @@ -72,7 +71,7 @@ class UpdateController extends Controller * * Disable a currency. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -98,38 +97,6 @@ class UpdateController extends Controller $resource = new Item($currency, $transformer, 'currencies'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - - } - - /** - * This endpoint is documented at: - * https://api-docs.firefly-iii.org/#/currencies/enableCurrency - * - * Enable a currency. - * - * @param TransactionCurrency $currency - * - * @return JsonResponse - * @throws FireflyException - * @throws JsonException - * @codeCoverageIgnore - */ - public function enable(TransactionCurrency $currency): JsonResponse - { - $this->repository->enable($currency); - $manager = $this->getManager(); - - $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); - $this->parameters->set('defaultCurrency', $defaultCurrency); - - /** @var CurrencyTransformer $transformer */ - $transformer = app(CurrencyTransformer::class); - $transformer->setParameters($this->parameters); - - $resource = new Item($currency, $transformer, 'currencies'); - - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -138,7 +105,7 @@ class UpdateController extends Controller * * Make the currency a default currency. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -162,7 +129,36 @@ class UpdateController extends Controller $resource = new Item($currency, $transformer, 'currencies'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); + } + /** + * This endpoint is documented at: + * https://api-docs.firefly-iii.org/#/currencies/enableCurrency + * + * Enable a currency. + * + * @param TransactionCurrency $currency + * + * @return JsonResponse + * @throws FireflyException + * @throws JsonException + * @codeCoverageIgnore + */ + public function enable(TransactionCurrency $currency): JsonResponse + { + $this->repository->enable($currency); + $manager = $this->getManager(); + + $defaultCurrency = app('amount')->getDefaultCurrencyByUser(auth()->user()); + $this->parameters->set('defaultCurrency', $defaultCurrency); + + /** @var CurrencyTransformer $transformer */ + $transformer = app(CurrencyTransformer::class); + $transformer->setParameters($this->parameters); + + $resource = new Item($currency, $transformer, 'currencies'); + + return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } /** @@ -171,8 +167,8 @@ class UpdateController extends Controller * * Update a currency. * - * @param UpdateRequest $request - * @param TransactionCurrency $currency + * @param UpdateRequest $request + * @param TransactionCurrency $currency * * @return JsonResponse * @throws FireflyException @@ -200,6 +196,5 @@ class UpdateController extends Controller $resource = new Item($currency, $transformer, 'currencies'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/TransactionLink/DestroyController.php b/app/Api/V1/Controllers/Models/TransactionLink/DestroyController.php index e531469744..ff5b2cdb1e 100644 --- a/app/Api/V1/Controllers/Models/TransactionLink/DestroyController.php +++ b/app/Api/V1/Controllers/Models/TransactionLink/DestroyController.php @@ -32,7 +32,6 @@ use Illuminate\Http\JsonResponse; class DestroyController extends Controller { - private LinkTypeRepositoryInterface $repository; /** @@ -63,7 +62,7 @@ class DestroyController extends Controller * * Delete the resource. * - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link * * @return JsonResponse * @codeCoverageIgnore @@ -75,5 +74,4 @@ class DestroyController extends Controller return response()->json([], 204); } - } diff --git a/app/Api/V1/Controllers/Models/TransactionLink/ShowController.php b/app/Api/V1/Controllers/Models/TransactionLink/ShowController.php index c54b08610d..aef868534f 100644 --- a/app/Api/V1/Controllers/Models/TransactionLink/ShowController.php +++ b/app/Api/V1/Controllers/Models/TransactionLink/ShowController.php @@ -69,7 +69,7 @@ class ShowController extends Controller * * List all transaction links there are. * - * @param Request $request + * @param Request $request * * @return JsonResponse * @throws FireflyException @@ -83,7 +83,7 @@ class ShowController extends Controller $name = $request->get('name'); // types to get, page size: - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $linkType = $this->repository->findByName($name); // get list of transaction links. Count it and split it. @@ -93,7 +93,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($journalLinks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.transaction_links.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.transaction_links.index').$this->buildParams()); /** @var TransactionLinkTransformer $transformer */ $transformer = app(TransactionLinkTransformer::class); @@ -103,7 +103,6 @@ class ShowController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -112,7 +111,7 @@ class ShowController extends Controller * * List single resource. * - * @param TransactionJournalLink $journalLink + * @param TransactionJournalLink $journalLink * * @return JsonResponse * @codeCoverageIgnore @@ -128,6 +127,5 @@ class ShowController extends Controller $resource = new Item($journalLink, $transformer, 'transaction_links'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/TransactionLink/StoreController.php b/app/Api/V1/Controllers/Models/TransactionLink/StoreController.php index 08eaf6de80..6558cdd423 100644 --- a/app/Api/V1/Controllers/Models/TransactionLink/StoreController.php +++ b/app/Api/V1/Controllers/Models/TransactionLink/StoreController.php @@ -72,7 +72,7 @@ class StoreController extends Controller * * Store new object. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Models/TransactionLink/UpdateController.php b/app/Api/V1/Controllers/Models/TransactionLink/UpdateController.php index e95de834a9..2db52ca859 100644 --- a/app/Api/V1/Controllers/Models/TransactionLink/UpdateController.php +++ b/app/Api/V1/Controllers/Models/TransactionLink/UpdateController.php @@ -69,8 +69,8 @@ class UpdateController extends Controller * * Update object. * - * @param UpdateRequest $request - * @param TransactionJournalLink $journalLink + * @param UpdateRequest $request + * @param TransactionJournalLink $journalLink * * @return JsonResponse */ @@ -87,6 +87,5 @@ class UpdateController extends Controller $resource = new Item($journalLink, $transformer, 'transaction_links'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/TransactionLinkType/DestroyController.php b/app/Api/V1/Controllers/Models/TransactionLinkType/DestroyController.php index a0da83f635..c734e31c66 100644 --- a/app/Api/V1/Controllers/Models/TransactionLinkType/DestroyController.php +++ b/app/Api/V1/Controllers/Models/TransactionLinkType/DestroyController.php @@ -70,7 +70,7 @@ class DestroyController extends Controller * * Delete the resource. * - * @param LinkType $linkType + * @param LinkType $linkType * * @return JsonResponse * @throws FireflyException @@ -86,5 +86,4 @@ class DestroyController extends Controller return response()->json([], 204); } - } diff --git a/app/Api/V1/Controllers/Models/TransactionLinkType/ListController.php b/app/Api/V1/Controllers/Models/TransactionLinkType/ListController.php index d1ae43c0da..52cad81493 100644 --- a/app/Api/V1/Controllers/Models/TransactionLinkType/ListController.php +++ b/app/Api/V1/Controllers/Models/TransactionLinkType/ListController.php @@ -46,7 +46,6 @@ class ListController extends Controller use TransactionFilter; private LinkTypeRepositoryInterface $repository; - private UserRepositoryInterface $userRepository; /** * LinkTypeController constructor. @@ -61,7 +60,6 @@ class ListController extends Controller /** @var User $user */ $user = auth()->user(); $this->repository = app(LinkTypeRepositoryInterface::class); - $this->userRepository = app(UserRepositoryInterface::class); $this->repository->setUser($user); return $next($request); @@ -73,8 +71,8 @@ class ListController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/links/listTransactionByLinkType * - * @param Request $request - * @param LinkType $linkType + * @param Request $request + * @param LinkType $linkType * * @return JsonResponse * @throws FireflyException @@ -82,7 +80,7 @@ class ListController extends Controller */ public function transactions(Request $request, LinkType $linkType): JsonResponse { - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $type = $request->get('type') ?? 'default'; $this->parameters->set('type', $type); @@ -114,7 +112,7 @@ class ListController extends Controller $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); } $paginator = $collector->getPaginatedGroups(); - $paginator->setPath(route('api.v1.transactions.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.transactions.index').$this->buildParams()); $transactions = $paginator->getCollection(); /** @var TransactionGroupTransformer $transformer */ @@ -126,5 +124,4 @@ class ListController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Models/TransactionLinkType/ShowController.php b/app/Api/V1/Controllers/Models/TransactionLinkType/ShowController.php index 5bc8538995..181e1a2962 100644 --- a/app/Api/V1/Controllers/Models/TransactionLinkType/ShowController.php +++ b/app/Api/V1/Controllers/Models/TransactionLinkType/ShowController.php @@ -46,7 +46,6 @@ class ShowController extends Controller use TransactionFilter; private LinkTypeRepositoryInterface $repository; - private UserRepositoryInterface $userRepository; /** * LinkTypeController constructor. @@ -61,7 +60,6 @@ class ShowController extends Controller /** @var User $user */ $user = auth()->user(); $this->repository = app(LinkTypeRepositoryInterface::class); - $this->userRepository = app(UserRepositoryInterface::class); $this->repository->setUser($user); return $next($request); @@ -82,7 +80,7 @@ class ShowController extends Controller { // create some objects: $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; // get list of accounts. Count it and split it. $collection = $this->repository->get(); @@ -91,7 +89,7 @@ class ShowController extends Controller // make paginator: $paginator = new LengthAwarePaginator($linkTypes, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.link_types.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.link_types.index').$this->buildParams()); /** @var LinkTypeTransformer $transformer */ $transformer = app(LinkTypeTransformer::class); @@ -101,7 +99,6 @@ class ShowController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -110,7 +107,7 @@ class ShowController extends Controller * * List single resource. * - * @param LinkType $linkType + * @param LinkType $linkType * * @return JsonResponse * @codeCoverageIgnore @@ -125,6 +122,5 @@ class ShowController extends Controller $resource = new Item($linkType, $transformer, 'link_types'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/TransactionLinkType/StoreController.php b/app/Api/V1/Controllers/Models/TransactionLinkType/StoreController.php index 6a16ca9c34..abd1a748e7 100644 --- a/app/Api/V1/Controllers/Models/TransactionLinkType/StoreController.php +++ b/app/Api/V1/Controllers/Models/TransactionLinkType/StoreController.php @@ -72,7 +72,7 @@ class StoreController extends Controller * * Store new object. * - * @param StoreRequest $request + * @param StoreRequest $request * * @return JsonResponse * @throws FireflyException @@ -96,6 +96,5 @@ class StoreController extends Controller $resource = new Item($linkType, $transformer, 'link_types'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Models/TransactionLinkType/UpdateController.php b/app/Api/V1/Controllers/Models/TransactionLinkType/UpdateController.php index 4eb5ad9ee4..ddd55e6688 100644 --- a/app/Api/V1/Controllers/Models/TransactionLinkType/UpdateController.php +++ b/app/Api/V1/Controllers/Models/TransactionLinkType/UpdateController.php @@ -73,8 +73,8 @@ class UpdateController extends Controller * * Update object. * - * @param UpdateRequest $request - * @param LinkType $linkType + * @param UpdateRequest $request + * @param LinkType $linkType * * @return JsonResponse * @throws FireflyException @@ -102,6 +102,5 @@ class UpdateController extends Controller $resource = new Item($linkType, $transformer, 'link_types'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } } diff --git a/app/Api/V1/Controllers/Search/AccountController.php b/app/Api/V1/Controllers/Search/AccountController.php index 2950b6cf17..e79ba13306 100644 --- a/app/Api/V1/Controllers/Search/AccountController.php +++ b/app/Api/V1/Controllers/Search/AccountController.php @@ -61,7 +61,7 @@ class AccountController extends Controller /** * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/search/searchAccounts - * @param Request $request + * @param Request $request * * @return JsonResponse|Response * @throws JsonException @@ -70,8 +70,8 @@ class AccountController extends Controller { Log::debug('Now in account search()'); $manager = $this->getManager(); - $query = trim((string) $request->get('query')); - $field = trim((string) $request->get('field')); + $query = trim((string)$request->get('query')); + $field = trim((string)$request->get('field')); $type = $request->get('type') ?? 'all'; if ('' === $query || !in_array($field, $this->validFields, true)) { return response(null, 422); diff --git a/app/Api/V1/Controllers/Search/TransactionController.php b/app/Api/V1/Controllers/Search/TransactionController.php index 016af96eda..9255da7713 100644 --- a/app/Api/V1/Controllers/Search/TransactionController.php +++ b/app/Api/V1/Controllers/Search/TransactionController.php @@ -42,8 +42,8 @@ class TransactionController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/search/searchTransactions * - * @param Request $request - * @param SearchInterface $searcher + * @param Request $request + * @param SearchInterface $searcher * * @return JsonResponse * @throws FireflyException @@ -51,16 +51,16 @@ class TransactionController extends Controller public function search(Request $request, SearchInterface $searcher): JsonResponse { $manager = $this->getManager(); - $fullQuery = (string) $request->get('query'); - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; - $pageSize = 0 === (int) $request->get('limit') ? $pageSize : (int) $request->get('limit'); + $fullQuery = (string)$request->get('query'); + $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = 0 === (int)$request->get('limit') ? $pageSize : (int)$request->get('limit'); $searcher->parseQuery($fullQuery); $searcher->setPage($page); $searcher->setLimit($pageSize); $groups = $searcher->searchTransactions(); $parameters = ['search' => $fullQuery]; - $url = route('api.v1.search.transactions') . '?' . http_build_query($parameters); + $url = route('api.v1.search.transactions').'?'.http_build_query($parameters); $groups->setPath($url); $transactions = $groups->getCollection(); diff --git a/app/Api/V1/Controllers/Summary/BasicController.php b/app/Api/V1/Controllers/Summary/BasicController.php index 6a204c99a6..1ea7ef2967 100644 --- a/app/Api/V1/Controllers/Summary/BasicController.php +++ b/app/Api/V1/Controllers/Summary/BasicController.php @@ -90,7 +90,7 @@ class BasicController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/summary/getBasicSummary * - * @param DateRequest $request + * @param DateRequest $request * * @return JsonResponse * @throws Exception @@ -122,8 +122,8 @@ class BasicController extends Controller } /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -148,10 +148,11 @@ class BasicController extends Controller $set = $collector->getExtractedJournals(); /** @var array $transactionJournal */ foreach ($set as $transactionJournal) { - $currencyId = (int) $transactionJournal['currency_id']; + $currencyId = (int)$transactionJournal['currency_id']; $incomes[$currencyId] = $incomes[$currencyId] ?? '0'; - $incomes[$currencyId] = bcadd($incomes[$currencyId], - bcmul($transactionJournal['amount'], '-1') + $incomes[$currencyId] = bcadd( + $incomes[$currencyId], + bcmul($transactionJournal['amount'], '-1') ); $sums[$currencyId] = $sums[$currencyId] ?? '0'; $sums[$currencyId] = bcadd($sums[$currencyId], bcmul($transactionJournal['amount'], '-1')); @@ -170,7 +171,7 @@ class BasicController extends Controller /** @var array $transactionJournal */ foreach ($set as $transactionJournal) { - $currencyId = (int) $transactionJournal['currency_id']; + $currencyId = (int)$transactionJournal['currency_id']; $expenses[$currencyId] = $expenses[$currencyId] ?? '0'; $expenses[$currencyId] = bcadd($expenses[$currencyId], $transactionJournal['amount']); $sums[$currencyId] = $sums[$currencyId] ?? '0'; @@ -188,15 +189,15 @@ class BasicController extends Controller $return[] = [ 'key' => sprintf('balance-in-%s', $currency->code), 'title' => trans('firefly.box_balance_in_currency', ['currency' => $currency->symbol]), - 'monetary_value' => $sums[$currencyId] ?? '0', + 'monetary_value' => $sums[$currencyId] ?? '0', 'currency_id' => $currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, 'currency_decimal_places' => $currency->decimal_places, 'value_parsed' => app('amount')->formatAnything($currency, $sums[$currencyId] ?? '0', false), 'local_icon' => 'balance-scale', - 'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false) . - ' + ' . app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), + 'sub_title' => app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false). + ' + '.app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false), ]; $return[] = [ 'key' => sprintf('spent-in-%s', $currency->code), @@ -228,8 +229,8 @@ class BasicController extends Controller } /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -244,14 +245,14 @@ class BasicController extends Controller $return = []; foreach ($paidAmount as $currencyId => $amount) { $amount = bcmul($amount, '-1'); - $currency = $this->currencyRepos->find((int) $currencyId); + $currency = $this->currencyRepos->find((int)$currencyId); if (null === $currency) { continue; } $return[] = [ 'key' => sprintf('bills-paid-in-%s', $currency->code), 'title' => trans('firefly.box_bill_paid_in_currency', ['currency' => $currency->symbol]), - 'monetary_value' => $amount, + 'monetary_value' => $amount, 'currency_id' => $currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, @@ -264,7 +265,7 @@ class BasicController extends Controller foreach ($unpaidAmount as $currencyId => $amount) { $amount = bcmul($amount, '-1'); - $currency = $this->currencyRepos->find((int) $currencyId); + $currency = $this->currencyRepos->find((int)$currencyId); if (null === $currency) { continue; } @@ -286,8 +287,8 @@ class BasicController extends Controller } /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array * @throws Exception @@ -309,27 +310,29 @@ class BasicController extends Controller $days = $today->diffInDays($end) + 1; $perDay = '0'; if (0 !== $days && bccomp($leftToSpend, '0') > -1) { - $perDay = bcdiv($leftToSpend, (string) $days); + $perDay = bcdiv($leftToSpend, (string)$days); } $return[] = [ 'key' => sprintf('left-to-spend-in-%s', $row['currency_code']), 'title' => trans('firefly.box_left_to_spend_in_currency', ['currency' => $row['currency_symbol']]), - 'monetary_value' => $leftToSpend, + 'monetary_value' => $leftToSpend, 'currency_id' => $row['currency_id'], 'currency_code' => $row['currency_code'], 'currency_symbol' => $row['currency_symbol'], 'currency_decimal_places' => $row['currency_decimal_places'], 'value_parsed' => app('amount')->formatFlat($row['currency_symbol'], $row['currency_decimal_places'], $leftToSpend, false), 'local_icon' => 'money', - 'sub_title' => (string) trans( + 'sub_title' => (string)trans( 'firefly.box_spend_per_day', - ['amount' => app('amount')->formatFlat( - $row['currency_symbol'], - $row['currency_decimal_places'], - $perDay, - false - )] + [ + 'amount' => app('amount')->formatFlat( + $row['currency_symbol'], + $row['currency_decimal_places'], + $perDay, + false + ), + ] ), ]; } @@ -338,8 +341,8 @@ class BasicController extends Controller } /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -357,7 +360,7 @@ class BasicController extends Controller /** @var NetWorthInterface $netWorthHelper */ $netWorthHelper = app(NetWorthInterface::class); $netWorthHelper->setUser($user); - $allAccounts = $this->accountRepository->getActiveAccountsByType([AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE]); + $allAccounts = $this->accountRepository->getActiveAccountsByType([AccountType::ASSET]); // filter list on preference of being included. $filtered = $allAccounts->filter( @@ -373,7 +376,7 @@ class BasicController extends Controller foreach ($netWorthSet as $data) { /** @var TransactionCurrency $currency */ $currency = $data['currency']; - $amount = $data['balance']; + $amount = $data['balance']; if (0 === bccomp($amount, '0')) { continue; } @@ -398,10 +401,10 @@ class BasicController extends Controller /** * Check if date is outside session range. * - * @param Carbon $date + * @param Carbon $date * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return bool */ diff --git a/app/Api/V1/Controllers/System/AboutController.php b/app/Api/V1/Controllers/System/AboutController.php index 8c2cf0995a..b78a995d3f 100644 --- a/app/Api/V1/Controllers/System/AboutController.php +++ b/app/Api/V1/Controllers/System/AboutController.php @@ -62,7 +62,7 @@ class AboutController extends Controller 'driver' => $currentDriver, ]; - return response()->json(['data' => $data])->header('Content-Type', self::CONTENT_TYPE); + return response()->api(['data' => $data])->header('Content-Type', self::CONTENT_TYPE); } /** @@ -83,6 +83,6 @@ class AboutController extends Controller $resource = new Item(auth()->user(), $transformer, 'users'); - return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); + return response()->api($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } } diff --git a/app/Api/V1/Controllers/System/ConfigurationController.php b/app/Api/V1/Controllers/System/ConfigurationController.php index 552a901336..eb5f4437fd 100644 --- a/app/Api/V1/Controllers/System/ConfigurationController.php +++ b/app/Api/V1/Controllers/System/ConfigurationController.php @@ -108,8 +108,8 @@ class ConfigurationController extends Controller return [ 'is_demo_site' => $isDemoSite?->data, - 'permission_update_check' => null === $updateCheck ? null : (int) $updateCheck->data, - 'last_update_check' => null === $lastCheck ? null : (int) $lastCheck->data, + 'permission_update_check' => null === $updateCheck ? null : (int)$updateCheck->data, + 'last_update_check' => null === $lastCheck ? null : (int)$lastCheck->data, 'single_user_mode' => $singleUser?->data, ]; } @@ -132,7 +132,7 @@ class ConfigurationController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/configuration/getSingleConfiguration * - * @param string $configKey + * @param string $configKey * * @return JsonResponse * @throws FireflyException @@ -166,8 +166,8 @@ class ConfigurationController extends Controller * * Update the configuration. * - * @param UpdateRequest $request - * @param string $name + * @param UpdateRequest $request + * @param string $name * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/System/CronController.php b/app/Api/V1/Controllers/System/CronController.php index aac11c2447..c76a39c097 100644 --- a/app/Api/V1/Controllers/System/CronController.php +++ b/app/Api/V1/Controllers/System/CronController.php @@ -40,8 +40,8 @@ class CronController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/about/getCron * - * @param CronRequest $request - * @param string $token + * @param CronRequest $request + * @param string $token * * @return JsonResponse */ @@ -57,5 +57,4 @@ class CronController extends Controller return response()->json($return); } - } diff --git a/app/Api/V1/Controllers/System/UserController.php b/app/Api/V1/Controllers/System/UserController.php index c36eeb03c2..b96ea03f24 100644 --- a/app/Api/V1/Controllers/System/UserController.php +++ b/app/Api/V1/Controllers/System/UserController.php @@ -67,7 +67,7 @@ class UserController extends Controller * * Remove the specified resource from storage. * - * @param User $user + * @param User $user * * @return JsonResponse * @throws FireflyException @@ -102,7 +102,7 @@ class UserController extends Controller public function index(): JsonResponse { // user preferences - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $manager = $this->getManager(); // build collection @@ -112,7 +112,7 @@ class UserController extends Controller // make paginator: $paginator = new LengthAwarePaginator($users, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.users.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.users.index').$this->buildParams()); // make resource /** @var UserTransformer $transformer */ @@ -131,7 +131,7 @@ class UserController extends Controller * * Show a single user. * - * @param User $user + * @param User $user * * @return JsonResponse * @codeCoverageIgnore @@ -156,7 +156,7 @@ class UserController extends Controller * * Store a new user. * - * @param UserStoreRequest $request + * @param UserStoreRequest $request * * @return JsonResponse */ @@ -183,8 +183,8 @@ class UserController extends Controller * * Update a user. * - * @param UserUpdateRequest $request - * @param User $user + * @param UserUpdateRequest $request + * @param User $user * * @return JsonResponse */ @@ -201,7 +201,5 @@ class UserController extends Controller $resource = new Item($user, $transformer, 'users'); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } - } diff --git a/app/Api/V1/Controllers/User/PreferencesController.php b/app/Api/V1/Controllers/User/PreferencesController.php index 08650f24ae..4baf172ba3 100644 --- a/app/Api/V1/Controllers/User/PreferencesController.php +++ b/app/Api/V1/Controllers/User/PreferencesController.php @@ -59,12 +59,12 @@ class PreferencesController extends Controller $collection = app('preferences')->all(); $manager = $this->getManager(); $count = $collection->count(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $preferences = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); // make paginator: $paginator = new LengthAwarePaginator($preferences, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.preferences.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.preferences.index').$this->buildParams()); /** @var PreferenceTransformer $transformer */ $transformer = app(PreferenceTransformer::class); @@ -74,7 +74,6 @@ class PreferencesController extends Controller $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); - } /** @@ -83,7 +82,7 @@ class PreferencesController extends Controller * * Return a single preference by name. * - * @param Preference $preference + * @param Preference $preference * * @return JsonResponse * @codeCoverageIgnore @@ -104,7 +103,7 @@ class PreferencesController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/preferences/storePreference * - * @param PreferenceStoreRequest $request + * @param PreferenceStoreRequest $request * * @return JsonResponse * @throws FireflyException @@ -128,8 +127,8 @@ class PreferencesController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/preferences/updatePreference * - * @param PreferenceUpdateRequest $request - * @param Preference $preference + * @param PreferenceUpdateRequest $request + * @param Preference $preference * * @return JsonResponse * @throws FireflyException @@ -148,5 +147,4 @@ class PreferencesController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Webhook/AttemptController.php b/app/Api/V1/Controllers/Webhook/AttemptController.php index 3d80cad8d7..7b705a0a6a 100644 --- a/app/Api/V1/Controllers/Webhook/AttemptController.php +++ b/app/Api/V1/Controllers/Webhook/AttemptController.php @@ -64,8 +64,8 @@ class AttemptController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/webhooks/getWebhookMessageAttempts * - * @param Webhook $webhook - * @param WebhookMessage $message + * @param Webhook $webhook + * @param WebhookMessage $message * * @return JsonResponse * @throws FireflyException @@ -77,14 +77,14 @@ class AttemptController extends Controller } $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getAttempts($message); $count = $collection->count(); $attempts = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); // make paginator: $paginator = new LengthAwarePaginator($attempts, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.webhooks.attempts.index', [$webhook->id, $message->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.webhooks.attempts.index', [$webhook->id, $message->id]).$this->buildParams()); /** @var WebhookAttemptTransformer $transformer */ $transformer = app(WebhookAttemptTransformer::class); @@ -102,9 +102,9 @@ class AttemptController extends Controller * * Show single instance. * - * @param Webhook $webhook - * @param WebhookMessage $message - * @param WebhookAttempt $attempt + * @param Webhook $webhook + * @param WebhookMessage $message + * @param WebhookAttempt $attempt * * @return JsonResponse * @throws FireflyException @@ -116,7 +116,6 @@ class AttemptController extends Controller } if ($attempt->webhook_message_id !== $message->id) { throw new FireflyException('Webhook message and webhook attempt are no match'); - } $manager = $this->getManager(); diff --git a/app/Api/V1/Controllers/Webhook/DestroyController.php b/app/Api/V1/Controllers/Webhook/DestroyController.php index c2b0715b59..329e9f5e56 100644 --- a/app/Api/V1/Controllers/Webhook/DestroyController.php +++ b/app/Api/V1/Controllers/Webhook/DestroyController.php @@ -61,7 +61,7 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param Webhook $webhook + * @param Webhook $webhook * * @return JsonResponse * @codeCoverageIgnore @@ -80,9 +80,9 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param Webhook $webhook - * @param WebhookMessage $message - * @param WebhookAttempt $attempt + * @param Webhook $webhook + * @param WebhookMessage $message + * @param WebhookAttempt $attempt * * @return JsonResponse * @throws FireflyException @@ -95,7 +95,6 @@ class DestroyController extends Controller } if ($attempt->webhook_message_id !== $message->id) { throw new FireflyException('Webhook message and webhook attempt are no match'); - } $this->repository->destroyAttempt($attempt); @@ -110,8 +109,8 @@ class DestroyController extends Controller * * Remove the specified resource from storage. * - * @param Webhook $webhook - * @param WebhookMessage $message + * @param Webhook $webhook + * @param WebhookMessage $message * * @return JsonResponse * @throws FireflyException diff --git a/app/Api/V1/Controllers/Webhook/MessageController.php b/app/Api/V1/Controllers/Webhook/MessageController.php index b9fd26272e..54a77fd2c5 100644 --- a/app/Api/V1/Controllers/Webhook/MessageController.php +++ b/app/Api/V1/Controllers/Webhook/MessageController.php @@ -60,7 +60,7 @@ class MessageController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/webhooks/getWebhookMessages * - * @param Webhook $webhook + * @param Webhook $webhook * * @return JsonResponse * @throws FireflyException @@ -68,7 +68,7 @@ class MessageController extends Controller public function index(Webhook $webhook): JsonResponse { $manager = $this->getManager(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $collection = $this->repository->getMessages($webhook); $count = $collection->count(); @@ -76,7 +76,7 @@ class MessageController extends Controller // make paginator: $paginator = new LengthAwarePaginator($messages, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.webhooks.messages.index', [$webhook->id]) . $this->buildParams()); + $paginator->setPath(route('api.v1.webhooks.messages.index', [$webhook->id]).$this->buildParams()); /** @var WebhookMessageTransformer $transformer */ $transformer = app(WebhookMessageTransformer::class); @@ -94,8 +94,8 @@ class MessageController extends Controller * * Show single instance. * - * @param Webhook $webhook - * @param WebhookMessage $message + * @param Webhook $webhook + * @param WebhookMessage $message * * @return JsonResponse * @throws FireflyException @@ -115,5 +115,4 @@ class MessageController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Controllers/Webhook/ShowController.php b/app/Api/V1/Controllers/Webhook/ShowController.php index 22550f00e3..817ecb8dcf 100644 --- a/app/Api/V1/Controllers/Webhook/ShowController.php +++ b/app/Api/V1/Controllers/Webhook/ShowController.php @@ -24,12 +24,18 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Controllers\Webhook; use FireflyIII\Api\V1\Controllers\Controller; +use FireflyIII\Enums\WebhookTrigger; +use FireflyIII\Events\RequestedSendWebhookMessages; +use FireflyIII\Events\StoredTransactionGroup; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Generator\Webhook\MessageGeneratorInterface; +use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\Webhook; use FireflyIII\Repositories\Webhook\WebhookRepositoryInterface; use FireflyIII\Transformers\WebhookTransformer; use Illuminate\Http\JsonResponse; use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Support\Collection; use League\Fractal\Pagination\IlluminatePaginatorAdapter; use League\Fractal\Resource\Collection as FractalCollection; use League\Fractal\Resource\Item; @@ -72,13 +78,13 @@ class ShowController extends Controller { $manager = $this->getManager(); $collection = $this->repository->all(); - $pageSize = (int) app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + $pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; $count = $collection->count(); $webhooks = $collection->slice(($this->parameters->get('page') - 1) * $pageSize, $pageSize); // make paginator: $paginator = new LengthAwarePaginator($webhooks, $count, $pageSize, $this->parameters->get('page')); - $paginator->setPath(route('api.v1.webhooks.index') . $this->buildParams()); + $paginator->setPath(route('api.v1.webhooks.index').$this->buildParams()); /** @var WebhookTransformer $transformer */ $transformer = app(WebhookTransformer::class); @@ -96,7 +102,7 @@ class ShowController extends Controller * * Show single instance. * - * @param Webhook $webhook + * @param Webhook $webhook * * @return JsonResponse */ @@ -111,4 +117,35 @@ class ShowController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } + + /** + * This endpoint is documented at: + * https://api-docs.firefly-iii.org/#/webhooks/triggerWebhookTransaction + * + * This method recycles part of the code of the StoredGroupEventHandler. + * + * @param Webhook $webhook + * @param TransactionGroup $group + * @return JsonResponse + */ + public function triggerTransaction(Webhook $webhook, TransactionGroup $group): JsonResponse + { + /** @var MessageGeneratorInterface $engine */ + $engine = app(MessageGeneratorInterface::class); + $engine->setUser(auth()->user()); + + // tell the generator which trigger it should look for + $engine->setTrigger($webhook->trigger); + // tell the generator which objects to process + $engine->setObjects(new Collection([$group])); + // set the webhook to trigger + $engine->setWebhooks(new Collection([$webhook])); + // tell the generator to generate the messages + $engine->generateMessages(); + + // trigger event to send them: + event(new RequestedSendWebhookMessages()); + return response()->json([], 204); + + } } diff --git a/app/Api/V1/Controllers/Webhook/StoreController.php b/app/Api/V1/Controllers/Webhook/StoreController.php index a55a8659cd..057e1a8c25 100644 --- a/app/Api/V1/Controllers/Webhook/StoreController.php +++ b/app/Api/V1/Controllers/Webhook/StoreController.php @@ -58,7 +58,7 @@ class StoreController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/webhooks/storeWebhook * - * @param CreateRequest $request + * @param CreateRequest $request * * @return JsonResponse */ diff --git a/app/Api/V1/Controllers/Webhook/SubmitController.php b/app/Api/V1/Controllers/Webhook/SubmitController.php index 989a118b26..8c5cd1b391 100644 --- a/app/Api/V1/Controllers/Webhook/SubmitController.php +++ b/app/Api/V1/Controllers/Webhook/SubmitController.php @@ -56,9 +56,7 @@ class SubmitController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/webhooks/submitWebook * - * Remove the specified resource from storage. - * - * @param Webhook $webhook + * @param Webhook $webhook * * @return JsonResponse * @codeCoverageIgnore diff --git a/app/Api/V1/Controllers/Webhook/UpdateController.php b/app/Api/V1/Controllers/Webhook/UpdateController.php index 2ac56df45d..54b9f850d0 100644 --- a/app/Api/V1/Controllers/Webhook/UpdateController.php +++ b/app/Api/V1/Controllers/Webhook/UpdateController.php @@ -58,8 +58,8 @@ class UpdateController extends Controller * This endpoint is documented at: * https://api-docs.firefly-iii.org/#/webhooks/updateWebhook * - * @param Webhook $webhook - * @param UpdateRequest $request + * @param Webhook $webhook + * @param UpdateRequest $request * * @return JsonResponse */ @@ -76,5 +76,4 @@ class UpdateController extends Controller return response()->json($manager->createData($resource)->toArray())->header('Content-Type', self::CONTENT_TYPE); } - } diff --git a/app/Api/V1/Middleware/ApiDemoUser.php b/app/Api/V1/Middleware/ApiDemoUser.php index 46cecc1966..2573ee939d 100644 --- a/app/Api/V1/Middleware/ApiDemoUser.php +++ b/app/Api/V1/Middleware/ApiDemoUser.php @@ -1,4 +1,5 @@ hasRole('demo')) { return response('', 403); - } return $next($request); diff --git a/app/Api/V1/Requests/Autocomplete/AutocompleteRequest.php b/app/Api/V1/Requests/Autocomplete/AutocompleteRequest.php index c023c500fc..5d071fe7b6 100644 --- a/app/Api/V1/Requests/Autocomplete/AutocompleteRequest.php +++ b/app/Api/V1/Requests/Autocomplete/AutocompleteRequest.php @@ -33,7 +33,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class AutocompleteRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * @return array diff --git a/app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php b/app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php index 30afe54219..2f73415dd2 100644 --- a/app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php +++ b/app/Api/V1/Requests/Data/Bulk/MoveTransactionsRequest.php @@ -35,7 +35,8 @@ use Illuminate\Validation\Validator; */ class MoveTransactionsRequest extends FormRequest { - use ChecksLogin, ConvertsDataTypes; + use ChecksLogin; + use ConvertsDataTypes; /** * @return array @@ -62,8 +63,8 @@ class MoveTransactionsRequest extends FormRequest /** * Configure the validator instance with special rules for after the basic validation rules. * - * @param Validator $validator - * See reference nr. 74 + * @param Validator $validator + * TODO this is duplicate. * * @return void */ @@ -81,19 +82,20 @@ class MoveTransactionsRequest extends FormRequest } /** - * @param Validator $validator + * @param Validator $validator * @return void */ - private function validateMove(Validator $validator): void { - $data = $validator->getData(); + private function validateMove(Validator $validator): void + { + $data = $validator->getData(); $repository = app(AccountRepositoryInterface::class); $repository->setUser(auth()->user()); - $original = $repository->find((int) $data['original_account']); - $destination = $repository->find((int) $data['destination_account']); + $original = $repository->find((int)$data['original_account']); + $destination = $repository->find((int)$data['destination_account']); // not the same type: if ($original->accountType->type !== $destination->accountType->type) { - $validator->errors()->add('title', (string) trans('validation.same_account_type')); + $validator->errors()->add('title', (string)trans('validation.same_account_type')); return; } @@ -103,7 +105,7 @@ class MoveTransactionsRequest extends FormRequest // check different scenario's. if (null === $originalCurrency xor null === $destinationCurrency) { - $validator->errors()->add('title', (string) trans('validation.same_account_currency')); + $validator->errors()->add('title', (string)trans('validation.same_account_currency')); return; } @@ -112,7 +114,7 @@ class MoveTransactionsRequest extends FormRequest return; } if ($originalCurrency->code !== $destinationCurrency->code) { - $validator->errors()->add('title', (string) trans('validation.same_account_currency')); + $validator->errors()->add('title', (string)trans('validation.same_account_currency')); } } } diff --git a/app/Api/V1/Requests/Data/Bulk/TransactionRequest.php b/app/Api/V1/Requests/Data/Bulk/TransactionRequest.php index 02e013fdea..df540c26db 100644 --- a/app/Api/V1/Requests/Data/Bulk/TransactionRequest.php +++ b/app/Api/V1/Requests/Data/Bulk/TransactionRequest.php @@ -39,7 +39,9 @@ use Log; */ class TransactionRequest extends FormRequest { - use ChecksLogin, ConvertsDataTypes, ValidatesBulkTransactionQuery; + use ChecksLogin; + use ConvertsDataTypes; + use ValidatesBulkTransactionQuery; /** * @return array @@ -60,7 +62,7 @@ class TransactionRequest extends FormRequest } /** - * @return string[] + * @return array */ public function rules(): array { @@ -70,7 +72,7 @@ class TransactionRequest extends FormRequest } /** - * @param Validator $validator + * @param Validator $validator * * @return void */ diff --git a/app/Api/V1/Requests/Data/DateRequest.php b/app/Api/V1/Requests/Data/DateRequest.php index ead7ffc4e2..a6e1cdf23b 100644 --- a/app/Api/V1/Requests/Data/DateRequest.php +++ b/app/Api/V1/Requests/Data/DateRequest.php @@ -35,7 +35,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class DateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. diff --git a/app/Api/V1/Requests/Data/DestroyRequest.php b/app/Api/V1/Requests/Data/DestroyRequest.php index 2bc93dbb56..bc8026c703 100644 --- a/app/Api/V1/Requests/Data/DestroyRequest.php +++ b/app/Api/V1/Requests/Data/DestroyRequest.php @@ -32,7 +32,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class DestroyRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -51,11 +52,12 @@ class DestroyRequest extends FormRequest */ public function rules(): array { - $valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups' . + $valid = 'budgets,bills,piggy_banks,rules,recurring,categories,tags,object_groups'. ',accounts,asset_accounts,expense_accounts,revenue_accounts,liabilities,transactions,withdrawals,deposits,transfers'; return [ 'objects' => sprintf('required|min:1|string|in:%s', $valid), + 'unused' => 'in:true,false', ]; } } diff --git a/app/Api/V1/Requests/Data/Export/ExportRequest.php b/app/Api/V1/Requests/Data/Export/ExportRequest.php index 0ada44dce7..ce41ef1bc3 100644 --- a/app/Api/V1/Requests/Data/Export/ExportRequest.php +++ b/app/Api/V1/Requests/Data/Export/ExportRequest.php @@ -36,7 +36,8 @@ use Illuminate\Support\Collection; */ class ExportRequest extends FormRequest { - use ChecksLogin, ConvertsDataTypes; + use ChecksLogin; + use ConvertsDataTypes; public function getAll(): array { @@ -49,9 +50,9 @@ class ExportRequest extends FormRequest $repository = app(AccountRepositoryInterface::class); $repository->setUser(auth()->user()); - $accounts = new Collection; + $accounts = new Collection(); foreach ($parts as $part) { - $accountId = (int) $part; + $accountId = (int)$part; if (0 !== $accountId) { $account = $repository->find($accountId); if (null !== $account && AccountType::ASSET === $account->accountType->type) { diff --git a/app/Api/V1/Requests/Insight/GenericRequest.php b/app/Api/V1/Requests/Insight/GenericRequest.php index 5a10d23e7d..3e9f3b255e 100644 --- a/app/Api/V1/Requests/Insight/GenericRequest.php +++ b/app/Api/V1/Requests/Insight/GenericRequest.php @@ -42,7 +42,8 @@ use Illuminate\Support\Collection; */ class GenericRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; private Collection $accounts; private Collection $bills; @@ -69,11 +70,11 @@ class GenericRequest extends FormRequest public function getAssetAccounts(): Collection { $this->parseAccounts(); - $return = new Collection; + $return = new Collection(); /** @var Account $account */ foreach ($this->accounts as $account) { $type = $account->accountType->type; - if (in_array($type, [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE])) { + if (in_array($type, [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], true)) { $return->push($account); } } @@ -94,7 +95,7 @@ class GenericRequest extends FormRequest $array = $this->get('accounts'); if (is_array($array)) { foreach ($array as $accountId) { - $accountId = (int) $accountId; + $accountId = (int)$accountId; $account = $repository->find($accountId); if (null !== $account) { $this->accounts->push($account); @@ -126,7 +127,7 @@ class GenericRequest extends FormRequest $array = $this->get('bills'); if (is_array($array)) { foreach ($array as $billId) { - $billId = (int) $billId; + $billId = (int)$billId; $bill = $repository->find($billId); if (null !== $bill) { $this->bills->push($bill); @@ -158,7 +159,7 @@ class GenericRequest extends FormRequest $array = $this->get('budgets'); if (is_array($array)) { foreach ($array as $budgetId) { - $budgetId = (int) $budgetId; + $budgetId = (int)$budgetId; $budget = $repository->find($budgetId); if (null !== $budget) { $this->budgets->push($budget); @@ -190,7 +191,7 @@ class GenericRequest extends FormRequest $array = $this->get('categories'); if (is_array($array)) { foreach ($array as $categoryId) { - $categoryId = (int) $categoryId; + $categoryId = (int)$categoryId; $category = $repository->find($categoryId); if (null !== $category) { $this->categories->push($category); @@ -216,7 +217,7 @@ class GenericRequest extends FormRequest public function getExpenseAccounts(): Collection { $this->parseAccounts(); - $return = new Collection; + $return = new Collection(); /** @var Account $account */ foreach ($this->accounts as $account) { $type = $account->accountType->type; @@ -234,7 +235,7 @@ class GenericRequest extends FormRequest public function getRevenueAccounts(): Collection { $this->parseAccounts(); - $return = new Collection; + $return = new Collection(); /** @var Account $account */ foreach ($this->accounts as $account) { $type = $account->accountType->type; @@ -280,7 +281,7 @@ class GenericRequest extends FormRequest $array = $this->get('tags'); if (is_array($array)) { foreach ($array as $tagId) { - $tagId = (int) $tagId; + $tagId = (int)$tagId; $tag = $repository->find($tagId); if (null !== $tag) { $this->tags->push($tag); @@ -297,11 +298,11 @@ class GenericRequest extends FormRequest public function rules(): array { // this is cheating but it works to initialize the collections. - $this->accounts = new Collection; - $this->budgets = new Collection; - $this->categories = new Collection; - $this->bills = new Collection; - $this->tags = new Collection; + $this->accounts = new Collection(); + $this->budgets = new Collection(); + $this->categories = new Collection(); + $this->bills = new Collection(); + $this->tags = new Collection(); return [ 'start' => 'required|date', diff --git a/app/Api/V1/Requests/Models/Account/StoreRequest.php b/app/Api/V1/Requests/Models/Account/StoreRequest.php index e198c0a88a..e758863e66 100644 --- a/app/Api/V1/Requests/Models/Account/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Account/StoreRequest.php @@ -40,7 +40,9 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, AppendsLocationData, ChecksLogin; + use ConvertsDataTypes; + use AppendsLocationData; + use ChecksLogin; /** * @return array @@ -104,7 +106,7 @@ class StoreRequest extends FormRequest $type = $this->convertString('type'); $rules = [ 'name' => 'required|min:1|uniqueAccountForUser', - 'type' => 'required|' . sprintf('in:%s', $types), + 'type' => 'required|min:1|'.sprintf('in:%s', $types), 'iban' => ['iban', 'nullable', new UniqueIban(null, $type)], 'bic' => 'bic|nullable', 'account_number' => ['between:1,255', 'nullable', new UniqueAccountNumber(null, $type)], @@ -114,8 +116,8 @@ class StoreRequest extends FormRequest 'order' => 'numeric|nullable', 'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', - 'active' => [new IsBoolean], - 'include_net_worth' => [new IsBoolean], + 'active' => [new IsBoolean()], + 'include_net_worth' => [new IsBoolean()], 'account_role' => sprintf('nullable|in:%s|required_if:type,asset', $accountRoles), 'credit_card_type' => sprintf('nullable|in:%s|required_if:account_role,ccAsset', $ccPaymentTypes), 'monthly_payment_date' => 'nullable|date|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull', diff --git a/app/Api/V1/Requests/Models/Account/UpdateRequest.php b/app/Api/V1/Requests/Models/Account/UpdateRequest.php index 83c852a837..1bacf98792 100644 --- a/app/Api/V1/Requests/Models/Account/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Account/UpdateRequest.php @@ -42,7 +42,9 @@ use Log; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, AppendsLocationData, ChecksLogin; + use ConvertsDataTypes; + use AppendsLocationData; + use ChecksLogin; /** * @return array @@ -99,6 +101,7 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var Account $account */ $account = $this->route()->parameter('account'); $accountRoles = implode(',', config('firefly.accountRoles')); $types = implode(',', array_keys(config('firefly.subTitlesByIdentifier'))); @@ -116,11 +119,11 @@ class UpdateRequest extends FormRequest 'order' => 'numeric|nullable', 'currency_id' => 'numeric|exists:transaction_currencies,id', 'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', - 'active' => [new IsBoolean], - 'include_net_worth' => [new IsBoolean], + 'active' => [new IsBoolean()], + 'include_net_worth' => [new IsBoolean()], 'account_role' => sprintf('in:%s|nullable|required_if:type,asset', $accountRoles), 'credit_card_type' => sprintf('in:%s|nullable|required_if:account_role,ccAsset', $ccPaymentTypes), - 'monthly_payment_date' => 'date' . '|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull', + 'monthly_payment_date' => 'date'.'|nullable|required_if:account_role,ccAsset|required_if:credit_card_type,monthlyFull', 'liability_type' => 'required_if:type,liability|in:loan,debt,mortgage', 'liability_direction' => 'required_if:type,liability|in:credit,debit', 'interest' => 'required_if:type,liability|between:0,100|numeric', diff --git a/app/Api/V1/Requests/Models/Attachment/StoreRequest.php b/app/Api/V1/Requests/Models/Attachment/StoreRequest.php index 96fa752803..cfd78e9291 100644 --- a/app/Api/V1/Requests/Models/Attachment/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Attachment/StoreRequest.php @@ -35,7 +35,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -62,10 +63,10 @@ class StoreRequest extends FormRequest { $models = config('firefly.valid_attachment_models'); $models = array_map( - static function (string $className) { return str_replace('FireflyIII\\Models\\', '', $className); - }, $models + }, + $models ); $models = implode(',', $models); $model = $this->convertString('attachable_type'); diff --git a/app/Api/V1/Requests/Models/Attachment/UpdateRequest.php b/app/Api/V1/Requests/Models/Attachment/UpdateRequest.php index 0727ea50c9..d3d50b5811 100644 --- a/app/Api/V1/Requests/Models/Attachment/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Attachment/UpdateRequest.php @@ -35,7 +35,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -64,10 +65,10 @@ class UpdateRequest extends FormRequest { $models = config('firefly.valid_attachment_models'); $models = array_map( - static function (string $className) { return str_replace('FireflyIII\\Models\\', '', $className); - }, $models + }, + $models ); $models = implode(',', $models); $model = $this->convertString('attachable_type'); diff --git a/app/Api/V1/Requests/Models/AvailableBudget/Request.php b/app/Api/V1/Requests/Models/AvailableBudget/Request.php index 694015c1cf..3e7fcb126a 100644 --- a/app/Api/V1/Requests/Models/AvailableBudget/Request.php +++ b/app/Api/V1/Requests/Models/AvailableBudget/Request.php @@ -36,7 +36,8 @@ use Illuminate\Validation\Validator; */ class Request extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -76,7 +77,7 @@ class Request extends FormRequest /** * Configure the validator instance with special rules for after the basic validation rules. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -90,7 +91,7 @@ class Request extends FormRequest $start = new Carbon($data['start']); $end = new Carbon($data['end']); if ($end->isBefore($start)) { - $validator->errors()->add('end', (string) trans('validation.date_after')); + $validator->errors()->add('end', (string)trans('validation.date_after')); } } } diff --git a/app/Api/V1/Requests/Models/Bill/StoreRequest.php b/app/Api/V1/Requests/Models/Bill/StoreRequest.php index e227803368..deb73635c0 100644 --- a/app/Api/V1/Requests/Models/Bill/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Bill/StoreRequest.php @@ -38,7 +38,8 @@ use Log; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -87,7 +88,7 @@ class StoreRequest extends FormRequest 'extension_date' => 'date|after:date', 'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly|required', 'skip' => 'between:0,31', - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], 'notes' => 'between:1,65536', ]; } @@ -95,7 +96,7 @@ class StoreRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -108,7 +109,7 @@ class StoreRequest extends FormRequest $max = $data['amount_max'] ?? '0'; if (1 === bccomp($min, $max)) { - $validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max')); + $validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max')); } } ); diff --git a/app/Api/V1/Requests/Models/Bill/UpdateRequest.php b/app/Api/V1/Requests/Models/Bill/UpdateRequest.php index a4d8bb5146..26de59a084 100644 --- a/app/Api/V1/Requests/Models/Bill/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Bill/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Bill; +use FireflyIII\Models\Bill; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -37,7 +38,8 @@ use Illuminate\Validation\Validator; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -74,6 +76,7 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var Bill $bill */ $bill = $this->route()->parameter('bill'); return [ @@ -87,7 +90,7 @@ class UpdateRequest extends FormRequest 'extension_date' => 'date|after:date', 'repeat_freq' => 'in:weekly,monthly,quarterly,half-year,yearly', 'skip' => 'between:0,31', - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], 'notes' => 'between:1,65536', ]; } @@ -95,7 +98,7 @@ class UpdateRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -105,11 +108,11 @@ class UpdateRequest extends FormRequest static function (Validator $validator) { $data = $validator->getData(); if (array_key_exists('amount_min', $data) && array_key_exists('amount_max', $data)) { - $min = $data['amount_min'] ?? '0'; - $max = $data['amount_max'] ?? '0'; + $min = $data['amount_min'] ?? '0'; + $max = $data['amount_max'] ?? '0'; if (1 === bccomp($min, $max)) { - $validator->errors()->add('amount_min', (string) trans('validation.amount_min_over_max')); + $validator->errors()->add('amount_min', (string)trans('validation.amount_min_over_max')); } } } diff --git a/app/Api/V1/Requests/Models/Budget/StoreRequest.php b/app/Api/V1/Requests/Models/Budget/StoreRequest.php index 0398b7e5b5..c5344bb8b7 100644 --- a/app/Api/V1/Requests/Models/Budget/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Budget/StoreRequest.php @@ -37,7 +37,9 @@ use Illuminate\Validation\Validator; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ValidatesAutoBudgetRequest, ChecksLogin; + use ConvertsDataTypes; + use ValidatesAutoBudgetRequest; + use ChecksLogin; /** * Get all data from the request. @@ -72,7 +74,7 @@ class StoreRequest extends FormRequest { return [ 'name' => 'required|between:1,100|uniqueObjectForUser:budgets,name', - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], 'currency_id' => 'exists:transaction_currencies,id', 'currency_code' => 'exists:transaction_currencies,code', 'notes' => 'nullable|between:1,65536', @@ -86,7 +88,7 @@ class StoreRequest extends FormRequest /** * Configure the validator instance with special rules for after the basic validation rules. * - * @param Validator $validator + * @param Validator $validator * * @return void */ diff --git a/app/Api/V1/Requests/Models/Budget/UpdateRequest.php b/app/Api/V1/Requests/Models/Budget/UpdateRequest.php index 230edd7cd9..46550b434e 100644 --- a/app/Api/V1/Requests/Models/Budget/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Budget/UpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Budget; +use FireflyIII\Models\Budget; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -37,7 +38,9 @@ use Illuminate\Validation\Validator; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ValidatesAutoBudgetRequest, ChecksLogin; + use ConvertsDataTypes; + use ValidatesAutoBudgetRequest; + use ChecksLogin; /** * Get all data from the request. @@ -78,11 +81,12 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var Budget $budget */ $budget = $this->route()->parameter('budget'); return [ 'name' => sprintf('between:1,100|uniqueObjectForUser:budgets,name,%d', $budget->id), - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], 'notes' => 'nullable|between:1,65536', 'auto_budget_type' => 'in:reset,rollover,none', 'auto_budget_currency_id' => 'exists:transaction_currencies,id', @@ -95,7 +99,7 @@ class UpdateRequest extends FormRequest /** * Configure the validator instance with special rules for after the basic validation rules. * - * @param Validator $validator + * @param Validator $validator * * @return void */ diff --git a/app/Api/V1/Requests/Models/BudgetLimit/StoreRequest.php b/app/Api/V1/Requests/Models/BudgetLimit/StoreRequest.php index f2d98b5017..247697e707 100644 --- a/app/Api/V1/Requests/Models/BudgetLimit/StoreRequest.php +++ b/app/Api/V1/Requests/Models/BudgetLimit/StoreRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -67,5 +68,4 @@ class StoreRequest extends FormRequest 'currency_code' => 'min:3|max:3|exists:transaction_currencies,code', ]; } - } diff --git a/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php b/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php index abc6936abc..02aab4659d 100644 --- a/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/BudgetLimit/UpdateRequest.php @@ -36,7 +36,8 @@ use Illuminate\Validation\Validator; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -75,8 +76,8 @@ class UpdateRequest extends FormRequest /** * Configure the validator instance with special rules for after the basic validation rules. * - * @param Validator $validator - * See reference nr. 72 + * @param Validator $validator + * TODO duplicate code * * @return void */ @@ -90,11 +91,10 @@ class UpdateRequest extends FormRequest $start = new Carbon($data['start']); $end = new Carbon($data['end']); if ($end->isBefore($start)) { - $validator->errors()->add('end', (string) trans('validation.date_after')); + $validator->errors()->add('end', (string)trans('validation.date_after')); } } } ); } - } diff --git a/app/Api/V1/Requests/Models/Category/StoreRequest.php b/app/Api/V1/Requests/Models/Category/StoreRequest.php index bebfee1438..8a5512f2f3 100644 --- a/app/Api/V1/Requests/Models/Category/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Category/StoreRequest.php @@ -35,7 +35,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. diff --git a/app/Api/V1/Requests/Models/Category/UpdateRequest.php b/app/Api/V1/Requests/Models/Category/UpdateRequest.php index 827df56734..25d3e3d86f 100644 --- a/app/Api/V1/Requests/Models/Category/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Category/UpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Category; +use FireflyIII\Models\Category; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; @@ -34,7 +35,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -58,6 +60,7 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var Category $category */ $category = $this->route()->parameter('category'); return [ diff --git a/app/Api/V1/Requests/Models/ObjectGroup/UpdateRequest.php b/app/Api/V1/Requests/Models/ObjectGroup/UpdateRequest.php index e0c3e12c66..1303cf21f1 100644 --- a/app/Api/V1/Requests/Models/ObjectGroup/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/ObjectGroup/UpdateRequest.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\ObjectGroup; +use FireflyIII\Models\ObjectGroup; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; @@ -35,7 +36,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * @return array @@ -57,6 +59,7 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var ObjectGroup $objectGroup */ $objectGroup = $this->route()->parameter('objectGroup'); return [ diff --git a/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php b/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php index 768fd93020..c7fe30e6ea 100644 --- a/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php +++ b/app/Api/V1/Requests/Models/PiggyBank/StoreRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -58,7 +59,6 @@ class StoreRequest extends FormRequest $data['object_group_title'] = $this->convertString('object_group_title'); return $data; - } /** @@ -80,5 +80,4 @@ class StoreRequest extends FormRequest 'notes' => 'max:65000', ]; } - } diff --git a/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php b/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php index 189a4a4360..14af9dd6ae 100644 --- a/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/PiggyBank/UpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\PiggyBank; +use FireflyIII\Models\PiggyBank; use FireflyIII\Rules\IsAssetAccountId; use FireflyIII\Rules\LessThanPiggyTarget; use FireflyIII\Support\Request\ChecksLogin; @@ -36,7 +37,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -68,17 +70,17 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var PiggyBank $piggyBank */ $piggyBank = $this->route()->parameter('piggyBank'); return [ - 'name' => 'between:1,255|uniquePiggyBankForUser:' . $piggyBank->id, - 'current_amount' => ['numeric', 'gte:0', new LessThanPiggyTarget], + 'name' => 'between:1,255|uniquePiggyBankForUser:'.$piggyBank->id, + 'current_amount' => ['numeric', 'gte:0', new LessThanPiggyTarget()], 'target_amount' => 'numeric|gt:0', 'start_date' => 'date|nullable', 'target_date' => 'date|nullable|after:start_date', 'notes' => 'max:65000', - 'account_id' => ['belongsToUser:accounts', new IsAssetAccountId], + 'account_id' => ['belongsToUser:accounts', new IsAssetAccountId()], ]; } - } diff --git a/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php b/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php index 5235446ea0..6892791352 100644 --- a/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Recurrence/StoreRequest.php @@ -39,7 +39,12 @@ use Illuminate\Validation\Validator; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData, ChecksLogin; + use ConvertsDataTypes; + use RecurrenceValidation; + use TransactionValidation; + use CurrencyValidation; + use GetRecurrenceData; + use ChecksLogin; /** * Get all data from the request. @@ -115,10 +120,10 @@ class StoreRequest extends FormRequest $current['moment'] = $repetition['moment']; } if (array_key_exists('skip', $repetition)) { - $current['skip'] = (int) $repetition['skip']; + $current['skip'] = (int)$repetition['skip']; } if (array_key_exists('weekend', $repetition)) { - $current['weekend'] = (int) $repetition['weekend']; + $current['weekend'] = (int)$repetition['weekend']; } $return[] = $current; @@ -139,8 +144,8 @@ class StoreRequest extends FormRequest 'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title', 'description' => 'between:1,65000', 'first_date' => 'required|date', - 'apply_rules' => [new IsBoolean], - 'active' => [new IsBoolean], + 'apply_rules' => [new IsBoolean()], + 'active' => [new IsBoolean()], 'repeat_until' => 'nullable|date', 'nr_of_repetitions' => 'nullable|numeric|between:1,31', @@ -156,18 +161,18 @@ class StoreRequest extends FormRequest 'transactions.*.currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', 'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id', 'transactions.*.foreign_currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', - 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.source_name' => 'between:1,255|nullable', - 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.destination_name' => 'between:1,255|nullable', // new and updated fields: - 'transactions.*.budget_id' => ['nullable', 'mustExist:budgets,id', new BelongsUser], - 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser], - 'transactions.*.category_id' => ['nullable', 'mustExist:categories,id', new BelongsUser], + 'transactions.*.budget_id' => ['nullable', 'mustExist:budgets,id', new BelongsUser()], + 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser()], + 'transactions.*.category_id' => ['nullable', 'mustExist:categories,id', new BelongsUser()], 'transactions.*.category_name' => 'between:1,255|nullable', - 'transactions.*.piggy_bank_id' => ['nullable', 'numeric', 'mustExist:piggy_banks,id', new BelongsUser], - 'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser], + 'transactions.*.piggy_bank_id' => ['nullable', 'numeric', 'mustExist:piggy_banks,id', new BelongsUser()], + 'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser()], 'transactions.*.tags' => 'nullable|between:1,64000', ]; } @@ -175,7 +180,7 @@ class StoreRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ diff --git a/app/Api/V1/Requests/Models/Recurrence/UpdateRequest.php b/app/Api/V1/Requests/Models/Recurrence/UpdateRequest.php index 0df8810a08..2677ab6157 100644 --- a/app/Api/V1/Requests/Models/Recurrence/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Recurrence/UpdateRequest.php @@ -40,7 +40,12 @@ use Illuminate\Validation\Validator; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, RecurrenceValidation, TransactionValidation, CurrencyValidation, GetRecurrenceData, ChecksLogin; + use ConvertsDataTypes; + use RecurrenceValidation; + use TransactionValidation; + use CurrencyValidation; + use GetRecurrenceData; + use ChecksLogin; /** * Get all data from the request. @@ -97,19 +102,19 @@ class UpdateRequest extends FormRequest } if (array_key_exists('moment', $repetition)) { - $current['moment'] = (string) $repetition['moment']; + $current['moment'] = (string)$repetition['moment']; } if (array_key_exists('skip', $repetition)) { - $current['skip'] = (int) $repetition['skip']; + $current['skip'] = (int)$repetition['skip']; } if (array_key_exists('weekend', $repetition)) { - $current['weekend'] = (int) $repetition['weekend']; + $current['weekend'] = (int)$repetition['weekend']; } $return[] = $current; } - if (empty($return)) { + if (0 === count($return)) { return null; } @@ -153,8 +158,8 @@ class UpdateRequest extends FormRequest 'title' => sprintf('between:1,255|uniqueObjectForUser:recurrences,title,%d', $recurrence->id), 'description' => 'between:1,65000', 'first_date' => 'date', - 'apply_rules' => [new IsBoolean], - 'active' => [new IsBoolean], + 'apply_rules' => [new IsBoolean()], + 'active' => [new IsBoolean()], 'repeat_until' => 'nullable|date', 'nr_of_repetitions' => 'nullable|numeric|between:1,31', @@ -170,18 +175,18 @@ class UpdateRequest extends FormRequest 'transactions.*.currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', 'transactions.*.foreign_currency_id' => 'nullable|numeric|exists:transaction_currencies,id', 'transactions.*.foreign_currency_code' => 'nullable|min:3|max:3|exists:transaction_currencies,code', - 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.source_name' => 'between:1,255|nullable', - 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.destination_name' => 'between:1,255|nullable', // new and updated fields: - 'transactions.*.budget_id' => ['nullable', 'mustExist:budgets,id', new BelongsUser], - 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser], - 'transactions.*.category_id' => ['nullable', 'mustExist:categories,id', new BelongsUser], + 'transactions.*.budget_id' => ['nullable', 'mustExist:budgets,id', new BelongsUser()], + 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser()], + 'transactions.*.category_id' => ['nullable', 'mustExist:categories,id', new BelongsUser()], 'transactions.*.category_name' => 'between:1,255|nullable', - 'transactions.*.piggy_bank_id' => ['nullable', 'numeric', 'mustExist:piggy_banks,id', new BelongsUser], - 'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser], + 'transactions.*.piggy_bank_id' => ['nullable', 'numeric', 'mustExist:piggy_banks,id', new BelongsUser()], + 'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser()], 'transactions.*.tags' => 'nullable|between:1,64000', ]; @@ -190,7 +195,7 @@ class UpdateRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ diff --git a/app/Api/V1/Requests/Models/Rule/StoreRequest.php b/app/Api/V1/Requests/Models/Rule/StoreRequest.php index 042d9051c8..024bfb4da5 100644 --- a/app/Api/V1/Requests/Models/Rule/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Rule/StoreRequest.php @@ -29,6 +29,7 @@ use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\GetRuleConfiguration; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Validator; + use function is_array; /** @@ -36,7 +37,9 @@ use function is_array; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, GetRuleConfiguration, ChecksLogin; + use ConvertsDataTypes; + use GetRuleConfiguration; + use ChecksLogin; /** * Get all data from the request. @@ -76,8 +79,8 @@ class StoreRequest extends FormRequest $return[] = [ 'type' => $trigger['type'], 'value' => $trigger['value'], - 'active' => $this->convertBoolean((string) ($trigger['active'] ?? 'false')), - 'stop_processing' => $this->convertBoolean((string) ($trigger['stop_processing'] ?? 'false')), + 'active' => $this->convertBoolean((string)($trigger['active'] ?? 'false')), + 'stop_processing' => $this->convertBoolean((string)($trigger['stop_processing'] ?? 'false')), ]; } } @@ -97,8 +100,8 @@ class StoreRequest extends FormRequest $return[] = [ 'type' => $action['type'], 'value' => $action['value'], - 'active' => $this->convertBoolean((string) ($action['active'] ?? 'false')), - 'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')), + 'active' => $this->convertBoolean((string)($action['active'] ?? 'false')), + 'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')), ]; } } @@ -126,24 +129,24 @@ class StoreRequest extends FormRequest 'rule_group_id' => 'belongsToUser:rule_groups|required_without:rule_group_title', 'rule_group_title' => 'nullable|between:1,255|required_without:rule_group_id|belongsToUser:rule_groups,title', 'trigger' => 'required|in:store-journal,update-journal', - 'triggers.*.type' => 'required|in:' . implode(',', $validTriggers), - 'triggers.*.value' => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue', - 'triggers.*.stop_processing' => [new IsBoolean], - 'triggers.*.active' => [new IsBoolean], - 'actions.*.type' => 'required|in:' . implode(',', $validActions), - 'actions.*.value' => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue', - 'actions.*.stop_processing' => [new IsBoolean], - 'actions.*.active' => [new IsBoolean], - 'strict' => [new IsBoolean], - 'stop_processing' => [new IsBoolean], - 'active' => [new IsBoolean], + 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), + 'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue', + 'triggers.*.stop_processing' => [new IsBoolean()], + 'triggers.*.active' => [new IsBoolean()], + 'actions.*.type' => 'required|in:'.implode(',', $validActions), + 'actions.*.value' => 'required_if:actions.*.type,'.$contextActions.'|ruleActionValue', + 'actions.*.stop_processing' => [new IsBoolean()], + 'actions.*.active' => [new IsBoolean()], + 'strict' => [new IsBoolean()], + 'stop_processing' => [new IsBoolean()], + 'active' => [new IsBoolean()], ]; } /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -162,44 +165,44 @@ class StoreRequest extends FormRequest /** * Adds an error to the validator when there are no triggers in the array of data. * - * @param Validator $validator + * @param Validator $validator */ protected function atLeastOneTrigger(Validator $validator): void { $data = $validator->getData(); $triggers = $data['triggers'] ?? []; // need at least one trigger - if (!is_countable($triggers) || empty($triggers)) { - $validator->errors()->add('title', (string) trans('validation.at_least_one_trigger')); + if (!is_countable($triggers) || 0 === count($triggers)) { + $validator->errors()->add('title', (string)trans('validation.at_least_one_trigger')); } } /** * Adds an error to the validator when there are no repetitions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ protected function atLeastOneAction(Validator $validator): void { $data = $validator->getData(); $actions = $data['actions'] ?? []; // need at least one trigger - if (!is_countable($actions) || empty($actions)) { - $validator->errors()->add('title', (string) trans('validation.at_least_one_action')); + if (!is_countable($actions) || 0 === count($actions)) { + $validator->errors()->add('title', (string)trans('validation.at_least_one_action')); } } /** * Adds an error to the validator when there are no ACTIVE triggers in the array of data. * - * @param Validator $validator + * @param Validator $validator */ protected function atLeastOneActiveTrigger(Validator $validator): void { $data = $validator->getData(); $triggers = $data['triggers'] ?? []; // need at least one trigger - if (!is_countable($triggers) || empty($triggers)) { + if (!is_countable($triggers) || 0 === count($triggers)) { return; } $allInactive = true; @@ -214,21 +217,21 @@ class StoreRequest extends FormRequest } } if (true === $allInactive) { - $validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_trigger')); + $validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_trigger')); } } /** * Adds an error to the validator when there are no ACTIVE actions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ protected function atLeastOneActiveAction(Validator $validator): void { $data = $validator->getData(); $actions = $data['actions'] ?? []; // need at least one trigger - if (!is_countable($actions) || empty($actions)) { + if (!is_countable($actions) || 0 === count($actions)) { return; } $allInactive = true; @@ -243,7 +246,7 @@ class StoreRequest extends FormRequest } } if (true === $allInactive) { - $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_action')); + $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action')); } } } diff --git a/app/Api/V1/Requests/Models/Rule/TestRequest.php b/app/Api/V1/Requests/Models/Rule/TestRequest.php index 29f4fcd3f1..b4708f3df6 100644 --- a/app/Api/V1/Requests/Models/Rule/TestRequest.php +++ b/app/Api/V1/Requests/Models/Rule/TestRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class TestRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * @return array @@ -55,12 +56,11 @@ class TestRequest extends FormRequest */ private function getPage(): int { - return 0 === (int) $this->query('page') ? 1 : (int) $this->query('page'); - + return 0 === (int)$this->query('page') ? 1 : (int)$this->query('page'); } /** - * @param string $field + * @param string $field * * @return Carbon|null */ @@ -89,5 +89,4 @@ class TestRequest extends FormRequest 'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts', ]; } - } diff --git a/app/Api/V1/Requests/Models/Rule/TriggerRequest.php b/app/Api/V1/Requests/Models/Rule/TriggerRequest.php index 37bc6d06d5..ce5cc1b9a0 100644 --- a/app/Api/V1/Requests/Models/Rule/TriggerRequest.php +++ b/app/Api/V1/Requests/Models/Rule/TriggerRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class TriggerRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * @return array @@ -49,7 +50,7 @@ class TriggerRequest extends FormRequest } /** - * @param string $field + * @param string $field * * @return Carbon|null */ @@ -78,5 +79,4 @@ class TriggerRequest extends FormRequest 'accounts.*' => 'exists:accounts,id|belongsToUser:accounts', ]; } - } diff --git a/app/Api/V1/Requests/Models/Rule/UpdateRequest.php b/app/Api/V1/Requests/Models/Rule/UpdateRequest.php index b3746488ef..ab51cdd56c 100644 --- a/app/Api/V1/Requests/Models/Rule/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Rule/UpdateRequest.php @@ -23,12 +23,14 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Rule; +use FireflyIII\Models\Rule; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\GetRuleConfiguration; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Validator; + use function is_array; /** @@ -36,7 +38,9 @@ use function is_array; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, GetRuleConfiguration, ChecksLogin; + use ConvertsDataTypes; + use GetRuleConfiguration; + use ChecksLogin; /** * Get all data from the request. @@ -110,8 +114,8 @@ class UpdateRequest extends FormRequest $return[] = [ 'type' => $action['type'], 'value' => $action['value'], - 'active' => $this->convertBoolean((string) ($action['active'] ?? 'false')), - 'stop_processing' => $this->convertBoolean((string) ($action['stop_processing'] ?? 'false')), + 'active' => $this->convertBoolean((string)($action['active'] ?? 'false')), + 'stop_processing' => $this->convertBoolean((string)($action['stop_processing'] ?? 'false')), ]; } } @@ -128,7 +132,9 @@ class UpdateRequest extends FormRequest { $validTriggers = $this->getTriggers(); $validActions = array_keys(config('firefly.rule-actions')); - $rule = $this->route()->parameter('rule'); + + /** @var Rule $rule */ + $rule = $this->route()->parameter('rule'); // some triggers and actions require text: $contextTriggers = implode(',', $this->getTriggersWithContext()); @@ -140,17 +146,17 @@ class UpdateRequest extends FormRequest 'rule_group_id' => 'belongsToUser:rule_groups', 'rule_group_title' => 'nullable|between:1,255|belongsToUser:rule_groups,title', 'trigger' => 'in:store-journal,update-journal', - 'triggers.*.type' => 'required|in:' . implode(',', $validTriggers), - 'triggers.*.value' => 'required_if:actions.*.type,' . $contextTriggers . '|min:1|ruleTriggerValue', - 'triggers.*.stop_processing' => [new IsBoolean], - 'triggers.*.active' => [new IsBoolean], - 'actions.*.type' => 'required|in:' . implode(',', $validActions), - 'actions.*.value' => 'required_if:actions.*.type,' . $contextActions . '|ruleActionValue', - 'actions.*.stop_processing' => [new IsBoolean], - 'actions.*.active' => [new IsBoolean], - 'strict' => [new IsBoolean], - 'stop_processing' => [new IsBoolean], - 'active' => [new IsBoolean], + 'triggers.*.type' => 'required|in:'.implode(',', $validTriggers), + 'triggers.*.value' => 'required_if:actions.*.type,'.$contextTriggers.'|min:1|ruleTriggerValue', + 'triggers.*.stop_processing' => [new IsBoolean()], + 'triggers.*.active' => [new IsBoolean()], + 'actions.*.type' => 'required|in:'.implode(',', $validActions), + 'actions.*.value' => 'required_if:actions.*.type,'.$contextActions.'|ruleActionValue', + 'actions.*.stop_processing' => [new IsBoolean()], + 'actions.*.active' => [new IsBoolean()], + 'strict' => [new IsBoolean()], + 'stop_processing' => [new IsBoolean()], + 'active' => [new IsBoolean()], 'order' => 'numeric|between:1,1337', ]; } @@ -158,7 +164,7 @@ class UpdateRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -177,22 +183,22 @@ class UpdateRequest extends FormRequest /** * Adds an error to the validator when there are no repetitions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ protected function atLeastOneTrigger(Validator $validator): void { $data = $validator->getData(); $triggers = $data['triggers'] ?? null; // need at least one trigger - if (is_array($triggers) && empty($triggers)) { - $validator->errors()->add('title', (string) trans('validation.at_least_one_trigger')); + if (is_array($triggers) && 0 === count($triggers)) { + $validator->errors()->add('title', (string)trans('validation.at_least_one_trigger')); } } /** * Adds an error to the validator when there are no repetitions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ protected function atLeastOneValidTrigger(Validator $validator): void { @@ -201,7 +207,7 @@ class UpdateRequest extends FormRequest $allInactive = true; $inactiveIndex = 0; // need at least one trigger - if (is_array($triggers) && empty($triggers)) { + if (is_array($triggers) && 0 === count($triggers)) { return; } foreach ($triggers as $index => $trigger) { @@ -214,29 +220,29 @@ class UpdateRequest extends FormRequest } } if (true === $allInactive) { - $validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_trigger')); + $validator->errors()->add(sprintf('triggers.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_trigger')); } } /** * Adds an error to the validator when there are no repetitions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ protected function atLeastOneAction(Validator $validator): void { $data = $validator->getData(); $actions = $data['actions'] ?? null; // need at least one action - if (is_array($actions) && empty($actions)) { - $validator->errors()->add('title', (string) trans('validation.at_least_one_action')); + if (is_array($actions) && 0 === count($actions)) { + $validator->errors()->add('title', (string)trans('validation.at_least_one_action')); } } /** * Adds an error to the validator when there are no repetitions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ protected function atLeastOneValidAction(Validator $validator): void { @@ -245,7 +251,7 @@ class UpdateRequest extends FormRequest $allInactive = true; $inactiveIndex = 0; // need at least one action - if (is_array($actions) && empty($actions)) { + if (is_array($actions) && 0 === count($actions)) { return; } @@ -259,7 +265,7 @@ class UpdateRequest extends FormRequest } } if (true === $allInactive) { - $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string) trans('validation.at_least_one_active_action')); + $validator->errors()->add(sprintf('actions.%d.active', $inactiveIndex), (string)trans('validation.at_least_one_active_action')); } } } diff --git a/app/Api/V1/Requests/Models/RuleGroup/StoreRequest.php b/app/Api/V1/Requests/Models/RuleGroup/StoreRequest.php index 1bfa8f5475..de4a99f7fc 100644 --- a/app/Api/V1/Requests/Models/RuleGroup/StoreRequest.php +++ b/app/Api/V1/Requests/Models/RuleGroup/StoreRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -70,7 +71,7 @@ class StoreRequest extends FormRequest return [ 'title' => 'required|between:1,100|uniqueObjectForUser:rule_groups,title', 'description' => 'between:1,5000|nullable', - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], ]; } } diff --git a/app/Api/V1/Requests/Models/RuleGroup/TestRequest.php b/app/Api/V1/Requests/Models/RuleGroup/TestRequest.php index 7e08bece5b..b48c050cba 100644 --- a/app/Api/V1/Requests/Models/RuleGroup/TestRequest.php +++ b/app/Api/V1/Requests/Models/RuleGroup/TestRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class TestRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * @return array @@ -49,7 +50,7 @@ class TestRequest extends FormRequest } /** - * @param string $field + * @param string $field * * @return Carbon|null */ @@ -78,5 +79,4 @@ class TestRequest extends FormRequest 'accounts.*' => 'exists:accounts,id|belongsToUser:accounts', ]; } - } diff --git a/app/Api/V1/Requests/Models/RuleGroup/TriggerRequest.php b/app/Api/V1/Requests/Models/RuleGroup/TriggerRequest.php index 8dcc96b995..cd84f3fe2e 100644 --- a/app/Api/V1/Requests/Models/RuleGroup/TriggerRequest.php +++ b/app/Api/V1/Requests/Models/RuleGroup/TriggerRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class TriggerRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * @return array @@ -49,7 +50,7 @@ class TriggerRequest extends FormRequest } /** - * @param string $field + * @param string $field * * @return Carbon|null */ @@ -76,5 +77,4 @@ class TriggerRequest extends FormRequest 'end' => 'date|after_or_equal:start', ]; } - } diff --git a/app/Api/V1/Requests/Models/RuleGroup/UpdateRequest.php b/app/Api/V1/Requests/Models/RuleGroup/UpdateRequest.php index 0efada299e..3d354e475a 100644 --- a/app/Api/V1/Requests/Models/RuleGroup/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/RuleGroup/UpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\RuleGroup; +use FireflyIII\Models\RuleGroup; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -34,7 +35,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -61,12 +63,13 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var RuleGroup $ruleGroup */ $ruleGroup = $this->route()->parameter('ruleGroup'); return [ - 'title' => 'between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id, + 'title' => 'between:1,100|uniqueObjectForUser:rule_groups,title,'.$ruleGroup->id, 'description' => 'between:1,5000|nullable', - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], ]; } } diff --git a/app/Api/V1/Requests/Models/Tag/StoreRequest.php b/app/Api/V1/Requests/Models/Tag/StoreRequest.php index 01ac8cb5c4..a1e4c82af1 100644 --- a/app/Api/V1/Requests/Models/Tag/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Tag/StoreRequest.php @@ -36,7 +36,9 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin, AppendsLocationData; + use ConvertsDataTypes; + use ChecksLogin; + use AppendsLocationData; /** * Get all data from the request. diff --git a/app/Api/V1/Requests/Models/Tag/UpdateRequest.php b/app/Api/V1/Requests/Models/Tag/UpdateRequest.php index 4fc11e9a32..a5e2e059d7 100644 --- a/app/Api/V1/Requests/Models/Tag/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Tag/UpdateRequest.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Tag; use FireflyIII\Models\Location; +use FireflyIII\Models\Tag; use FireflyIII\Support\Request\AppendsLocationData; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -37,7 +38,9 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin, AppendsLocationData; + use ConvertsDataTypes; + use ChecksLogin; + use AppendsLocationData; /** * Get all data from the request. @@ -64,10 +67,11 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var Tag $tag */ $tag = $this->route()->parameter('tagOrId'); - // See reference nr. 73 + // TODO check if uniqueObjectForUser is obsolete $rules = [ - 'tag' => 'min:1|uniqueObjectForUser:tags,tag,' . $tag->id, + 'tag' => 'min:1|uniqueObjectForUser:tags,tag,'.$tag->id, 'description' => 'min:1|nullable', 'date' => 'date|nullable', ]; diff --git a/app/Api/V1/Requests/Models/Transaction/StoreRequest.php b/app/Api/V1/Requests/Models/Transaction/StoreRequest.php index b1306b8454..20d5e6de13 100644 --- a/app/Api/V1/Requests/Models/Transaction/StoreRequest.php +++ b/app/Api/V1/Requests/Models/Transaction/StoreRequest.php @@ -43,7 +43,12 @@ use Log; */ class StoreRequest extends FormRequest { - use TransactionValidation, GroupValidation, CurrencyValidation, ConvertsDataTypes, ChecksLogin, AppendsLocationData; + use TransactionValidation; + use GroupValidation; + use CurrencyValidation; + use ConvertsDataTypes; + use ChecksLogin; + use AppendsLocationData; /** * Get all data. Is pretty complex because of all the ??-statements. @@ -61,7 +66,7 @@ class StoreRequest extends FormRequest 'fire_webhooks' => $this->boolean('fire_webhooks', true), 'transactions' => $this->getTransactionData(), ]; - // See reference nr. 71 + // TODO include location and ability to process it. } /** @@ -80,73 +85,73 @@ class StoreRequest extends FormRequest $return[] = [ 'type' => $this->clearString($object['type'], false), 'date' => $this->dateFromValue($object['date']), - 'order' => $this->integerFromValue((string) $object['order']), + 'order' => $this->integerFromValue((string)$object['order']), - 'currency_id' => $this->integerFromValue((string) $object['currency_id']), - 'currency_code' => $this->clearString((string) $object['currency_code'], false), + 'currency_id' => $this->integerFromValue((string)$object['currency_id']), + 'currency_code' => $this->clearString((string)$object['currency_code'], false), // foreign currency info: - 'foreign_currency_id' => $this->integerFromValue((string) $object['foreign_currency_id']), - 'foreign_currency_code' => $this->clearString((string) $object['foreign_currency_code'], false), + 'foreign_currency_id' => $this->integerFromValue((string)$object['foreign_currency_id']), + 'foreign_currency_code' => $this->clearString((string)$object['foreign_currency_code'], false), // amount and foreign amount. Cannot be 0. - 'amount' => $this->clearString((string) $object['amount'], false), - 'foreign_amount' => $this->clearString((string) $object['foreign_amount'], false), + 'amount' => $this->clearString((string)$object['amount'], false), + 'foreign_amount' => $this->clearString((string)$object['foreign_amount'], false), // description. 'description' => $this->clearString($object['description'], false), // source of transaction. If everything is null, assume cash account. - 'source_id' => $this->integerFromValue((string) $object['source_id']), - 'source_name' => $this->clearString((string) $object['source_name'], false), - 'source_iban' => $this->clearString((string) $object['source_iban'], false), - 'source_number' => $this->clearString((string) $object['source_number'], false), - 'source_bic' => $this->clearString((string) $object['source_bic'], false), + 'source_id' => $this->integerFromValue((string)$object['source_id']), + 'source_name' => $this->clearString((string)$object['source_name'], false), + 'source_iban' => $this->clearString((string)$object['source_iban'], false), + 'source_number' => $this->clearString((string)$object['source_number'], false), + 'source_bic' => $this->clearString((string)$object['source_bic'], false), // destination of transaction. If everything is null, assume cash account. - 'destination_id' => $this->integerFromValue((string) $object['destination_id']), - 'destination_name' => $this->clearString((string) $object['destination_name'], false), - 'destination_iban' => $this->clearString((string) $object['destination_iban'], false), - 'destination_number' => $this->clearString((string) $object['destination_number'], false), - 'destination_bic' => $this->clearString((string) $object['destination_bic'], false), + 'destination_id' => $this->integerFromValue((string)$object['destination_id']), + 'destination_name' => $this->clearString((string)$object['destination_name'], false), + 'destination_iban' => $this->clearString((string)$object['destination_iban'], false), + 'destination_number' => $this->clearString((string)$object['destination_number'], false), + 'destination_bic' => $this->clearString((string)$object['destination_bic'], false), // budget info - 'budget_id' => $this->integerFromValue((string) $object['budget_id']), - 'budget_name' => $this->clearString((string) $object['budget_name'], false), + 'budget_id' => $this->integerFromValue((string)$object['budget_id']), + 'budget_name' => $this->clearString((string)$object['budget_name'], false), // category info - 'category_id' => $this->integerFromValue((string) $object['category_id']), - 'category_name' => $this->clearString((string) $object['category_name'], false), + 'category_id' => $this->integerFromValue((string)$object['category_id']), + 'category_name' => $this->clearString((string)$object['category_name'], false), // journal bill reference. Optional. Will only work for withdrawals - 'bill_id' => $this->integerFromValue((string) $object['bill_id']), - 'bill_name' => $this->clearString((string) $object['bill_name'], false), + 'bill_id' => $this->integerFromValue((string)$object['bill_id']), + 'bill_name' => $this->clearString((string)$object['bill_name'], false), // piggy bank reference. Optional. Will only work for transfers - 'piggy_bank_id' => $this->integerFromValue((string) $object['piggy_bank_id']), - 'piggy_bank_name' => $this->clearString((string) $object['piggy_bank_name'], false), + 'piggy_bank_id' => $this->integerFromValue((string)$object['piggy_bank_id']), + 'piggy_bank_name' => $this->clearString((string)$object['piggy_bank_name'], false), // some other interesting properties - 'reconciled' => $this->convertBoolean((string) $object['reconciled']), - 'notes' => $this->clearString((string) $object['notes']), + 'reconciled' => $this->convertBoolean((string)$object['reconciled']), + 'notes' => $this->clearString((string)$object['notes']), 'tags' => $this->arrayFromValue($object['tags']), // all custom fields: - 'internal_reference' => $this->clearString((string) $object['internal_reference'], false), - 'external_id' => $this->clearString((string) $object['external_id'], false), + 'internal_reference' => $this->clearString((string)$object['internal_reference'], false), + 'external_id' => $this->clearString((string)$object['external_id'], false), 'original_source' => sprintf('ff3-v%s|api-v%s', config('firefly.version'), config('firefly.api_version')), 'recurrence_id' => $this->integerFromValue($object['recurrence_id']), - 'bunq_payment_id' => $this->clearString((string) $object['bunq_payment_id'], false), - 'external_url' => $this->clearString((string) $object['external_url'], false), + 'bunq_payment_id' => $this->clearString((string)$object['bunq_payment_id'], false), + 'external_url' => $this->clearString((string)$object['external_url'], false), - 'sepa_cc' => $this->clearString((string) $object['sepa_cc'], false), - 'sepa_ct_op' => $this->clearString((string) $object['sepa_ct_op'], false), - 'sepa_ct_id' => $this->clearString((string) $object['sepa_ct_id'], false), - 'sepa_db' => $this->clearString((string) $object['sepa_db'], false), - 'sepa_country' => $this->clearString((string) $object['sepa_country'], false), - 'sepa_ep' => $this->clearString((string) $object['sepa_ep'], false), - 'sepa_ci' => $this->clearString((string) $object['sepa_ci'], false), - 'sepa_batch_id' => $this->clearString((string) $object['sepa_batch_id'], false), + 'sepa_cc' => $this->clearString((string)$object['sepa_cc'], false), + 'sepa_ct_op' => $this->clearString((string)$object['sepa_ct_op'], false), + 'sepa_ct_id' => $this->clearString((string)$object['sepa_ct_id'], false), + 'sepa_db' => $this->clearString((string)$object['sepa_db'], false), + 'sepa_country' => $this->clearString((string)$object['sepa_country'], false), + 'sepa_ep' => $this->clearString((string)$object['sepa_ep'], false), + 'sepa_ci' => $this->clearString((string)$object['sepa_ci'], false), + 'sepa_batch_id' => $this->clearString((string)$object['sepa_batch_id'], false), // custom date fields. Must be Carbon objects. Presence is optional. 'interest_date' => $this->dateFromValue($object['interest_date']), 'book_date' => $this->dateFromValue($object['book_date']), @@ -173,12 +178,12 @@ class StoreRequest extends FormRequest return [ // basic fields for group: 'group_title' => 'between:1,1000|nullable', - 'error_if_duplicate_hash' => [new IsBoolean], - 'apply_rules' => [new IsBoolean], + 'error_if_duplicate_hash' => [new IsBoolean()], + 'apply_rules' => [new IsBoolean()], // transaction rules (in array for splits): 'transactions.*.type' => 'required|in:withdrawal,deposit,transfer,opening-balance,reconciliation', - 'transactions.*.date' => ['required', new IsDateOrTime], + 'transactions.*.date' => ['required', new IsDateOrTime()], 'transactions.*.order' => 'numeric|min:0', // currency info @@ -195,31 +200,31 @@ class StoreRequest extends FormRequest 'transactions.*.description' => 'nullable|between:1,1000', // source of transaction - 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.source_name' => 'between:1,255|nullable', 'transactions.*.source_iban' => 'between:1,255|nullable|iban', 'transactions.*.source_number' => 'between:1,255|nullable', 'transactions.*.source_bic' => 'between:1,255|nullable|bic', // destination of transaction - 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.destination_name' => 'between:1,255|nullable', 'transactions.*.destination_iban' => 'between:1,255|nullable|iban', 'transactions.*.destination_number' => 'between:1,255|nullable', 'transactions.*.destination_bic' => 'between:1,255|nullable|bic', // budget, category, bill and piggy - 'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser], - 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser], - 'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser, 'nullable'], + 'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser()], + 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser()], + 'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser(), 'nullable'], 'transactions.*.category_name' => 'between:1,255|nullable', - 'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser], - 'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUser], - 'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser], - 'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser], + 'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()], + 'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUser()], + 'transactions.*.piggy_bank_id' => ['numeric', 'nullable', 'mustExist:piggy_banks,id', new BelongsUser()], + 'transactions.*.piggy_bank_name' => ['between:1,255', 'nullable', new BelongsUser()], // other interesting fields - 'transactions.*.reconciled' => [new IsBoolean], + 'transactions.*.reconciled' => [new IsBoolean()], 'transactions.*.notes' => 'min:1,max:50000|nullable', 'transactions.*.tags' => 'between:0,255', @@ -253,7 +258,7 @@ class StoreRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -261,7 +266,6 @@ class StoreRequest extends FormRequest { $validator->after( function (Validator $validator) { - // must be valid array. $this->validateTransactionArray($validator); @@ -285,7 +289,6 @@ class StoreRequest extends FormRequest // the group must have a description if > 1 journal. $this->validateGroupDescription($validator); - } ); } diff --git a/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php b/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php index adaa967a62..3148f02422 100644 --- a/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Transaction/UpdateRequest.php @@ -41,14 +41,17 @@ use Log; */ class UpdateRequest extends FormRequest { - use TransactionValidation, GroupValidation, ConvertsDataTypes, ChecksLogin; + use TransactionValidation; + use GroupValidation; + use ConvertsDataTypes; + use ChecksLogin; private array $arrayFields; private array $booleanFields; private array $dateFields; + private array $floatFields; private array $integerFields; private array $stringFields; - private array $floatFields; private array $textareaFields; /** @@ -86,8 +89,8 @@ class UpdateRequest extends FormRequest ]; $this->floatFields = [ // not really floats, for validation. - 'amount', - 'foreign_amount', + 'amount', + 'foreign_amount', ]; $this->stringFields = [ @@ -177,8 +180,8 @@ class UpdateRequest extends FormRequest /** * For each field, add it to the array if a reference is present in the request: * - * @param array $current - * @param array $transaction + * @param array $current + * @param array $transaction * * @return array */ @@ -186,7 +189,7 @@ class UpdateRequest extends FormRequest { foreach ($this->integerFields as $fieldName) { if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->integerFromValue((string) $transaction[$fieldName]); + $current[$fieldName] = $this->integerFromValue((string)$transaction[$fieldName]); } } @@ -194,8 +197,8 @@ class UpdateRequest extends FormRequest } /** - * @param array $current - * @param array $transaction + * @param array $current + * @param array $transaction * * @return array */ @@ -203,7 +206,7 @@ class UpdateRequest extends FormRequest { foreach ($this->stringFields as $fieldName) { if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->clearString((string) $transaction[$fieldName], false); + $current[$fieldName] = $this->clearString((string)$transaction[$fieldName], false); } } @@ -211,8 +214,8 @@ class UpdateRequest extends FormRequest } /** - * @param array $current - * @param array $transaction + * @param array $current + * @param array $transaction * * @return array */ @@ -220,7 +223,7 @@ class UpdateRequest extends FormRequest { foreach ($this->textareaFields as $fieldName) { if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->clearString((string) $transaction[$fieldName]); + $current[$fieldName] = $this->clearString((string)$transaction[$fieldName]); } } @@ -228,8 +231,8 @@ class UpdateRequest extends FormRequest } /** - * @param array $current - * @param array $transaction + * @param array $current + * @param array $transaction * * @return array */ @@ -238,8 +241,8 @@ class UpdateRequest extends FormRequest foreach ($this->dateFields as $fieldName) { Log::debug(sprintf('Now at date field %s', $fieldName)); if (array_key_exists($fieldName, $transaction)) { - Log::debug(sprintf('New value: "%s"', (string) $transaction[$fieldName])); - $current[$fieldName] = $this->dateFromValue((string) $transaction[$fieldName]); + Log::debug(sprintf('New value: "%s"', (string)$transaction[$fieldName])); + $current[$fieldName] = $this->dateFromValue((string)$transaction[$fieldName]); } } @@ -247,8 +250,8 @@ class UpdateRequest extends FormRequest } /** - * @param array $current - * @param array $transaction + * @param array $current + * @param array $transaction * * @return array */ @@ -256,7 +259,7 @@ class UpdateRequest extends FormRequest { foreach ($this->booleanFields as $fieldName) { if (array_key_exists($fieldName, $transaction)) { - $current[$fieldName] = $this->convertBoolean((string) $transaction[$fieldName]); + $current[$fieldName] = $this->convertBoolean((string)$transaction[$fieldName]); } } @@ -264,8 +267,8 @@ class UpdateRequest extends FormRequest } /** - * @param array $current - * @param array $transaction + * @param array $current + * @param array $transaction * * @return array */ @@ -280,6 +283,28 @@ class UpdateRequest extends FormRequest return $current; } + /** + * @param array $current + * @param array $transaction + * @return array + */ + private function getFloatData(array $current, array $transaction): array + { + foreach ($this->floatFields as $fieldName) { + if (array_key_exists($fieldName, $transaction)) { + $value = $transaction[$fieldName]; + if (is_float($value)) { + $current[$fieldName] = sprintf('%.24f', $value); + } + if (!is_float($value)) { + $current[$fieldName] = (string)$value; + } + } + } + + return $current; + } + /** * The rules that the incoming request must be matched against. * @@ -290,15 +315,15 @@ class UpdateRequest extends FormRequest return [ // basic fields for group: 'group_title' => 'between:1,1000', - 'apply_rules' => [new IsBoolean], + 'apply_rules' => [new IsBoolean()], // transaction rules (in array for splits): 'transactions.*.type' => 'in:withdrawal,deposit,transfer,opening-balance,reconciliation', - 'transactions.*.date' => [new IsDateOrTime], + 'transactions.*.date' => [new IsDateOrTime()], 'transactions.*.order' => 'numeric|min:0', // group id: - 'transactions.*.transaction_journal_id' => ['nullable', 'numeric', new BelongsUser], + 'transactions.*.transaction_journal_id' => ['nullable', 'numeric', new BelongsUser()], // currency info @@ -315,23 +340,23 @@ class UpdateRequest extends FormRequest 'transactions.*.description' => 'nullable|between:1,1000', // source of transaction - 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.source_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.source_name' => 'between:1,255|nullable', // destination of transaction - 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser], + 'transactions.*.destination_id' => ['numeric', 'nullable', new BelongsUser()], 'transactions.*.destination_name' => 'between:1,255|nullable', // budget, category, bill and piggy - 'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser], - 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser], - 'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser], + 'transactions.*.budget_id' => ['mustExist:budgets,id', new BelongsUser()], + 'transactions.*.budget_name' => ['between:1,255', 'nullable', new BelongsUser()], + 'transactions.*.category_id' => ['mustExist:categories,id', new BelongsUser()], 'transactions.*.category_name' => 'between:1,255|nullable', - 'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser], - 'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUser], + 'transactions.*.bill_id' => ['numeric', 'nullable', 'mustExist:bills,id', new BelongsUser()], + 'transactions.*.bill_name' => ['between:1,255', 'nullable', new BelongsUser()], // other interesting fields - 'transactions.*.reconciled' => [new IsBoolean], + 'transactions.*.reconciled' => [new IsBoolean()], 'transactions.*.notes' => 'min:1,max:50000|nullable', 'transactions.*.tags' => 'between:0,255', @@ -365,7 +390,7 @@ class UpdateRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -385,35 +410,12 @@ class UpdateRequest extends FormRequest $this->validateEqualAccountsForUpdate($validator, $transactionGroup); // a catch when users submit splits with no source or destination info at all. - $this->preventNoAccountInfo($validator,); + $this->preventNoAccountInfo($validator, ); // validate that the currency fits the source and/or destination account. // validate all account info $this->validateAccountInformationUpdate($validator, $transactionGroup); - } ); } - - /** - * @param array $current - * @param array $transaction - * @return array - */ - private function getFloatData(array $current, array $transaction): array - { - foreach ($this->floatFields as $fieldName) { - if (array_key_exists($fieldName, $transaction)) { - $value = $transaction[$fieldName]; - if (is_float($value)) { - $current[$fieldName] = sprintf('%.24f', $value); - } - if (!is_float($value)) { - $current[$fieldName] = (string) $value; - } - } - } - - return $current; - } } diff --git a/app/Api/V1/Requests/Models/TransactionCurrency/StoreRequest.php b/app/Api/V1/Requests/Models/TransactionCurrency/StoreRequest.php index f0fe87c6d7..f048c336a3 100644 --- a/app/Api/V1/Requests/Models/TransactionCurrency/StoreRequest.php +++ b/app/Api/V1/Requests/Models/TransactionCurrency/StoreRequest.php @@ -35,7 +35,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. diff --git a/app/Api/V1/Requests/Models/TransactionCurrency/UpdateRequest.php b/app/Api/V1/Requests/Models/TransactionCurrency/UpdateRequest.php index df72125217..5c9b5bfa0f 100644 --- a/app/Api/V1/Requests/Models/TransactionCurrency/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/TransactionCurrency/UpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\TransactionCurrency; +use FireflyIII\Models\TransactionCurrency; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -35,7 +36,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -65,6 +67,7 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var TransactionCurrency $currency */ $currency = $this->route()->parameter('currency_code'); return [ diff --git a/app/Api/V1/Requests/Models/TransactionLink/StoreRequest.php b/app/Api/V1/Requests/Models/TransactionLink/StoreRequest.php index 9473a75a42..af57c23d31 100644 --- a/app/Api/V1/Requests/Models/TransactionLink/StoreRequest.php +++ b/app/Api/V1/Requests/Models/TransactionLink/StoreRequest.php @@ -36,7 +36,8 @@ use Illuminate\Validation\Validator; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -73,7 +74,7 @@ class StoreRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -87,7 +88,7 @@ class StoreRequest extends FormRequest } /** - * @param Validator $validator + * @param Validator $validator */ private function validateExistingLink(Validator $validator): void { @@ -102,8 +103,8 @@ class StoreRequest extends FormRequest $journalRepos->setUser($user); $data = $validator->getData(); - $inwardId = (int) ($data['inward_id'] ?? 0); - $outwardId = (int) ($data['outward_id'] ?? 0); + $inwardId = (int)($data['inward_id'] ?? 0); + $outwardId = (int)($data['outward_id'] ?? 0); $inward = $journalRepos->find($inwardId); $outward = $journalRepos->find($outwardId); diff --git a/app/Api/V1/Requests/Models/TransactionLink/UpdateRequest.php b/app/Api/V1/Requests/Models/TransactionLink/UpdateRequest.php index 0649b832c8..e63121c47b 100644 --- a/app/Api/V1/Requests/Models/TransactionLink/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/TransactionLink/UpdateRequest.php @@ -36,7 +36,8 @@ use Illuminate\Validation\Validator; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -73,7 +74,7 @@ class UpdateRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -87,7 +88,7 @@ class UpdateRequest extends FormRequest } /** - * @param Validator $validator + * @param Validator $validator */ private function validateUpdate(Validator $validator): void { @@ -104,8 +105,8 @@ class UpdateRequest extends FormRequest $inwardId = $data['inward_id'] ?? $existing->source_id; $outwardId = $data['outward_id'] ?? $existing->destination_id; - $inward = $journalRepos->find((int) $inwardId); - $outward = $journalRepos->find((int) $outwardId); + $inward = $journalRepos->find((int)$inwardId); + $outward = $journalRepos->find((int)$outwardId); if (null === $inward) { $inward = $existing->source; } diff --git a/app/Api/V1/Requests/Models/TransactionLinkType/StoreRequest.php b/app/Api/V1/Requests/Models/TransactionLinkType/StoreRequest.php index 5226968de4..3cd392ed30 100644 --- a/app/Api/V1/Requests/Models/TransactionLinkType/StoreRequest.php +++ b/app/Api/V1/Requests/Models/TransactionLinkType/StoreRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class StoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. diff --git a/app/Api/V1/Requests/Models/TransactionLinkType/UpdateRequest.php b/app/Api/V1/Requests/Models/TransactionLinkType/UpdateRequest.php index 54036336bd..5f4aaa79f0 100644 --- a/app/Api/V1/Requests/Models/TransactionLinkType/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/TransactionLinkType/UpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\TransactionLinkType; +use FireflyIII\Models\LinkType; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; use Illuminate\Foundation\Http\FormRequest; @@ -35,7 +36,8 @@ use Illuminate\Validation\Rule; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -58,6 +60,7 @@ class UpdateRequest extends FormRequest */ public function rules(): array { + /** @var LinkType $linkType */ $linkType = $this->route()->parameter('linkType'); return [ diff --git a/app/Api/V1/Requests/Models/Webhook/CreateRequest.php b/app/Api/V1/Requests/Models/Webhook/CreateRequest.php index 242ad7d9e2..24c4084bf0 100644 --- a/app/Api/V1/Requests/Models/Webhook/CreateRequest.php +++ b/app/Api/V1/Requests/Models/Webhook/CreateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Webhook; +use FireflyIII\Models\Webhook; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -33,16 +34,17 @@ use Illuminate\Foundation\Http\FormRequest; */ class CreateRequest extends FormRequest { - use ChecksLogin, ConvertsDataTypes; + use ChecksLogin; + use ConvertsDataTypes; /** * @return array */ public function getData(): array { - $triggers = array_flip(config('firefly.webhooks.triggers')); - $responses = array_flip(config('firefly.webhooks.responses')); - $deliveries = array_flip(config('firefly.webhooks.deliveries')); + $triggers = Webhook::getTriggersForValidation(); + $responses = Webhook::getResponsesForValidation(); + $deliveries = Webhook::getDeliveriesForValidation(); $fields = [ 'title' => ['title', 'convertString'], @@ -55,9 +57,9 @@ class CreateRequest extends FormRequest // this is the way. $return = $this->getAllData($fields); - $return['trigger'] = $triggers[$return['trigger']] ?? 0; - $return['response'] = $responses[$return['response']] ?? 0; - $return['delivery'] = $deliveries[$return['delivery']] ?? 0; + $return['trigger'] = $triggers[$return['trigger']] ?? intval($return['trigger']); + $return['response'] = $responses[$return['response']] ?? intval($return['response']); + $return['delivery'] = $deliveries[$return['delivery']] ?? intval($return['delivery']); return $return; } @@ -69,17 +71,17 @@ class CreateRequest extends FormRequest */ public function rules(): array { - $triggers = implode(',', array_values(config('firefly.webhooks.triggers'))); - $responses = implode(',', array_values(config('firefly.webhooks.responses'))); - $deliveries = implode(',', array_values(config('firefly.webhooks.deliveries'))); + $triggers = implode(',', array_keys(Webhook::getTriggersForValidation())); + $responses = implode(',', array_keys(Webhook::getResponsesForValidation())); + $deliveries = implode(',', array_keys(Webhook::getDeliveriesForValidation())); return [ 'title' => 'required|between:1,512|uniqueObjectForUser:webhooks,title', - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], 'trigger' => sprintf('required|in:%s', $triggers), 'response' => sprintf('required|in:%s', $responses), 'delivery' => sprintf('required|in:%s', $deliveries), - 'url' => ['required', 'url', 'starts_with:https://', 'uniqueWebhook'], + 'url' => ['required', 'url', 'uniqueWebhook'], ]; } } diff --git a/app/Api/V1/Requests/Models/Webhook/UpdateRequest.php b/app/Api/V1/Requests/Models/Webhook/UpdateRequest.php index 7330cebfe4..157c2f5716 100644 --- a/app/Api/V1/Requests/Models/Webhook/UpdateRequest.php +++ b/app/Api/V1/Requests/Models/Webhook/UpdateRequest.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Api\V1\Requests\Models\Webhook; +use FireflyIII\Models\Webhook; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; @@ -33,16 +34,17 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ChecksLogin, ConvertsDataTypes; + use ChecksLogin; + use ConvertsDataTypes; /** * @return array */ public function getData(): array { - $triggers = array_flip(config('firefly.webhooks.triggers')); - $responses = array_flip(config('firefly.webhooks.responses')); - $deliveries = array_flip(config('firefly.webhooks.deliveries')); + $triggers = Webhook::getTriggersForValidation(); + $responses = Webhook::getResponsesForValidation(); + $deliveries = Webhook::getDeliveriesForValidation(); $fields = [ 'title' => ['title', 'convertString'], @@ -79,18 +81,20 @@ class UpdateRequest extends FormRequest */ public function rules(): array { - $triggers = implode(',', array_values(config('firefly.webhooks.triggers'))); - $responses = implode(',', array_values(config('firefly.webhooks.responses'))); - $deliveries = implode(',', array_values(config('firefly.webhooks.deliveries'))); - $webhook = $this->route()->parameter('webhook'); + $triggers = implode(',', array_keys(Webhook::getTriggersForValidation())); + $responses = implode(',', array_keys(Webhook::getResponsesForValidation())); + $deliveries = implode(',', array_keys(Webhook::getDeliveriesForValidation())); + + /** @var Webhook $webhook */ + $webhook = $this->route()->parameter('webhook'); return [ 'title' => sprintf('between:1,512|uniqueObjectForUser:webhooks,title,%d', $webhook->id), - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], 'trigger' => sprintf('in:%s', $triggers), 'response' => sprintf('in:%s', $responses), 'delivery' => sprintf('in:%s', $deliveries), - 'url' => ['url', 'starts_with:https://', sprintf('uniqueExistingWebhook:%d', $webhook->id)], + 'url' => ['url', sprintf('uniqueExistingWebhook:%d', $webhook->id)], ]; } } diff --git a/app/Api/V1/Requests/System/UpdateRequest.php b/app/Api/V1/Requests/System/UpdateRequest.php index fddaa7cb80..d5be18248c 100644 --- a/app/Api/V1/Requests/System/UpdateRequest.php +++ b/app/Api/V1/Requests/System/UpdateRequest.php @@ -36,7 +36,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class UpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get all data from the request. @@ -46,15 +47,12 @@ class UpdateRequest extends FormRequest public function getAll(): array { $name = $this->route()->parameter('dynamicConfigKey'); - switch ($name) { - default: - break; - case 'configuration.is_demo_site': - case 'configuration.single_user_mode': - return ['value' => $this->boolean('value')]; - case 'configuration.permission_update_check': - case 'configuration.last_update_check': - return ['value' => $this->convertInteger('value')]; + + if ($name === 'configuration.is_demo_site' || $name === 'configuration.single_user_mode') { + return ['value' => $this->boolean('value')]; + } + if ($name === 'configuration.permission_update_check' || $name === 'configuration.last_update_check') { + return ['value' => $this->convertInteger('value')]; } return ['value' => $this->convertString('value')]; @@ -68,16 +66,15 @@ class UpdateRequest extends FormRequest public function rules(): array { $name = $this->route()->parameter('configName'); - switch ($name) { - default: - break; - case 'configuration.is_demo_site': - case 'configuration.single_user_mode': - return ['value' => ['required', new IsBoolean]]; - case 'configuration.permission_update_check': - return ['value' => 'required|numeric|between:-1,1']; - case 'configuration.last_update_check': - return ['value' => 'required|numeric|min:464272080']; + + if ($name === 'configuration.is_demo_site' || $name === 'configuration.single_user_mode') { + return ['value' => ['required', new IsBoolean()]]; + } + if ($name === 'configuration.permission_update_check') { + return ['value' => 'required|numeric|between:-1,1']; + } + if ($name === 'configuration.last_update_check') { + return ['value' => 'required|numeric|min:464272080']; } return ['value' => 'required']; diff --git a/app/Api/V1/Requests/System/UserStoreRequest.php b/app/Api/V1/Requests/System/UserStoreRequest.php index 7168bc4555..28dae61728 100644 --- a/app/Api/V1/Requests/System/UserStoreRequest.php +++ b/app/Api/V1/Requests/System/UserStoreRequest.php @@ -34,7 +34,8 @@ use Illuminate\Foundation\Http\FormRequest; */ class UserStoreRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Logged in + owner @@ -75,10 +76,9 @@ class UserStoreRequest extends FormRequest { return [ 'email' => 'required|email|unique:users,email', - 'blocked' => [new IsBoolean], + 'blocked' => [new IsBoolean()], 'blocked_code' => 'in:email_changed', 'role' => 'in:owner,demo', ]; } - } diff --git a/app/Api/V1/Requests/System/UserUpdateRequest.php b/app/Api/V1/Requests/System/UserUpdateRequest.php index 1433467ce2..a6a6292543 100644 --- a/app/Api/V1/Requests/System/UserUpdateRequest.php +++ b/app/Api/V1/Requests/System/UserUpdateRequest.php @@ -27,6 +27,7 @@ namespace FireflyIII\Api\V1\Requests\System; use FireflyIII\Rules\IsBoolean; use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ConvertsDataTypes; +use FireflyIII\User; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Validator; @@ -35,7 +36,8 @@ use Illuminate\Validation\Validator; */ class UserUpdateRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Logged in + owner @@ -74,11 +76,12 @@ class UserUpdateRequest extends FormRequest */ public function rules(): array { + /** @var User $user */ $user = $this->route()->parameter('user'); return [ 'email' => sprintf('email|unique:users,email,%d', $user->id), - 'blocked' => [new IsBoolean], + 'blocked' => [new IsBoolean()], 'blocked_code' => 'in:email_changed', 'role' => 'in:owner,demo,', ]; @@ -87,22 +90,22 @@ class UserUpdateRequest extends FormRequest /** * Configure the validator instance. * - * @param Validator $validator + * @param Validator $validator * * @return void */ public function withValidator(Validator $validator): void { + /** @var User|null $current */ $current = $this->route()->parameter('user'); $validator->after( static function (Validator $validator) use ($current) { $isAdmin = auth()->user()->hasRole('owner'); // not admin, and not own user? if (auth()->check() && false === $isAdmin && $current?->id !== auth()->user()->id) { - $validator->errors()->add('email', (string) trans('validation.invalid_selection')); + $validator->errors()->add('email', (string)trans('validation.invalid_selection')); } } ); } - } diff --git a/app/Api/V1/Requests/User/PreferenceStoreRequest.php b/app/Api/V1/Requests/User/PreferenceStoreRequest.php index 39d6b575ee..e1c9459ab4 100644 --- a/app/Api/V1/Requests/User/PreferenceStoreRequest.php +++ b/app/Api/V1/Requests/User/PreferenceStoreRequest.php @@ -29,7 +29,8 @@ use Illuminate\Foundation\Http\FormRequest; class PreferenceStoreRequest extends FormRequest { - use ChecksLogin, ConvertsDataTypes; + use ChecksLogin; + use ConvertsDataTypes; /** * @return array @@ -47,7 +48,7 @@ class PreferenceStoreRequest extends FormRequest $array['data'] = false; } if (is_numeric($array['data'])) { - $array['data'] = (float) $array['data']; // intentional float. + $array['data'] = (float)$array['data']; // intentional float. } return $array; @@ -63,5 +64,4 @@ class PreferenceStoreRequest extends FormRequest 'data' => 'required', ]; } - } diff --git a/app/Api/V1/Requests/User/PreferenceUpdateRequest.php b/app/Api/V1/Requests/User/PreferenceUpdateRequest.php index a115bfba0a..42f0a36992 100644 --- a/app/Api/V1/Requests/User/PreferenceUpdateRequest.php +++ b/app/Api/V1/Requests/User/PreferenceUpdateRequest.php @@ -30,7 +30,8 @@ use Illuminate\Foundation\Http\FormRequest; class PreferenceUpdateRequest extends FormRequest { - use ChecksLogin, ConvertsDataTypes; + use ChecksLogin; + use ConvertsDataTypes; /** * @return array @@ -48,7 +49,7 @@ class PreferenceUpdateRequest extends FormRequest $array['data'] = false; } if (is_numeric($array['data'])) { - $array['data'] = (float) $array['data']; // intentional float. + $array['data'] = (float)$array['data']; // intentional float. } return $array; @@ -63,5 +64,4 @@ class PreferenceUpdateRequest extends FormRequest 'data' => 'required', ]; } - } diff --git a/app/Api/V2/Controllers/Autocomplete/AccountController.php b/app/Api/V2/Controllers/Autocomplete/AccountController.php new file mode 100644 index 0000000000..eac0044f95 --- /dev/null +++ b/app/Api/V2/Controllers/Autocomplete/AccountController.php @@ -0,0 +1,34 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Autocomplete; + +use FireflyIII\Api\V2\Controllers\Controller; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ +} diff --git a/app/Api/V2/Controllers/Chart/AccountController.php b/app/Api/V2/Controllers/Chart/AccountController.php new file mode 100644 index 0000000000..a9e396cc68 --- /dev/null +++ b/app/Api/V2/Controllers/Chart/AccountController.php @@ -0,0 +1,125 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Chart; + +use Carbon\Carbon; +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Api\V2\Request\Generic\DateRequest; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountType; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Http\Api\ConvertsExchangeRates; +use Illuminate\Http\JsonResponse; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ + use ConvertsExchangeRates; + + private AccountRepositoryInterface $repository; + + /** + * + */ + public function __construct() + { + $this->middleware( + function ($request, $next) { + $this->repository = app(AccountRepositoryInterface::class); + return $next($request); + } + ); + } + + /** + * @param DateRequest $request + * @return JsonResponse + */ + public function dashboard(DateRequest $request): JsonResponse + { + // parameters for chart: + $dates = $request->getAll(); + /** @var Carbon $start */ + $start = $dates['start']; + /** @var Carbon $end */ + $end = $dates['end']; + + // user's preferences + $defaultSet = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT])->pluck('id')->toArray(); + $frontPage = app('preferences')->get('frontPageAccounts', $defaultSet); + $default = app('amount')->getDefaultCurrency(); + $accounts = $this->repository->getAccountsById($frontPage->data); + $chartData = []; + + if (!(is_array($frontPage->data) && count($frontPage->data) > 0)) { + $frontPage->data = $defaultSet; + $frontPage->save(); + } + + /** @var Account $account */ + foreach ($accounts as $account) { + $currency = $this->repository->getAccountCurrency($account); + if (null === $currency) { + $currency = $default; + } + $currentSet = [ + 'label' => $account->name, + 'currency_id' => (string)$currency->id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => $currency->decimal_places, + 'native_id' => null, + 'native_code' => null, + 'native_symbol' => null, + 'native_decimal_places' => null, + 'start_date' => $start->toAtomString(), + 'end_date' => $end->toAtomString(), + 'type' => 'line', // line, area or bar + 'yAxisID' => 0, // 0, 1, 2 + 'entries' => [], + ]; + $currentStart = clone $start; + $range = app('steam')->balanceInRange($account, $start, clone $end); + + // 2022-10-11: this method no longer converts to floats + + $previous = array_values($range)[0]; + while ($currentStart <= $end) { + $format = $currentStart->format('Y-m-d'); + $label = $currentStart->toAtomString(); + $balance = array_key_exists($format, $range) ? $range[$format] : $previous; + $previous = $balance; + $currentStart->addDay(); + $currentSet['entries'][$label] = $balance; + } + $currentSet = $this->cerChartSet($currentSet); + $chartData[] = $currentSet; + } + + return response()->json($chartData); + } +} diff --git a/app/Api/V2/Controllers/Controller.php b/app/Api/V2/Controllers/Controller.php new file mode 100644 index 0000000000..4295397932 --- /dev/null +++ b/app/Api/V2/Controllers/Controller.php @@ -0,0 +1,164 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers; + +use Carbon\Carbon; +use Carbon\Exceptions\InvalidDateException; +use Carbon\Exceptions\InvalidFormatException; +use FireflyIII\Transformers\V2\AbstractTransformer; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Pagination\LengthAwarePaginator; +use Illuminate\Routing\Controller as BaseController; +use Illuminate\Support\Collection; +use League\Fractal\Manager; +use League\Fractal\Pagination\IlluminatePaginatorAdapter; +use League\Fractal\Resource\Collection as FractalCollection; +use League\Fractal\Resource\Item; +use League\Fractal\Serializer\JsonApiSerializer; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class Controller + */ +class Controller extends BaseController +{ + protected const CONTENT_TYPE = 'application/vnd.api+json'; + protected int $pageSize; + protected ParameterBag $parameters; + + /** + * + */ + public function __construct() + { + $this->parameters = $this->getParameters(); + $this->pageSize = 50; + if (auth()->check()) { + $this->pageSize = (int)app('preferences')->getForUser(auth()->user(), 'listPageSize', 50)->data; + } + } + + /** + * TODO duplicate from V1 controller + * Method to grab all parameters from the URL. + * + * @return ParameterBag + */ + private function getParameters(): ParameterBag + { + $bag = new ParameterBag(); + try { + $page = (int)request()->get('page'); + } catch (ContainerExceptionInterface|NotFoundExceptionInterface $e) { + $page = 1; + } + + $integers = ['limit']; + $dates = ['start', 'end', 'date']; + + if ($page < 1) { + $page = 1; + } + if ($page > (2 ^ 16)) { + $page = (2 ^ 16); + } + $bag->set('page', $page); + + // some date fields: + foreach ($dates as $field) { + $date = request()->query->get($field); + $obj = null; + if (null !== $date) { + try { + $obj = Carbon::parse($date); + } catch (InvalidDateException|InvalidFormatException $e) { + // don't care + app('log')->warning(sprintf('Ignored invalid date "%s" in API v2 controller parameter check: %s', $date, $e->getMessage())); + } + } + $bag->set($field, $obj); + } + + // integer fields: + foreach ($integers as $integer) { + $value = request()->query->get($integer); + if (null !== $value) { + $bag->set($integer, (int)$value); + } + } + + // sort fields: + // return $this->getSortParameters($bag); + + return $bag; + } + + /** + * @param string $key + * @param LengthAwarePaginator $paginator + * @param AbstractTransformer $transformer + * @return array + */ + final protected function jsonApiList(string $key, LengthAwarePaginator $paginator, AbstractTransformer $transformer): array + { + $manager = new Manager(); + $baseUrl = request()->getSchemeAndHttpHost().'/api/v2'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $objects = $paginator->getCollection(); + + // the transformer, at this point, needs to collect information that ALL items in the collection + // require, like meta data and stuff like that, and save it for later. + $transformer->collectMetaData($objects); + + $resource = new FractalCollection($objects, $transformer, $key); + $resource->setPaginator(new IlluminatePaginatorAdapter($paginator)); + + return $manager->createData($resource)->toArray(); + } + + /** + * Returns a JSON API object and returns it. + * + * @param string $key + * @param Model $object + * @param AbstractTransformer $transformer + * @return array + */ + final protected function jsonApiObject(string $key, Model $object, AbstractTransformer $transformer): array + { + // create some objects: + $manager = new Manager(); + $baseUrl = request()->getSchemeAndHttpHost().'/api/v2'; + $manager->setSerializer(new JsonApiSerializer($baseUrl)); + + $transformer->collectMetaData(new Collection([$object])); + + $resource = new Item($object, $transformer, $key); + return $manager->createData($resource)->toArray(); + } +} diff --git a/app/Api/V2/Controllers/Data/Bulk/AccountController.php b/app/Api/V2/Controllers/Data/Bulk/AccountController.php new file mode 100644 index 0000000000..d869b8843f --- /dev/null +++ b/app/Api/V2/Controllers/Data/Bulk/AccountController.php @@ -0,0 +1,34 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Data\Bulk; + +use FireflyIII\Api\V2\Controllers\Controller; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ +} diff --git a/app/Api/V2/Controllers/Data/Export/AccountController.php b/app/Api/V2/Controllers/Data/Export/AccountController.php new file mode 100644 index 0000000000..3787530d57 --- /dev/null +++ b/app/Api/V2/Controllers/Data/Export/AccountController.php @@ -0,0 +1,34 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Data\Export; + +use FireflyIII\Api\V2\Controllers\Controller; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ +} diff --git a/app/Api/V2/Controllers/Data/MassDestroy/AccountController.php b/app/Api/V2/Controllers/Data/MassDestroy/AccountController.php new file mode 100644 index 0000000000..51c18b60fe --- /dev/null +++ b/app/Api/V2/Controllers/Data/MassDestroy/AccountController.php @@ -0,0 +1,34 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Data\MassDestroy; + +use FireflyIII\Api\V2\Controllers\Controller; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ +} diff --git a/app/Api/V2/Controllers/Model/Account/ShowController.php b/app/Api/V2/Controllers/Model/Account/ShowController.php new file mode 100644 index 0000000000..8755071334 --- /dev/null +++ b/app/Api/V2/Controllers/Model/Account/ShowController.php @@ -0,0 +1,51 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Model\Account; + +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Models\Account; +use FireflyIII\Transformers\V2\AccountTransformer; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; + +/** + * Class ShowController + */ +class ShowController extends Controller +{ + /** + * @param Account $account + * @return JsonResponse + */ + public function show(Request $request, Account $account): JsonResponse + { + $transformer = new AccountTransformer(); + $transformer->setParameters($this->parameters); + + return response() + ->api($this->jsonApiObject('accounts', $account, $transformer)) + ->header('Content-Type', self::CONTENT_TYPE); + } +} diff --git a/app/Api/V2/Controllers/Model/Bill/SumController.php b/app/Api/V2/Controllers/Model/Bill/SumController.php new file mode 100644 index 0000000000..ebb486953f --- /dev/null +++ b/app/Api/V2/Controllers/Model/Bill/SumController.php @@ -0,0 +1,82 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Model\Bill; + +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Api\V2\Request\Generic\DateRequest; +use FireflyIII\Repositories\Bill\BillRepositoryInterface; +use FireflyIII\Support\Http\Api\ConvertsExchangeRates; +use Illuminate\Http\JsonResponse; + +/** + * Class SumController + */ +class SumController extends Controller +{ + use ConvertsExchangeRates; + + private BillRepositoryInterface $repository; + + /** + * + */ + public function __construct() + { + $this->middleware( + function ($request, $next) { + $this->repository = app(BillRepositoryInterface::class); + return $next($request); + } + ); + } + + /** + * @param DateRequest $request + * @return JsonResponse + */ + public function paid(DateRequest $request): JsonResponse + { + $dates = $request->getAll(); + $result = $this->repository->sumPaidInRange($dates['start'], $dates['end']); + $converted = $this->cerSum($result); + + // convert to JSON response: + return response()->api($converted); + } + + /** + * @param DateRequest $request + * @return JsonResponse + */ + public function unpaid(DateRequest $request): JsonResponse + { + $dates = $request->getAll(); + $result = $this->repository->sumUnpaidInRange($dates['start'], $dates['end']); + $converted = $this->cerSum($result); + + // convert to JSON response: + return response()->api($converted); + } +} diff --git a/app/Api/V2/Controllers/Model/Budget/ListController.php b/app/Api/V2/Controllers/Model/Budget/ListController.php new file mode 100644 index 0000000000..1e1c0ac56c --- /dev/null +++ b/app/Api/V2/Controllers/Model/Budget/ListController.php @@ -0,0 +1,64 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Model\Budget; + +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use FireflyIII\Transformers\V2\BudgetTransformer; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; +use Illuminate\Pagination\LengthAwarePaginator; + +class ListController extends Controller +{ + private BudgetRepositoryInterface $repository; + + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + $this->repository = app(BudgetRepositoryInterface::class); + return $next($request); + } + ); + } + + /** + * @return JsonResponse + */ + public function index(Request $request): JsonResponse + { + $collection = $this->repository->getActiveBudgets(); + $total = $collection->count(); + $collection->slice($this->pageSize * $this->parameters->get('page'), $this->pageSize); + + $paginator = new LengthAwarePaginator($collection, $total, $this->pageSize, $this->parameters->get('page')); + $transformer = new BudgetTransformer(); + return response() + ->api($this->jsonApiList('budgets', $paginator, $transformer)) + ->header('Content-Type', self::CONTENT_TYPE); + } +} diff --git a/app/Api/V2/Controllers/Model/Budget/SumController.php b/app/Api/V2/Controllers/Model/Budget/SumController.php new file mode 100644 index 0000000000..ebd2f71591 --- /dev/null +++ b/app/Api/V2/Controllers/Model/Budget/SumController.php @@ -0,0 +1,80 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Model\Budget; + +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Api\V2\Request\Generic\DateRequest; +use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; +use FireflyIII\Support\Http\Api\ConvertsExchangeRates; +use Illuminate\Http\JsonResponse; + +/** + * Class SumController + */ +class SumController extends Controller +{ + use ConvertsExchangeRates; + + private BudgetRepositoryInterface $repository; + + /** + * + */ + public function __construct() + { + $this->middleware( + function ($request, $next) { + $this->repository = app(BudgetRepositoryInterface::class); + return $next($request); + } + ); + } + + /** + * @param DateRequest $request + * @return JsonResponse + */ + public function budgeted(DateRequest $request): JsonResponse + { + $data = $request->getAll(); + $result = $this->repository->budgetedInPeriod($data['start'], $data['end']); + $converted = $this->cerSum(array_values($result)); + + return response()->json($converted); + } + + /** + * @param DateRequest $request + * @return JsonResponse + */ + public function spent(DateRequest $request): JsonResponse + { + $data = $request->getAll(); + $result = $this->repository->spentInPeriod($data['start'], $data['end']); + $converted = $this->cerSum(array_values($result)); + + return response()->json($converted); + } +} diff --git a/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php b/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php new file mode 100644 index 0000000000..2c4732671e --- /dev/null +++ b/app/Api/V2/Controllers/Model/BudgetLimit/ListController.php @@ -0,0 +1,66 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Model\BudgetLimit; + +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Api\V2\Request\Generic\DateRequest; +use FireflyIII\Models\Budget; +use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; +use FireflyIII\Transformers\V2\BudgetLimitTransformer; +use Illuminate\Http\JsonResponse; +use Illuminate\Pagination\LengthAwarePaginator; + +class ListController extends Controller +{ + private BudgetLimitRepositoryInterface $repository; + + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + $this->repository = app(BudgetLimitRepositoryInterface::class); + return $next($request); + } + ); + } + + /** + * @return JsonResponse + */ + public function index(DateRequest $request, Budget $budget): JsonResponse + { + $dates = $request->getAll(); + $collection = $this->repository->getBudgetLimits($budget, $dates['start'], $dates['end']); + $total = $collection->count(); + $collection->slice($this->pageSize * $this->parameters->get('page'), $this->pageSize); + + $paginator = new LengthAwarePaginator($collection, $total, $this->pageSize, $this->parameters->get('page')); + $transformer = new BudgetLimitTransformer(); + return response() + ->api($this->jsonApiList('budget_limits', $paginator, $transformer)) + ->header('Content-Type', self::CONTENT_TYPE); + } +} diff --git a/app/Api/V2/Controllers/NetWorthController.php b/app/Api/V2/Controllers/NetWorthController.php new file mode 100644 index 0000000000..f4e1730be0 --- /dev/null +++ b/app/Api/V2/Controllers/NetWorthController.php @@ -0,0 +1,69 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers; + +use FireflyIII\Api\V2\Request\Generic\SingleDateRequest; +use FireflyIII\Helpers\Report\NetWorthInterface; +use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Http\Api\ConvertsExchangeRates; +use Illuminate\Http\JsonResponse; + +/** + * Class NetWorthController + */ +class NetWorthController extends Controller +{ + use ConvertsExchangeRates; + + private NetWorthInterface $netWorth; + + /** + * + */ + public function __construct() + { + parent::__construct(); + $this->middleware( + function ($request, $next) { + $this->netWorth = app(NetWorthInterface::class); + $this->netWorth->setUser(auth()->user()); + return $next($request); + } + ); + } + + /** + * @param SingleDateRequest $request + * @return JsonResponse + */ + public function get(SingleDateRequest $request): JsonResponse + { + $date = $request->getDate(); + $result = $this->netWorth->sumNetWorthByCurrency($date); + $converted = $this->cerSum($result); + + return response()->api($converted); + } +} diff --git a/app/Api/V2/Controllers/Search/AccountController.php b/app/Api/V2/Controllers/Search/AccountController.php new file mode 100644 index 0000000000..9c107899cf --- /dev/null +++ b/app/Api/V2/Controllers/Search/AccountController.php @@ -0,0 +1,34 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Search; + +use FireflyIII\Api\V2\Controllers\Controller; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ +} diff --git a/app/Api/V2/Controllers/System/ConfigurationController.php b/app/Api/V2/Controllers/System/ConfigurationController.php new file mode 100644 index 0000000000..3945e0680a --- /dev/null +++ b/app/Api/V2/Controllers/System/ConfigurationController.php @@ -0,0 +1,29 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\System; + +class ConfigurationController +{ +} diff --git a/app/Api/V2/Controllers/System/DebugController.php b/app/Api/V2/Controllers/System/DebugController.php new file mode 100644 index 0000000000..f1c07c8163 --- /dev/null +++ b/app/Api/V2/Controllers/System/DebugController.php @@ -0,0 +1,31 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\System; + +use FireflyIII\Api\V2\Controllers\Controller; + +class DebugController extends Controller +{ +} diff --git a/app/Api/V2/Controllers/System/PreferencesController.php b/app/Api/V2/Controllers/System/PreferencesController.php new file mode 100644 index 0000000000..cd3ac6bd31 --- /dev/null +++ b/app/Api/V2/Controllers/System/PreferencesController.php @@ -0,0 +1,47 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\System; + +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Models\Preference; +use FireflyIII\Transformers\V2\PreferenceTransformer; +use Illuminate\Http\JsonResponse; + +/** + * Class PreferencesController + */ +class PreferencesController extends Controller +{ + /** + * @param Preference $preference + * @return JsonResponse + */ + public function get(Preference $preference): JsonResponse + { + return response() + ->json($this->jsonApiObject('preferences', $preference, new PreferenceTransformer())) + ->header('Content-Type', self::CONTENT_TYPE); + } +} diff --git a/app/Api/V2/Controllers/Transaction/List/AccountController.php b/app/Api/V2/Controllers/Transaction/List/AccountController.php new file mode 100644 index 0000000000..07d6d126d6 --- /dev/null +++ b/app/Api/V2/Controllers/Transaction/List/AccountController.php @@ -0,0 +1,82 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Transaction\List; + +use FireflyIII\Api\V2\Controllers\Controller; +use FireflyIII\Api\V2\Request\Transaction\ListRequest; +use FireflyIII\Helpers\Collector\GroupCollectorInterface; +use FireflyIII\Models\Account; +use FireflyIII\Support\Http\Api\TransactionFilter; +use FireflyIII\Transformers\V2\TransactionGroupTransformer; +use Illuminate\Http\JsonResponse; +use Illuminate\Support\Collection; + +/** + * Class AccountController + */ +class AccountController extends Controller +{ + use TransactionFilter; + + /** + * @param ListRequest $request + * @param Account $account + * @return JsonResponse + */ + public function listTransactions(ListRequest $request, Account $account): JsonResponse + { + // collect transactions: + $type = $request->get('type') ?? 'default'; + $limit = (int)$request->get('limit'); + $page = (int)$request->get('page'); + $page = max($page, 1); + + if ($limit > 0 && $limit <= $this->pageSize) { + $this->pageSize = $limit; + } + + $types = $this->mapTransactionTypes($type); + + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setAccounts(new Collection([$account])) + ->withAPIInformation() + ->setLimit($this->pageSize) + ->setPage($page) + ->setTypes($types); + + // TODO date filter + //if (null !== $this->parameters->get('start') && null !== $this->parameters->get('end')) { + // $collector->setRange($this->parameters->get('start'), $this->parameters->get('end')); + //} + + $paginator = $collector->getPaginatedGroups(); + $paginator->setPath(route('api.v2.accounts.transactions', [$account->id])); // TODO . $this->buildParams() + + return response() + ->json($this->jsonApiList('transactions', $paginator, new TransactionGroupTransformer())) + ->header('Content-Type', self::CONTENT_TYPE); + } +} diff --git a/app/Api/V2/Controllers/Transaction/Sum/BillController.php b/app/Api/V2/Controllers/Transaction/Sum/BillController.php new file mode 100644 index 0000000000..bd031e34dc --- /dev/null +++ b/app/Api/V2/Controllers/Transaction/Sum/BillController.php @@ -0,0 +1,34 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers\Transaction\Sum; + +use FireflyIII\Api\V2\Controllers\Controller; + +/** + * Class BillController + */ +class BillController extends Controller +{ +} diff --git a/app/Api/V2/Controllers/VersionUpdateController.php b/app/Api/V2/Controllers/VersionUpdateController.php new file mode 100644 index 0000000000..0852ae7d74 --- /dev/null +++ b/app/Api/V2/Controllers/VersionUpdateController.php @@ -0,0 +1,32 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Controllers; + +/** + * Class VersionUpdateController + */ +class VersionUpdateController extends Controller +{ +} diff --git a/app/Api/V2/Request/Generic/DateRequest.php b/app/Api/V2/Request/Generic/DateRequest.php new file mode 100644 index 0000000000..2c9acfc13f --- /dev/null +++ b/app/Api/V2/Request/Generic/DateRequest.php @@ -0,0 +1,66 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Request\Generic; + +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Foundation\Http\FormRequest; + +/** + * Request class for end points that require date parameters. + * + * Class DateRequest + */ +class DateRequest extends FormRequest +{ + use ConvertsDataTypes; + use ChecksLogin; + + /** + * Get all data from the request. + * + * @return array + */ + public function getAll(): array + { + return [ + 'start' => $this->getCarbonDate('start'), + 'end' => $this->getCarbonDate('end'), + ]; + } + + /** + * The rules that the incoming request must be matched against. + * + * @return array + */ + public function rules(): array + { + return [ + 'start' => 'required|date|after:1900-01-01|before:2099-12-31', + 'end' => 'required|date|after_or_equal:start|before:2099-12-31|after:1900-01-01', + ]; + } +} diff --git a/app/Api/V2/Request/Generic/SingleDateRequest.php b/app/Api/V2/Request/Generic/SingleDateRequest.php new file mode 100644 index 0000000000..c76e6df39a --- /dev/null +++ b/app/Api/V2/Request/Generic/SingleDateRequest.php @@ -0,0 +1,63 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Request\Generic; + +use Carbon\Carbon; +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Foundation\Http\FormRequest; + +/** + * Request class for end points that require a date parameter. + * + * Class SingleDateRequest + */ +class SingleDateRequest extends FormRequest +{ + use ConvertsDataTypes; + use ChecksLogin; + + /** + * Get all data from the request. + * + * @return Carbon + */ + public function getDate(): Carbon + { + return $this->getCarbonDate('date'); + } + + /** + * The rules that the incoming request must be matched against. + * + * @return array + */ + public function rules(): array + { + return [ + 'date' => 'required|date|after:1900-01-01|before:2099-12-31', + ]; + } +} diff --git a/app/Api/V2/Request/Transaction/ListRequest.php b/app/Api/V2/Request/Transaction/ListRequest.php new file mode 100644 index 0000000000..4bbb03b90a --- /dev/null +++ b/app/Api/V2/Request/Transaction/ListRequest.php @@ -0,0 +1,47 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Request\Transaction; + +use FireflyIII\Support\Request\ChecksLogin; +use Illuminate\Foundation\Http\FormRequest; + +/** + * Class ListRequest + */ +class ListRequest extends FormRequest +{ + use ChecksLogin; + + /** + * @return array + */ + public function rules(): array + { + return [ + 'start' => 'date', + 'end' => 'date|after:start', + ]; + } +} diff --git a/app/Api/V2/Response/Sum/AutoSum.php b/app/Api/V2/Response/Sum/AutoSum.php new file mode 100644 index 0000000000..7b5ad63ada --- /dev/null +++ b/app/Api/V2/Response/Sum/AutoSum.php @@ -0,0 +1,69 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Api\V2\Response\Sum; + +use Closure; +use FireflyIII\Models\TransactionCurrency; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Collection; + +/** + * Class AutoSum + * @deprecated + */ +class AutoSum +{ + /** + * @param Collection $objects + * @param Closure $getCurrency + * @param Closure $getSum + * @return array + */ + public function autoSum(Collection $objects, Closure $getCurrency, Closure $getSum): array + { + $return = []; + /** @var Model $object */ + foreach ($objects as $object) { + /** @var TransactionCurrency $currency */ + $currency = $getCurrency($object); + /** @var string $amount */ + $amount = $getSum($object); + + $return[$currency->id] = $return[$currency->id] ?? [ + 'id' => (string)$currency->id, + 'name' => $currency->name, + 'symbol' => $currency->symbol, + 'code' => $currency->code, + 'decimal_places' => $currency->decimal_places, + 'sum' => '0', + ]; + + $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $amount); + } + + var_dump(array_values($return)); + exit; + } +} diff --git a/app/Console/Commands/Correction/CorrectDatabase.php b/app/Console/Commands/Correction/CorrectDatabase.php index db9d072f64..0696987b9c 100644 --- a/app/Console/Commands/Correction/CorrectDatabase.php +++ b/app/Console/Commands/Correction/CorrectDatabase.php @@ -77,6 +77,7 @@ class CorrectDatabase extends Command 'firefly-iii:fix-long-descriptions', 'firefly-iii:fix-recurring-transactions', 'firefly-iii:restore-oauth-keys', + 'firefly-iii:upgrade-group-information', 'firefly-iii:fix-transaction-types', 'firefly-iii:fix-frontpage-accounts', ]; diff --git a/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php b/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php index 6c5fba45c9..1d0fa1e0aa 100644 --- a/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php +++ b/app/Console/Commands/Correction/CorrectOpeningBalanceCurrencies.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Console\Commands\Correction; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Transaction; @@ -62,10 +63,9 @@ class CorrectOpeningBalanceCurrencies extends Command { Log::debug(sprintf('Now in %s', __METHOD__)); // get all OB journals: - $set = TransactionJournal - ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') - ->whereNull('transaction_journals.deleted_at') - ->where('transaction_types.type', TransactionType::OPENING_BALANCE)->get(['transaction_journals.*']); + $set = TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->whereNull('transaction_journals.deleted_at') + ->where('transaction_types.type', TransactionType::OPENING_BALANCE)->get(['transaction_journals.*']); $this->line(sprintf('Going to verify %d opening balance transactions.', $set->count())); $count = 0; @@ -91,7 +91,7 @@ class CorrectOpeningBalanceCurrencies extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return int */ @@ -101,7 +101,7 @@ class CorrectOpeningBalanceCurrencies extends Command $account = $this->getAccount($journal); if (null === $account) { $message = sprintf('Transaction journal #%d has no valid account. Cant fix this line.', $journal->id); - Log::warning($message); + app('log')->warning($message); $this->warn($message); return 0; @@ -113,7 +113,7 @@ class CorrectOpeningBalanceCurrencies extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Account|null */ @@ -132,11 +132,11 @@ class CorrectOpeningBalanceCurrencies extends Command } /** - * @param Account $account + * @param Account $account * * @return TransactionCurrency * @throws JsonException - * @throws \FireflyIII\Exceptions\FireflyException + * @throws FireflyException */ private function getCurrency(Account $account): TransactionCurrency { @@ -148,15 +148,15 @@ class CorrectOpeningBalanceCurrencies extends Command } /** - * @param TransactionJournal $journal - * @param TransactionCurrency $currency + * @param TransactionJournal $journal + * @param TransactionCurrency $currency * * @return int */ private function setCurrency(TransactionJournal $journal, TransactionCurrency $currency): int { $count = 0; - if ((int) $journal->transaction_currency_id !== (int) $currency->id) { + if ((int)$journal->transaction_currency_id !== (int)$currency->id) { $journal->transaction_currency_id = $currency->id; $journal->save(); $count = 1; @@ -164,7 +164,7 @@ class CorrectOpeningBalanceCurrencies extends Command /** @var Transaction $transaction */ foreach ($journal->transactions as $transaction) { - if ((int) $transaction->transaction_currency_id !== (int) $currency->id) { + if ((int)$transaction->transaction_currency_id !== (int)$currency->id) { $transaction->transaction_currency_id = $currency->id; $transaction->save(); $count = 1; diff --git a/app/Console/Commands/Correction/CreateLinkTypes.php b/app/Console/Commands/Correction/CreateLinkTypes.php index 0bdf1d924d..bec99fd9d5 100644 --- a/app/Console/Commands/Correction/CreateLinkTypes.php +++ b/app/Console/Commands/Correction/CreateLinkTypes.php @@ -63,7 +63,7 @@ class CreateLinkTypes extends Command $link = LinkType::where('name', $name) ->first(); if (null === $link) { - $link = new LinkType; + $link = new LinkType(); $link->name = $name; $link->inward = $values[1]; $link->outward = $values[0]; diff --git a/app/Console/Commands/Correction/DeleteEmptyGroups.php b/app/Console/Commands/Correction/DeleteEmptyGroups.php index bb5a0c52bf..1b88164f6d 100644 --- a/app/Console/Commands/Correction/DeleteEmptyGroups.php +++ b/app/Console/Commands/Correction/DeleteEmptyGroups.php @@ -58,9 +58,8 @@ class DeleteEmptyGroups extends Command Log::debug(sprintf('Now in %s', __METHOD__)); $start = microtime(true); $groupIds - = TransactionGroup - ::leftJoin('transaction_journals', 'transaction_groups.id', '=', 'transaction_journals.transaction_group_id') - ->whereNull('transaction_journals.id')->get(['transaction_groups.id'])->pluck('id')->toArray(); + = TransactionGroup::leftJoin('transaction_journals', 'transaction_groups.id', '=', 'transaction_journals.transaction_group_id') + ->whereNull('transaction_journals.id')->get(['transaction_groups.id'])->pluck('id')->toArray(); $total = count($groupIds); Log::debug(sprintf('Count is %d', $total)); diff --git a/app/Console/Commands/Correction/DeleteEmptyJournals.php b/app/Console/Commands/Correction/DeleteEmptyJournals.php index d1b4d4451a..5a1ff07926 100644 --- a/app/Console/Commands/Correction/DeleteEmptyJournals.php +++ b/app/Console/Commands/Correction/DeleteEmptyJournals.php @@ -24,10 +24,10 @@ declare(strict_types=1); namespace FireflyIII\Console\Commands\Correction; use DB; -use Exception; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use Illuminate\Console\Command; +use Illuminate\Database\QueryException; use Log; /** @@ -66,25 +66,23 @@ class DeleteEmptyJournals extends Command */ private function deleteUnevenJournals(): void { - $set = Transaction - ::whereNull('deleted_at') - ->groupBy('transactions.transaction_journal_id') - ->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']); + $set = Transaction::whereNull('deleted_at') + ->groupBy('transactions.transaction_journal_id') + ->get([DB::raw('COUNT(transactions.transaction_journal_id) as the_count'), 'transaction_journal_id']); $total = 0; /** @var Transaction $row */ foreach ($set as $row) { - $count = (int) $row->the_count; + $count = (int)$row->the_count; if (1 === $count % 2) { // uneven number, delete journal and transactions: try { - TransactionJournal::find((int) $row->transaction_journal_id)->delete(); - - } catch (Exception $e) { // @phpstan-ignore-line + TransactionJournal::find((int)$row->transaction_journal_id)->delete(); + } catch (QueryException $e) { Log::info(sprintf('Could not delete journal: %s', $e->getMessage())); } - Transaction::where('transaction_journal_id', (int) $row->transaction_journal_id)->delete(); + Transaction::where('transaction_journal_id', (int)$row->transaction_journal_id)->delete(); $this->info(sprintf('Deleted transaction journal #%d because it had an uneven number of transactions.', $row->transaction_journal_id)); $total++; } @@ -106,8 +104,7 @@ class DeleteEmptyJournals extends Command foreach ($set as $entry) { try { TransactionJournal::find($entry->id)->delete(); - - } catch (Exception $e) { // @phpstan-ignore-line + } catch (QueryException $e) { Log::info(sprintf('Could not delete entry: %s', $e->getMessage())); } @@ -121,5 +118,4 @@ class DeleteEmptyJournals extends Command $end = round(microtime(true) - $start, 2); $this->info(sprintf('Verified empty journals in %s seconds', $end)); } - } diff --git a/app/Console/Commands/Correction/DeleteOrphanedTransactions.php b/app/Console/Commands/Correction/DeleteOrphanedTransactions.php index 9e54af2e0f..1b2ab74827 100644 --- a/app/Console/Commands/Correction/DeleteOrphanedTransactions.php +++ b/app/Console/Commands/Correction/DeleteOrphanedTransactions.php @@ -27,6 +27,7 @@ use Exception; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use Illuminate\Console\Command; +use Illuminate\Database\QueryException; use Log; use stdClass; @@ -57,6 +58,7 @@ class DeleteOrphanedTransactions extends Command public function handle(): int { $start = microtime(true); + $this->deleteOrphanedJournals(); $this->deleteOrphanedTransactions(); $this->deleteFromOrphanedAccounts(); $end = round(microtime(true) - $start, 2); @@ -65,35 +67,64 @@ class DeleteOrphanedTransactions extends Command return 0; } + private function deleteOrphanedJournals(): void + { + $set = TransactionJournal::leftJoin('transaction_groups', 'transaction_journals.transaction_group_id', 'transaction_groups.id') + ->whereNotNull('transaction_groups.deleted_at') + ->whereNull('transaction_journals.deleted_at') + ->get(['transaction_journals.id', 'transaction_journals.transaction_group_id']); + $count = $set->count(); + if (0 === $count) { + $this->info('No orphaned journals.'); + } + if ($count > 0) { + $this->info(sprintf('Found %d orphaned journal(s).', $count)); + foreach ($set as $entry) { + $journal = TransactionJournal::withTrashed()->find((int)$entry->id); + if (null !== $journal) { + $journal->delete(); + $this->info( + sprintf( + 'Journal #%d (part of deleted transaction group #%d) has been deleted as well.', + $entry->id, + $entry->transaction_group_id + ) + ); + } + } + } + } + /** * @throws Exception */ private function deleteOrphanedTransactions(): void { $count = 0; - $set = Transaction - ::leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->whereNotNull('transaction_journals.deleted_at') - ->whereNull('transactions.deleted_at') - ->whereNotNull('transactions.id') - ->get( - [ - 'transaction_journals.id as journal_id', - 'transactions.id as transaction_id', - ] - ); + $set = Transaction::leftJoin('transaction_journals', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->whereNotNull('transaction_journals.deleted_at') + ->whereNull('transactions.deleted_at') + ->whereNotNull('transactions.id') + ->get( + [ + 'transaction_journals.id as journal_id', + 'transactions.id as transaction_id', + ] + ); /** @var stdClass $entry */ foreach ($set as $entry) { - $transaction = Transaction::find((int) $entry->transaction_id); - $transaction->delete(); - $this->info( - sprintf( - 'Transaction #%d (part of deleted transaction journal #%d) has been deleted as well.', - $entry->transaction_id, - $entry->journal_id - ) - ); - ++$count; + $transaction = Transaction::find((int)$entry->transaction_id); + if (null !== $transaction) { + $transaction->delete(); + $this->info( + sprintf( + 'Transaction #%d (part of deleted transaction journal #%d) has been deleted as well.', + $entry->transaction_id, + $entry->journal_id + ) + ); + ++$count; + } } if (0 === $count) { $this->info('No orphaned transactions.'); @@ -106,25 +137,18 @@ class DeleteOrphanedTransactions extends Command private function deleteFromOrphanedAccounts(): void { $set - = Transaction - ::leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id') - ->whereNotNull('accounts.deleted_at') - ->get(['transactions.*']); + = Transaction::leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id') + ->whereNotNull('accounts.deleted_at') + ->get(['transactions.*']); $count = 0; /** @var Transaction $transaction */ foreach ($set as $transaction) { // delete journals - $journal = TransactionJournal::find((int) $transaction->transaction_journal_id); + $journal = TransactionJournal::find((int)$transaction->transaction_journal_id); if ($journal) { - try { - $journal->delete(); - - } catch (Exception $e) { // @phpstan-ignore-line - Log::info(sprintf('Could not delete journal %s', $e->getMessage())); - } - + $journal->delete(); } - Transaction::where('transaction_journal_id', (int) $transaction->transaction_journal_id)->delete(); + Transaction::where('transaction_journal_id', (int)$transaction->transaction_journal_id)->delete(); $this->line( sprintf( 'Deleted transaction journal #%d because account #%d was already deleted.', diff --git a/app/Console/Commands/Correction/DeleteZeroAmount.php b/app/Console/Commands/Correction/DeleteZeroAmount.php index 6ff620ce97..5a7fabbd39 100644 --- a/app/Console/Commands/Correction/DeleteZeroAmount.php +++ b/app/Console/Commands/Correction/DeleteZeroAmount.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Console\Commands\Correction; -use Exception; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; use Illuminate\Console\Command; +use Illuminate\Database\QueryException; /** * Class DeleteZeroAmount @@ -60,12 +60,7 @@ class DeleteZeroAmount extends Command /** @var TransactionJournal $journal */ foreach ($journals as $journal) { $this->info(sprintf('Deleted transaction journal #%d because the amount is zero (0.00).', $journal->id)); - try { - $journal->delete(); - - } catch (Exception $e) { // @phpstan-ignore-line - $this->line($e->getMessage()); - } + $journal->delete(); Transaction::where('transaction_journal_id', $journal->id)->delete(); } diff --git a/app/Console/Commands/Correction/EnableCurrencies.php b/app/Console/Commands/Correction/EnableCurrencies.php index 3e1aaee2d1..16957c4ff6 100644 --- a/app/Console/Commands/Correction/EnableCurrencies.php +++ b/app/Console/Commands/Correction/EnableCurrencies.php @@ -63,34 +63,35 @@ class EnableCurrencies extends Command /** @var Collection $meta */ $meta = AccountMeta::where('name', 'currency_id')->groupBy('data')->get(['data']); foreach ($meta as $entry) { - $found[] = (int) $entry->data; + $found[] = (int)$entry->data; } // get all from journals: $journals = TransactionJournal::groupBy('transaction_currency_id')->get(['transaction_currency_id']); foreach ($journals as $entry) { - $found[] = (int) $entry->transaction_currency_id; + $found[] = (int)$entry->transaction_currency_id; } // get all from transactions $transactions = Transaction::groupBy('transaction_currency_id', 'foreign_currency_id')->get(['transaction_currency_id', 'foreign_currency_id']); foreach ($transactions as $entry) { - $found[] = (int) $entry->transaction_currency_id; - $found[] = (int) $entry->foreign_currency_id; + $found[] = (int)$entry->transaction_currency_id; + $found[] = (int)$entry->foreign_currency_id; } // get all from budget limits $limits = BudgetLimit::groupBy('transaction_currency_id')->get(['transaction_currency_id']); foreach ($limits as $entry) { - $found[] = (int) $entry->transaction_currency_id; + $found[] = (int)$entry->transaction_currency_id; } $found = array_values(array_unique($found)); $found = array_values( array_filter( - $found, function (int $currencyId) { - return $currencyId !== 0; - } + $found, + function (int $currencyId) { + return $currencyId !== 0; + } ) ); $message = sprintf('%d different currencies are currently in use.', count($found)); diff --git a/app/Console/Commands/Correction/FixAccountTypes.php b/app/Console/Commands/Correction/FixAccountTypes.php index 048c32d9b5..e3da62893d 100644 --- a/app/Console/Commands/Correction/FixAccountTypes.php +++ b/app/Console/Commands/Correction/FixAccountTypes.php @@ -48,7 +48,7 @@ class FixAccountTypes extends Command * * @var string */ - protected $signature = 'firefly-iii:fix-account-types'; + protected $signature = 'firefly-iii:fix-account-types'; private int $count; private array $expected; private AccountFactory $factory; @@ -99,7 +99,7 @@ class FixAccountTypes extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @throws FireflyException */ @@ -121,12 +121,10 @@ class FixAccountTypes extends Command $destAccountType = $destAccount->accountType->type; if (!array_key_exists($type, $this->expected)) { - Log::info(sprintf('No source/destination info for transaction type %s.', $type)); $this->info(sprintf('No source/destination info for transaction type %s.', $type)); return; - } if (!array_key_exists($sourceAccountType, $this->expected[$type])) { Log::debug(sprintf('Going to fix journal #%d', $journal->id)); @@ -142,7 +140,7 @@ class FixAccountTypes extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Transaction */ @@ -152,7 +150,7 @@ class FixAccountTypes extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Transaction */ @@ -162,10 +160,10 @@ class FixAccountTypes extends Command } /** - * @param TransactionJournal $journal - * @param string $type - * @param Transaction $source - * @param Transaction $dest + * @param TransactionJournal $journal + * @param string $type + * @param Transaction $source + * @param Transaction $dest * * @throws FireflyException */ @@ -211,8 +209,12 @@ class FixAccountTypes extends Command $dest->account()->associate($result); $dest->save(); $message = sprintf( - 'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").', $journal->id, $oldDest->id, $oldDest->name, - $result->id, $result->name + 'Transaction journal #%d, destination account changed from #%d ("%s") to #%d ("%s").', + $journal->id, + $oldDest->id, + $oldDest->name, + $result->id, + $result->name ); $this->info($message); Log::debug($message); @@ -227,8 +229,12 @@ class FixAccountTypes extends Command $source->account()->associate($result); $source->save(); $message = sprintf( - 'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").', $journal->id, $oldSource->id, $oldSource->name, - $result->id, $result->name + 'Transaction journal #%d, source account changed from #%d ("%s") to #%d ("%s").', + $journal->id, + $oldSource->id, + $oldSource->name, + $result->id, + $result->name ); $this->info($message); Log::debug($message); @@ -244,7 +250,6 @@ class FixAccountTypes extends Command Log::debug($message); break; - } } } diff --git a/app/Console/Commands/Correction/FixFrontpageAccounts.php b/app/Console/Commands/Correction/FixFrontpageAccounts.php index 64372c7db4..3175bc0e3d 100644 --- a/app/Console/Commands/Correction/FixFrontpageAccounts.php +++ b/app/Console/Commands/Correction/FixFrontpageAccounts.php @@ -73,7 +73,7 @@ class FixFrontpageAccounts extends Command } /** - * @param Preference $preference + * @param Preference $preference */ private function fixPreference(Preference $preference): void { @@ -88,7 +88,7 @@ class FixFrontpageAccounts extends Command if (is_array($data)) { /** @var string $accountId */ foreach ($data as $accountId) { - $accountIdInt = (int) $accountId; + $accountIdInt = (int)$accountId; $account = $repository->find($accountIdInt); if (null !== $account && in_array($account->accountType->type, [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], true) diff --git a/app/Console/Commands/Correction/FixGroupAccounts.php b/app/Console/Commands/Correction/FixGroupAccounts.php index 9ed55a330e..31fa005c63 100644 --- a/app/Console/Commands/Correction/FixGroupAccounts.php +++ b/app/Console/Commands/Correction/FixGroupAccounts.php @@ -57,19 +57,18 @@ class FixGroupAccounts extends Command public function handle(): int { $groups = []; - $res = TransactionJournal - ::groupBy('transaction_group_id') - ->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')]); + $res = TransactionJournal::groupBy('transaction_group_id') + ->get(['transaction_group_id', DB::raw('COUNT(transaction_group_id) as the_count')]); /** @var TransactionJournal $journal */ foreach ($res as $journal) { - if ((int) $journal->the_count > 1) { - $groups[] = (int) $journal->transaction_group_id; + if ((int)$journal->the_count > 1) { + $groups[] = (int)$journal->transaction_group_id; } } - $handler = new UpdatedGroupEventHandler; + $handler = new UpdatedGroupEventHandler(); foreach ($groups as $groupId) { $group = TransactionGroup::find($groupId); - $event = new UpdatedTransactionGroup($group); + $event = new UpdatedTransactionGroup($group, true, true); $handler->unifyAccounts($event); } diff --git a/app/Console/Commands/Correction/FixIbans.php b/app/Console/Commands/Correction/FixIbans.php index 6ecf3a1a62..f527e84f9a 100644 --- a/app/Console/Commands/Correction/FixIbans.php +++ b/app/Console/Commands/Correction/FixIbans.php @@ -57,8 +57,7 @@ class FixIbans extends Command foreach ($accounts as $account) { $iban = $account->iban; if (str_contains($iban, ' ')) { - - $iban = app('steam')->filterSpaces((string) $account->iban); + $iban = app('steam')->filterSpaces((string)$account->iban); if ('' !== $iban) { $account->iban = $iban; $account->save(); diff --git a/app/Console/Commands/Correction/FixLongDescriptions.php b/app/Console/Commands/Correction/FixLongDescriptions.php index 2dfd02d15b..32fa810ec7 100644 --- a/app/Console/Commands/Correction/FixLongDescriptions.php +++ b/app/Console/Commands/Correction/FixLongDescriptions.php @@ -68,7 +68,7 @@ class FixLongDescriptions extends Command $groups = TransactionGroup::get(['id', 'title']); /** @var TransactionGroup $group */ foreach ($groups as $group) { - if (strlen((string) $group->title) > self::MAX_LENGTH) { + if (strlen((string)$group->title) > self::MAX_LENGTH) { $group->title = substr($group->title, 0, self::MAX_LENGTH); $group->save(); $this->line(sprintf('Truncated description of transaction group #%d', $group->id)); diff --git a/app/Console/Commands/Correction/FixPiggies.php b/app/Console/Commands/Correction/FixPiggies.php index 22ea9c0967..8d2bca27c0 100644 --- a/app/Console/Commands/Correction/FixPiggies.php +++ b/app/Console/Commands/Correction/FixPiggies.php @@ -61,11 +61,10 @@ class FixPiggies extends Command /** @var PiggyBankEvent $event */ foreach ($set as $event) { - if (null === $event->transaction_journal_id) { continue; } - /** @var TransactionJournal $journal */ + /** @var TransactionJournal|null $journal */ $journal = $event->transactionJournal; if (null === $journal) { diff --git a/app/Console/Commands/Correction/FixPostgresSequences.php b/app/Console/Commands/Correction/FixPostgresSequences.php index 0b1862e295..babdc6a333 100644 --- a/app/Console/Commands/Correction/FixPostgresSequences.php +++ b/app/Console/Commands/Correction/FixPostgresSequences.php @@ -52,7 +52,6 @@ class FixPostgresSequences extends Command */ public function handle(): int { - if (DB::connection()->getName() !== 'pgsql') { $this->info('Command executed successfully.'); diff --git a/app/Console/Commands/Correction/FixRecurringTransactions.php b/app/Console/Commands/Correction/FixRecurringTransactions.php index ac6e047558..58329f08d6 100644 --- a/app/Console/Commands/Correction/FixRecurringTransactions.php +++ b/app/Console/Commands/Correction/FixRecurringTransactions.php @@ -96,7 +96,7 @@ class FixRecurringTransactions extends Command } /** - * @param User $user + * @param User $user */ private function processUser(User $user): void { @@ -109,7 +109,7 @@ class FixRecurringTransactions extends Command } /** - * @param Recurrence $recurrence + * @param Recurrence $recurrence */ private function processRecurrence(Recurrence $recurrence): void { @@ -120,8 +120,8 @@ class FixRecurringTransactions extends Command } /** - * @param Recurrence $recurrence - * @param RecurrenceTransaction $transaction + * @param Recurrence $recurrence + * @param RecurrenceTransaction $transaction */ private function processTransaction(Recurrence $recurrence, RecurrenceTransaction $transaction): void { diff --git a/app/Console/Commands/Correction/FixTransactionTypes.php b/app/Console/Commands/Correction/FixTransactionTypes.php index 8ca46f9507..9f461813b1 100644 --- a/app/Console/Commands/Correction/FixTransactionTypes.php +++ b/app/Console/Commands/Correction/FixTransactionTypes.php @@ -85,13 +85,12 @@ class FixTransactionTypes extends Command */ private function collectJournals(): Collection { - return TransactionJournal - ::with(['transactionType', 'transactions', 'transactions.account', 'transactions.account.accountType']) - ->get(); + return TransactionJournal::with(['transactionType', 'transactions', 'transactions.account', 'transactions.account.accountType']) + ->get(); } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return bool */ @@ -106,13 +105,18 @@ class FixTransactionTypes extends Command return false; } - $expectedType = (string) config(sprintf('firefly.account_to_transaction.%s.%s', $source->accountType->type, $destination->accountType->type)); + $expectedType = (string)config(sprintf('firefly.account_to_transaction.%s.%s', $source->accountType->type, $destination->accountType->type)); if ($expectedType !== $type) { $this->line( - sprintf('Transaction journal #%d was of type "%s" but is corrected to "%s" (%s -> %s)', - $journal->id, $type, $expectedType, - $source->accountType->type, $destination->accountType->type, - )); + sprintf( + 'Transaction journal #%d was of type "%s" but is corrected to "%s" (%s -> %s)', + $journal->id, + $type, + $expectedType, + $source->accountType->type, + $destination->accountType->type, + ) + ); $this->changeJournal($journal, $expectedType); return true; @@ -122,7 +126,7 @@ class FixTransactionTypes extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Account * @throws FireflyException @@ -142,6 +146,7 @@ class FixTransactionTypes extends Command } /** @var Transaction $transaction */ $transaction = $collection->first(); + /** @var Account|null $account */ $account = $transaction->account; if (null === $account) { throw new FireflyException(sprintf('Journal #%d, transaction #%d has no source account.', $journal->id, $transaction->id)); @@ -151,7 +156,7 @@ class FixTransactionTypes extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Account * @throws FireflyException @@ -171,6 +176,7 @@ class FixTransactionTypes extends Command } /** @var Transaction $transaction */ $transaction = $collection->first(); + /** @var Account|null $account */ $account = $transaction->account; if (null === $account) { throw new FireflyException(sprintf('Journal #%d, transaction #%d has no destination account.', $journal->id, $transaction->id)); @@ -180,8 +186,8 @@ class FixTransactionTypes extends Command } /** - * @param TransactionJournal $journal - * @param string $expectedType + * @param TransactionJournal $journal + * @param string $expectedType */ private function changeJournal(TransactionJournal $journal, string $expectedType): void { diff --git a/app/Console/Commands/Correction/FixUnevenAmount.php b/app/Console/Commands/Correction/FixUnevenAmount.php index f02cb4e445..7013a3fd4d 100644 --- a/app/Console/Commands/Correction/FixUnevenAmount.php +++ b/app/Console/Commands/Correction/FixUnevenAmount.php @@ -65,11 +65,11 @@ class FixUnevenAmount extends Command ->get(['transaction_journal_id', DB::raw('SUM(amount) AS the_sum')]); /** @var stdClass $entry */ foreach ($journals as $entry) { - if (0 !== bccomp((string) $entry->the_sum, '0')) { + if (0 !== bccomp((string)$entry->the_sum, '0')) { $message = sprintf('Sum of journal #%d is %s instead of zero.', $entry->transaction_journal_id, $entry->the_sum); $this->warn($message); - Log::warning($message); - $this->fixJournal((int) $entry->transaction_journal_id); + app('log')->warning($message); + $this->fixJournal((int)$entry->transaction_journal_id); $count++; } } @@ -84,7 +84,7 @@ class FixUnevenAmount extends Command } /** - * @param int $param + * @param int $param */ private function fixJournal(int $param): void { @@ -93,7 +93,7 @@ class FixUnevenAmount extends Command if (!$journal) { return; } - /** @var Transaction $source */ + /** @var Transaction|null $source */ $source = $journal->transactions()->where('amount', '<', 0)->first(); if (null === $source) { @@ -110,10 +110,10 @@ class FixUnevenAmount extends Command return; } - $amount = bcmul('-1', (string) $source->amount); + $amount = bcmul('-1', (string)$source->amount); // fix amount of destination: - /** @var Transaction $destination */ + /** @var Transaction|null $destination */ $destination = $journal->transactions()->where('amount', '>', 0)->first(); if (null === $destination) { diff --git a/app/Console/Commands/Correction/RemoveBills.php b/app/Console/Commands/Correction/RemoveBills.php index f4f2d0d1a4..4e4d6fc12c 100644 --- a/app/Console/Commands/Correction/RemoveBills.php +++ b/app/Console/Commands/Correction/RemoveBills.php @@ -53,7 +53,7 @@ class RemoveBills extends Command public function handle(): int { $start = microtime(true); - /** @var TransactionType $withdrawal */ + /** @var TransactionType|null $withdrawal */ $withdrawal = TransactionType::where('type', TransactionType::WITHDRAWAL)->first(); if (null === $withdrawal) { return 0; diff --git a/app/Console/Commands/Correction/RenameMetaFields.php b/app/Console/Commands/Correction/RenameMetaFields.php index 480f586700..ff070f3707 100644 --- a/app/Console/Commands/Correction/RenameMetaFields.php +++ b/app/Console/Commands/Correction/RenameMetaFields.php @@ -87,8 +87,8 @@ class RenameMetaFields extends Command } /** - * @param string $original - * @param string $update + * @param string $original + * @param string $update */ private function rename(string $original, string $update): void { diff --git a/app/Console/Commands/CreateFirstUser.php b/app/Console/Commands/CreateFirstUser.php index aa7a4d10b6..427ef53727 100644 --- a/app/Console/Commands/CreateFirstUser.php +++ b/app/Console/Commands/CreateFirstUser.php @@ -47,7 +47,7 @@ class CreateFirstUser extends Command * * @var string */ - protected $signature = 'firefly-iii:create-first-user {email}'; + protected $signature = 'firefly-iii:create-first-user {email}'; private UserRepositoryInterface $repository; /** @@ -97,6 +97,5 @@ class CreateFirstUser extends Command private function stupidLaravel(): void { $this->repository = app(UserRepositoryInterface::class); - } } diff --git a/app/Console/Commands/DecryptDatabase.php b/app/Console/Commands/DecryptDatabase.php index 465bea2193..f0c82a920d 100644 --- a/app/Console/Commands/DecryptDatabase.php +++ b/app/Console/Commands/DecryptDatabase.php @@ -32,6 +32,8 @@ use Illuminate\Console\Command; use Illuminate\Contracts\Encryption\DecryptException; use JsonException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; use stdClass; /** @@ -75,7 +77,7 @@ class DecryptDatabase extends Command ]; /** * @var string $table - * @var array $fields + * @var array $fields */ foreach ($tables as $table => $fields) { $this->decryptTable($table, $fields); @@ -86,8 +88,8 @@ class DecryptDatabase extends Command } /** - * @param string $table - * @param array $fields + * @param string $table + * @param array $fields */ private function decryptTable(string $table, array $fields): void { @@ -106,11 +108,11 @@ class DecryptDatabase extends Command } /** - * @param string $table + * @param string $table * * @return bool - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isDecrypted(string $table): bool { @@ -122,15 +124,15 @@ class DecryptDatabase extends Command Log::error($e->getMessage()); } if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; } /** - * @param string $table - * @param string $field + * @param string $table + * @param string $field */ private function decryptField(string $table, string $field): void { @@ -142,9 +144,9 @@ class DecryptDatabase extends Command } /** - * @param string $table - * @param string $field - * @param stdClass $row + * @param string $table + * @param string $field + * @param stdClass $row */ private function decryptRow(string $table, string $field, stdClass $row): void { @@ -152,7 +154,7 @@ class DecryptDatabase extends Command if (null === $original) { return; } - $id = (int) $row->id; + $id = (int)$row->id; $value = ''; try { @@ -179,7 +181,7 @@ class DecryptDatabase extends Command /** * Tries to decrypt data. Will only throw an exception when the MAC is invalid. * - * @param mixed $value + * @param mixed $value * * @return string * @throws FireflyException @@ -198,8 +200,8 @@ class DecryptDatabase extends Command } /** - * @param int $id - * @param string $value + * @param int $id + * @param string $value */ private function decryptPreferencesRow(int $id, string $value): void { @@ -209,15 +211,15 @@ class DecryptDatabase extends Command } catch (JsonException $e) { $message = sprintf('Could not JSON decode preference row #%d: %s. This does not have to be a problem.', $id, $e->getMessage()); $this->error($message); - Log::warning($message); - Log::warning($value); - Log::warning($e->getTraceAsString()); + app('log')->warning($message); + app('log')->warning($value); + app('log')->warning($e->getTraceAsString()); return; } /** @var Preference $object */ - $object = Preference::find((int) $id); + $object = Preference::find((int)$id); if (null !== $object) { $object->data = $newValue; $object->save(); diff --git a/app/Console/Commands/Export/ExportData.php b/app/Console/Commands/Export/ExportData.php index 7aea9a3df4..108e2d0b8e 100644 --- a/app/Console/Commands/Export/ExportData.php +++ b/app/Console/Commands/Export/ExportData.php @@ -56,7 +56,7 @@ class ExportData extends Command * * @var string */ - protected $signature = 'firefly-iii:export-data + protected $signature = 'firefly-iii:export-data {--user=1 : The user ID that the export should run for.} {--token= : The user\'s access token.} {--start= : First transaction to export. Defaults to your very first transaction. Only applies to transaction export.} @@ -121,11 +121,11 @@ class ExportData extends Command $exporter->setExportBills($options['export']['bills']); $exporter->setExportPiggies($options['export']['piggies']); $data = $exporter->export(); - if (empty($data)) { + if (0 === count($data)) { $this->error('You must export *something*. Use --export-transactions or another option. See docs.firefly-iii.org'); } $returnCode = 0; - if (!empty($data)) { + if (0 !== count($data)) { try { $this->exportData($options, $data); } catch (FireflyException $e) { @@ -184,7 +184,7 @@ class ExportData extends Command } /** - * @param string $field + * @param string $field * * @return Carbon * @throws Exception @@ -230,11 +230,11 @@ class ExportData extends Command */ private function getAccountsParameter(): Collection { - $final = new Collection; - $accounts = new Collection; + $final = new Collection(); + $accounts = new Collection(); $accountList = $this->option('accounts'); $types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]; - if (null !== $accountList && '' !== (string) $accountList) { + if (null !== $accountList && '' !== (string)$accountList) { $accountIds = explode(',', $accountList); $accounts = $this->accountRepository->getAccountsById($accountIds); } @@ -262,7 +262,7 @@ class ExportData extends Command */ private function getExportDirectory(): string { - $directory = (string) $this->option('export_directory'); + $directory = (string)$this->option('export_directory'); if (null === $directory) { $directory = './'; } @@ -274,8 +274,8 @@ class ExportData extends Command } /** - * @param array $options - * @param array $data + * @param array $options + * @param array $data * * @throws FireflyException */ diff --git a/app/Console/Commands/Integrity/ReportEmptyObjects.php b/app/Console/Commands/Integrity/ReportEmptyObjects.php index fe1d9eaa3b..73c8814261 100644 --- a/app/Console/Commands/Integrity/ReportEmptyObjects.php +++ b/app/Console/Commands/Integrity/ReportEmptyObjects.php @@ -131,7 +131,6 @@ class ReportEmptyObjects extends Command /** @var stdClass $entry */ foreach ($set as $entry) { - $line = sprintf( 'User #%d (%s) has tag #%d ("%s") which has no transaction journals.', $entry->user_id, diff --git a/app/Console/Commands/Integrity/ReportIntegrity.php b/app/Console/Commands/Integrity/ReportIntegrity.php index c4f7122fb6..e9bc2dbfa2 100644 --- a/app/Console/Commands/Integrity/ReportIntegrity.php +++ b/app/Console/Commands/Integrity/ReportIntegrity.php @@ -34,7 +34,6 @@ use Schema; */ class ReportIntegrity extends Command { - /** * The console command description. * diff --git a/app/Console/Commands/Integrity/ReportSum.php b/app/Console/Commands/Integrity/ReportSum.php index f88fe087d1..5b5bcb8dc1 100644 --- a/app/Console/Commands/Integrity/ReportSum.php +++ b/app/Console/Commands/Integrity/ReportSum.php @@ -68,7 +68,7 @@ class ReportSum extends Command /** @var User $user */ foreach ($userRepository->all() as $user) { - $sum = (string) $user->transactions()->sum('amount'); + $sum = (string)$user->transactions()->sum('amount'); if (0 !== bccomp($sum, '0')) { $message = sprintf('Error: Transactions for user #%d (%s) are off by %s!', $user->id, $user->email, $sum); $this->error($message); @@ -79,6 +79,5 @@ class ReportSum extends Command } $end = round(microtime(true) - $start, 2); $this->info(sprintf('Report on total sum finished in %s seconds', $end)); - } } diff --git a/app/Console/Commands/Integrity/RestoreOAuthKeys.php b/app/Console/Commands/Integrity/RestoreOAuthKeys.php index 3e50f177e3..29104ed079 100644 --- a/app/Console/Commands/Integrity/RestoreOAuthKeys.php +++ b/app/Console/Commands/Integrity/RestoreOAuthKeys.php @@ -80,7 +80,7 @@ class RestoreOAuthKeys extends Command return; } - Log::warning('Could not restore keys. Will create new ones.'); + app('log')->warning('Could not restore keys. Will create new ones.'); $this->generateKeys(); $this->storeKeysInDB(); $this->line('Generated and stored new keys.'); diff --git a/app/Console/Commands/Integrity/UpdateGroupInformation.php b/app/Console/Commands/Integrity/UpdateGroupInformation.php new file mode 100644 index 0000000000..a373f9eb0b --- /dev/null +++ b/app/Console/Commands/Integrity/UpdateGroupInformation.php @@ -0,0 +1,129 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Console\Commands\Integrity; + +use FireflyIII\Models\Account; +use FireflyIII\Models\Attachment; +use FireflyIII\Models\AvailableBudget; +use FireflyIII\Models\Bill; +use FireflyIII\Models\Budget; +use FireflyIII\Models\Category; +use FireflyIII\Models\CurrencyExchangeRate; +use FireflyIII\Models\Recurrence; +use FireflyIII\Models\Rule; +use FireflyIII\Models\RuleGroup; +use FireflyIII\Models\Tag; +use FireflyIII\Models\TransactionGroup; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\UserGroup; +use FireflyIII\Models\Webhook; +use FireflyIII\User; +use Illuminate\Console\Command; +use Illuminate\Database\QueryException; + +/** + * Class UpdateGroupInformation + */ +class UpdateGroupInformation extends Command +{ + /** + * The console command description. + * + * @var string + */ + protected $description = 'Makes sure that every object is linked to a group'; + /** + * The name and signature of the console command. + * + * @var string + */ + protected $signature = 'firefly-iii:upgrade-group-information'; + + /** + * Execute the console command. + * + * @return int + */ + public function handle() + { + // objects: accounts, attachments, available budgets, bills, budgets, categories, currency_exchange_rates + // recurrences, rule groups, rules, tags, transaction groups, transaction journals, webhooks + + $users = User::get(); + /** @var User $user */ + foreach ($users as $user) { + $this->updateGroupInfo($user); + } + + return 0; + } + + private function updateGroupInfo(User $user): void + { + $group = $user->userGroup; + if (null === $group) { + $this->warn(sprintf('User "%s" has no group.', $user->email)); + return; + } + $set = [ + Account::class, + Attachment::class, + AvailableBudget::class, + Bill::class, + Budget::class, + Category::class, + CurrencyExchangeRate::class, + Recurrence::class, + RuleGroup::class, + Rule::class, + Tag::class, + TransactionGroup::class, + TransactionJournal::class, + Webhook::class, + ]; + foreach ($set as $className) { + $this->updateGroupInfoForObject($user, $group, $className); + } + } + + /** + * @param User $user + * @param UserGroup $group + * @param string $className + * @return void + */ + private function updateGroupInfoForObject(User $user, UserGroup $group, string $className): void + { + try { + $result = $className::where('user_id', $user->id)->where('user_group_id', null)->update(['user_group_id' => $group->id]); + } catch (QueryException $e) { + $this->error(sprintf('Could not update group information for "%s" because of error "%s"', $className, $e->getMessage())); + return; + } + if (0 !== $result) { + $this->line(sprintf('Moved %d %s objects to the correct group.', $result, str_replace('FireflyIII\\Models\\', '', $className))); + } + } +} diff --git a/app/Console/Commands/Tools/ApplyRules.php b/app/Console/Commands/Tools/ApplyRules.php index 0e4cf33cfb..576259c6bb 100644 --- a/app/Console/Commands/Tools/ApplyRules.php +++ b/app/Console/Commands/Tools/ApplyRules.php @@ -56,7 +56,7 @@ class ApplyRules extends Command * * @var string */ - protected $signature + protected $signature = 'firefly-iii:apply-rules {--user=1 : The user ID.} {--token= : The user\'s access token.} @@ -161,13 +161,13 @@ class ApplyRules extends Command private function stupidLaravel(): void { $this->allRules = false; - $this->accounts = new Collection; + $this->accounts = new Collection(); $this->ruleSelection = []; $this->ruleGroupSelection = []; $this->ruleRepository = app(RuleRepositoryInterface::class); $this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class); $this->acceptedAccounts = [AccountType::DEFAULT, AccountType::DEBT, AccountType::ASSET, AccountType::LOAN, AccountType::MORTGAGE]; - $this->groups = new Collection; + $this->groups = new Collection(); } /** @@ -205,14 +205,14 @@ class ApplyRules extends Command return false; } - $finalList = new Collection; + $finalList = new Collection(); $accountList = explode(',', $accountString); /** @var AccountRepositoryInterface $accountRepository */ $accountRepository = app(AccountRepositoryInterface::class); $accountRepository->setUser($this->getUser()); foreach ($accountList as $accountId) { - $accountId = (int) $accountId; + $accountId = (int)$accountId; $account = $accountRepository->find($accountId); if (null !== $account && in_array($account->accountType->type, $this->acceptedAccounts, true)) { $finalList->push($account); @@ -227,7 +227,6 @@ class ApplyRules extends Command $this->accounts = $finalList; return true; - } /** @@ -243,7 +242,7 @@ class ApplyRules extends Command $ruleGroupList = explode(',', $ruleGroupString); foreach ($ruleGroupList as $ruleGroupId) { - $ruleGroup = $this->ruleGroupRepository->find((int) $ruleGroupId); + $ruleGroup = $this->ruleGroupRepository->find((int)$ruleGroupId); if ($ruleGroup->active) { $this->ruleGroupSelection[] = $ruleGroup->id; } @@ -268,7 +267,7 @@ class ApplyRules extends Command $ruleList = explode(',', $ruleString); foreach ($ruleList as $ruleId) { - $rule = $this->ruleRepository->find((int) $ruleId); + $rule = $this->ruleRepository->find((int)$ruleId); if (null !== $rule && $rule->active) { $this->ruleSelection[] = $rule->id; } @@ -325,7 +324,7 @@ class ApplyRules extends Command */ private function getRulesToApply(): Collection { - $rulesToApply = new Collection; + $rulesToApply = new Collection(); /** @var RuleGroup $group */ foreach ($this->groups as $group) { $rules = $this->ruleGroupRepository->getActiveStoreRules($group); @@ -344,8 +343,8 @@ class ApplyRules extends Command } /** - * @param Rule $rule - * @param RuleGroup $group + * @param Rule $rule + * @param RuleGroup $group * * @return bool */ diff --git a/app/Console/Commands/Tools/Cron.php b/app/Console/Commands/Tools/Cron.php index 81cd65fe54..9b7269e90b 100644 --- a/app/Console/Commands/Tools/Cron.php +++ b/app/Console/Commands/Tools/Cron.php @@ -28,6 +28,7 @@ use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Support\Cronjobs\AutoBudgetCronjob; use FireflyIII\Support\Cronjobs\BillWarningCronjob; +use FireflyIII\Support\Cronjobs\ExchangeRatesCronjob; use FireflyIII\Support\Cronjobs\RecurringCronjob; use Illuminate\Console\Command; use InvalidArgumentException; @@ -67,7 +68,20 @@ class Cron extends Command } catch (InvalidArgumentException $e) { $this->error(sprintf('"%s" is not a valid date', $this->option('date'))); } - $force = (bool) $this->option('force'); + $force = (bool)$this->option('force'); + + /* + * Fire recurring transaction cron job. + */ + if (true === config('cer.enabled')) { + try { + $this->exchangeRatesCronJob($force, $date); + } catch (FireflyException $e) { + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); + $this->error($e->getMessage()); + } + } /* * Fire recurring transaction cron job. @@ -108,14 +122,41 @@ class Cron extends Command } /** - * @param bool $force - * @param Carbon|null $date + * @param bool $force + * @param Carbon|null $date + * @throws FireflyException + */ + private function exchangeRatesCronJob(bool $force, ?Carbon $date): void + { + $exchangeRates = new ExchangeRatesCronjob(); + $exchangeRates->setForce($force); + // set date in cron job: + if (null !== $date) { + $exchangeRates->setDate($date); + } + + $exchangeRates->fire(); + + if ($exchangeRates->jobErrored) { + $this->error(sprintf('Error in "exchange rates" cron: %s', $exchangeRates->message)); + } + if ($exchangeRates->jobFired) { + $this->line(sprintf('"Exchange rates" cron fired: %s', $exchangeRates->message)); + } + if ($exchangeRates->jobSucceeded) { + $this->info(sprintf('"Exchange rates" cron ran with success: %s', $exchangeRates->message)); + } + } + + /** + * @param bool $force + * @param Carbon|null $date * * @throws FireflyException */ private function recurringCronJob(bool $force, ?Carbon $date): void { - $recurring = new RecurringCronjob; + $recurring = new RecurringCronjob(); $recurring->setForce($force); // set date in cron job: @@ -128,21 +169,21 @@ class Cron extends Command $this->error(sprintf('Error in "create recurring transactions" cron: %s', $recurring->message)); } if ($recurring->jobFired) { - $this->error(sprintf('"Create recurring transactions" cron fired: %s', $recurring->message)); + $this->line(sprintf('"Create recurring transactions" cron fired: %s', $recurring->message)); } if ($recurring->jobSucceeded) { - $this->error(sprintf('"Create recurring transactions" cron ran with success: %s', $recurring->message)); + $this->info(sprintf('"Create recurring transactions" cron ran with success: %s', $recurring->message)); } } /** - * @param bool $force - * @param Carbon|null $date + * @param bool $force + * @param Carbon|null $date * */ private function autoBudgetCronJob(bool $force, ?Carbon $date): void { - $autoBudget = new AutoBudgetCronjob; + $autoBudget = new AutoBudgetCronjob(); $autoBudget->setForce($force); // set date in cron job: if (null !== $date) { @@ -155,22 +196,21 @@ class Cron extends Command $this->error(sprintf('Error in "create auto budgets" cron: %s', $autoBudget->message)); } if ($autoBudget->jobFired) { - $this->error(sprintf('"Create auto budgets" cron fired: %s', $autoBudget->message)); + $this->line(sprintf('"Create auto budgets" cron fired: %s', $autoBudget->message)); } if ($autoBudget->jobSucceeded) { - $this->error(sprintf('"Create auto budgets" cron ran with success: %s', $autoBudget->message)); + $this->info(sprintf('"Create auto budgets" cron ran with success: %s', $autoBudget->message)); } - } /** - * @param bool $force - * @param Carbon|null $date + * @param bool $force + * @param Carbon|null $date * @throws FireflyException */ private function billWarningCronJob(bool $force, ?Carbon $date): void { - $autoBudget = new BillWarningCronjob; + $autoBudget = new BillWarningCronjob(); $autoBudget->setForce($force); // set date in cron job: if (null !== $date) { @@ -183,11 +223,10 @@ class Cron extends Command $this->error(sprintf('Error in "bill warnings" cron: %s', $autoBudget->message)); } if ($autoBudget->jobFired) { - $this->error(sprintf('"Send bill warnings" cron fired: %s', $autoBudget->message)); + $this->line(sprintf('"Send bill warnings" cron fired: %s', $autoBudget->message)); } if ($autoBudget->jobSucceeded) { - $this->error(sprintf('"Send bill warnings" cron ran with success: %s', $autoBudget->message)); + $this->info(sprintf('"Send bill warnings" cron ran with success: %s', $autoBudget->message)); } - } } diff --git a/app/Console/Commands/Upgrade/AccountCurrencies.php b/app/Console/Commands/Upgrade/AccountCurrencies.php index 617fe579ad..8734353548 100644 --- a/app/Console/Commands/Upgrade/AccountCurrencies.php +++ b/app/Console/Commands/Upgrade/AccountCurrencies.php @@ -34,6 +34,8 @@ use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Illuminate\Console\Command; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class AccountCurrencies @@ -109,14 +111,14 @@ class AccountCurrencies extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -129,7 +131,7 @@ class AccountCurrencies extends Command { Log::debug('Now in updateAccountCurrencies()'); $users = $this->userRepos->all(); - $defaultCurrencyCode = (string) config('firefly.default_currency', 'EUR'); + $defaultCurrencyCode = (string)config('firefly.default_currency', 'EUR'); Log::debug(sprintf('Default currency is %s', $defaultCurrencyCode)); foreach ($users as $user) { $this->updateCurrenciesForUser($user, $defaultCurrencyCode); @@ -137,8 +139,8 @@ class AccountCurrencies extends Command } /** - * @param User $user - * @param string $systemCurrencyCode + * @param User $user + * @param string $systemCurrencyCode * * @throws FireflyException */ @@ -172,21 +174,21 @@ class AccountCurrencies extends Command } /** - * @param Account $account - * @param TransactionCurrency $currency + * @param Account $account + * @param TransactionCurrency $currency */ private function updateAccount(Account $account, TransactionCurrency $currency): void { Log::debug(sprintf('Now in updateAccount(%d, %s)', $account->id, $currency->code)); $this->accountRepos->setUser($account->user); - $accountCurrency = (int) $this->accountRepos->getMetaValue($account, 'currency_id'); + $accountCurrency = (int)$this->accountRepos->getMetaValue($account, 'currency_id'); Log::debug(sprintf('Account currency is #%d', $accountCurrency)); $openingBalance = $this->accountRepos->getOpeningBalance($account); $obCurrency = 0; if (null !== $openingBalance) { - $obCurrency = (int) $openingBalance->transaction_currency_id; + $obCurrency = (int)$openingBalance->transaction_currency_id; Log::debug('Account has opening balance.'); } Log::debug(sprintf('Account OB currency is #%d.', $obCurrency)); diff --git a/app/Console/Commands/Upgrade/AppendBudgetLimitPeriods.php b/app/Console/Commands/Upgrade/AppendBudgetLimitPeriods.php index 0558fe99c4..32d1f735f5 100644 --- a/app/Console/Commands/Upgrade/AppendBudgetLimitPeriods.php +++ b/app/Console/Commands/Upgrade/AppendBudgetLimitPeriods.php @@ -27,6 +27,8 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\BudgetLimit; use Illuminate\Console\Command; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; class AppendBudgetLimitPeriods extends Command { @@ -72,14 +74,14 @@ class AppendBudgetLimitPeriods extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); - return (bool) $configVar->data; + return (bool)$configVar->data; } /** @@ -95,7 +97,7 @@ class AppendBudgetLimitPeriods extends Command } /** - * @param BudgetLimit $limit + * @param BudgetLimit $limit */ private function fixLimit(BudgetLimit $limit) { @@ -103,10 +105,13 @@ class AppendBudgetLimitPeriods extends Command if (null === $period) { $message = sprintf( - 'Could not guesstimate budget limit #%d (%s - %s) period.', $limit->id, $limit->start_date->format('Y-m-d'), $limit->end_date->format('Y-m-d') + 'Could not guesstimate budget limit #%d (%s - %s) period.', + $limit->id, + $limit->start_date->format('Y-m-d'), + $limit->end_date->format('Y-m-d') ); $this->warn($message); - Log::warning($message); + app('log')->warning($message); return; } @@ -114,14 +119,17 @@ class AppendBudgetLimitPeriods extends Command $limit->save(); $msg = sprintf( - 'Budget limit #%d (%s - %s) period is "%s".', $limit->id, $limit->start_date->format('Y-m-d'), $limit->end_date->format('Y-m-d'), $period + 'Budget limit #%d (%s - %s) period is "%s".', + $limit->id, + $limit->start_date->format('Y-m-d'), + $limit->end_date->format('Y-m-d'), + $period ); Log::debug($msg); - } /** - * @param BudgetLimit $limit + * @param BudgetLimit $limit * * @return string|null */ @@ -159,8 +167,8 @@ class AppendBudgetLimitPeriods extends Command $start = ['1-1', '1-7']; $end = ['30-6', '31-12']; if ( - in_array($limit->start_date->format('j-n'), $start) // start of quarter - && in_array($limit->end_date->format('j-n'), $end) // end of quarter + in_array($limit->start_date->format('j-n'), $start, true) // start of quarter + && in_array($limit->end_date->format('j-n'), $end, true) // end of quarter && 5 === $limit->start_date->diffInMonths($limit->end_date) ) { return 'half_year'; diff --git a/app/Console/Commands/Upgrade/BackToJournals.php b/app/Console/Commands/Upgrade/BackToJournals.php index f3b3c61b11..e0a8454410 100644 --- a/app/Console/Commands/Upgrade/BackToJournals.php +++ b/app/Console/Commands/Upgrade/BackToJournals.php @@ -32,6 +32,8 @@ use FireflyIII\Models\TransactionJournal; use Illuminate\Console\Command; use Illuminate\Support\Collection; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class BackToJournals @@ -60,7 +62,6 @@ class BackToJournals extends Command */ public function handle(): int { - $start = microtime(true); if (!$this->isMigrated()) { $this->error('Please run firefly-iii:migrate-to-groups first.'); @@ -85,28 +86,25 @@ class BackToJournals extends Command /** * @return bool - * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface */ private function isMigrated(): bool { $configVar = app('fireflyconfig')->get(MigrateToGroups::CONFIG_NAME, false); - return (bool) $configVar->data; + return (bool)$configVar->data; } /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); - return (bool) $configVar->data; + return (bool)$configVar->data; } /** @@ -128,7 +126,7 @@ class BackToJournals extends Command */ private function migrateBudgets(): void { - $journals = new Collection; + $journals = new Collection(); $allIds = $this->getIdsForBudgets(); $chunks = array_chunk($allIds, 500); foreach ($chunks as $journalIds) { @@ -147,12 +145,12 @@ class BackToJournals extends Command */ private function getIdsForBudgets(): array { - $transactions = DB::table('budget_transaction')->distinct()->get(['transaction_id'])->pluck('transaction_id')->toArray(); // @phpstan-ignore-line + $transactions = DB::table('budget_transaction')->distinct()->pluck('transaction_id')->toArray(); $array = []; $chunks = array_chunk($transactions, 500); foreach ($chunks as $chunk) { - $set = DB::table('transactions')->whereIn('transactions.id', $chunk)->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray(); + $set = DB::table('transactions')->whereIn('transactions.id', $chunk)->pluck('transaction_journal_id')->toArray(); $array = array_merge($array, $set); } @@ -160,30 +158,27 @@ class BackToJournals extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal */ private function migrateBudgetsForJournal(TransactionJournal $journal): void { - // grab category from first transaction - /** @var Transaction $transaction */ + /** @var Transaction|null $transaction */ $transaction = $journal->transactions->first(); if (null === $transaction) { - $this->info(sprintf('Transaction journal #%d has no transactions. Will be fixed later.', $journal->id)); return; - } - /** @var Budget $budget */ + /** @var Budget|null $budget */ $budget = $transaction->budgets->first(); - /** @var Budget $journalBudget */ + /** @var Budget|null $journalBudget */ $journalBudget = $journal->budgets->first(); // both have a budget, but they don't match. if (null !== $budget && null !== $journalBudget && $budget->id !== $journalBudget->id) { // sync to journal: - $journal->budgets()->sync([(int) $budget->id]); + $journal->budgets()->sync([(int)$budget->id]); return; } @@ -191,7 +186,7 @@ class BackToJournals extends Command // transaction has a budget, but the journal doesn't. if (null !== $budget && null === $journalBudget) { // sync to journal: - $journal->budgets()->sync([(int) $budget->id]); + $journal->budgets()->sync([(int)$budget->id]); } } @@ -201,7 +196,7 @@ class BackToJournals extends Command private function migrateCategories(): void { Log::debug('Now in migrateCategories()'); - $journals = new Collection; + $journals = new Collection(); $allIds = $this->getIdsForCategories(); Log::debug(sprintf('Total: %d', count($allIds))); @@ -224,15 +219,14 @@ class BackToJournals extends Command */ private function getIdsForCategories(): array { - $transactions = DB::table('category_transaction')->distinct()->get(['transaction_id'])->pluck('transaction_id')->toArray(); // @phpstan-ignore-line + $transactions = DB::table('category_transaction')->distinct()->pluck('transaction_id')->toArray(); $array = []; $chunks = array_chunk($transactions, 500); foreach ($chunks as $chunk) { - $set = DB::table('transactions') // @phpstan-ignore-line - ->whereIn('transactions.id', $chunk) - ->get(['transaction_journal_id'])->pluck('transaction_journal_id')->toArray(); - /** @noinspection SlowArrayOperationsInLoopInspection */ + $set = DB::table('transactions') + ->whereIn('transactions.id', $chunk) + ->pluck('transaction_journal_id')->toArray(); $array = array_merge($array, $set); } @@ -240,34 +234,32 @@ class BackToJournals extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal */ private function migrateCategoriesForJournal(TransactionJournal $journal): void { // grab category from first transaction - /** @var Transaction $transaction */ + /** @var Transaction|null $transaction */ $transaction = $journal->transactions->first(); if (null === $transaction) { - $this->info(sprintf('Transaction journal #%d has no transactions. Will be fixed later.', $journal->id)); return; - } - /** @var Category $category */ + /** @var Category|null $category */ $category = $transaction->categories->first(); - /** @var Category $journalCategory */ + /** @var Category|null $journalCategory */ $journalCategory = $journal->categories->first(); // both have a category, but they don't match. if (null !== $category && null !== $journalCategory && $category->id !== $journalCategory->id) { // sync to journal: - $journal->categories()->sync([(int) $category->id]); + $journal->categories()->sync([(int)$category->id]); } // transaction has a category, but the journal doesn't. if (null !== $category && null === $journalCategory) { - $journal->categories()->sync([(int) $category->id]); + $journal->categories()->sync([(int)$category->id]); } } diff --git a/app/Console/Commands/Upgrade/BudgetLimitCurrency.php b/app/Console/Commands/Upgrade/BudgetLimitCurrency.php index 93b5ac95a1..333a4af854 100644 --- a/app/Console/Commands/Upgrade/BudgetLimitCurrency.php +++ b/app/Console/Commands/Upgrade/BudgetLimitCurrency.php @@ -27,6 +27,8 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\BudgetLimit; use Illuminate\Console\Command; use JsonException; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class BudgetLimitCurrency @@ -99,14 +101,14 @@ class BudgetLimitCurrency extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; diff --git a/app/Console/Commands/Upgrade/CCLiabilities.php b/app/Console/Commands/Upgrade/CCLiabilities.php index d28dc36860..aaac64b4bd 100644 --- a/app/Console/Commands/Upgrade/CCLiabilities.php +++ b/app/Console/Commands/Upgrade/CCLiabilities.php @@ -28,6 +28,8 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use Illuminate\Console\Command; use Illuminate\Support\Collection; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class CCLiabilities @@ -96,14 +98,14 @@ class CCLiabilities extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; diff --git a/app/Console/Commands/Upgrade/CreateGroupMemberships.php b/app/Console/Commands/Upgrade/CreateGroupMemberships.php index 77bfa2c78a..16d58a928d 100644 --- a/app/Console/Commands/Upgrade/CreateGroupMemberships.php +++ b/app/Console/Commands/Upgrade/CreateGroupMemberships.php @@ -31,6 +31,8 @@ use FireflyIII\Models\UserRole; use FireflyIII\User; use Illuminate\Console\Command; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class CreateGroupMemberships @@ -43,7 +45,7 @@ class CreateGroupMemberships extends Command * * @var string */ - protected $description = 'SOME DESCRIPTION'; + protected $description = 'Update group memberships'; /** * The name and signature of the console command. * @@ -77,14 +79,14 @@ class CreateGroupMemberships extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -109,7 +111,7 @@ class CreateGroupMemberships extends Command } /** - * @param User $user + * @param User $user * * @return bool */ @@ -119,7 +121,7 @@ class CreateGroupMemberships extends Command } /** - * @param User $user + * @param User $user * * @throws FireflyException */ @@ -132,6 +134,7 @@ class CreateGroupMemberships extends Command throw new FireflyException('Firefly III could not find a user role. Please make sure all validations have run.'); } + /** @var GroupMembership|null $membership */ $membership = GroupMembership::create( [ 'user_id' => $user->id, diff --git a/app/Console/Commands/Upgrade/MigrateAttachments.php b/app/Console/Commands/Upgrade/MigrateAttachments.php index da66743e5f..1fe8957180 100644 --- a/app/Console/Commands/Upgrade/MigrateAttachments.php +++ b/app/Console/Commands/Upgrade/MigrateAttachments.php @@ -28,6 +28,8 @@ use FireflyIII\Models\Attachment; use FireflyIII\Models\Note; use Illuminate\Console\Command; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class MigrateAttachments @@ -56,7 +58,6 @@ class MigrateAttachments extends Command */ public function handle(): int { - $start = microtime(true); if ($this->isExecuted() && true !== $this->option('force')) { $this->warn('This command has already been executed.'); @@ -70,15 +71,13 @@ class MigrateAttachments extends Command /** @var Attachment $att */ foreach ($attachments as $att) { - // move description: - $attDescription = (string) $att->description; + $attDescription = (string)$att->description; if ('' !== $attDescription) { - // find or create note: $note = $att->notes()->first(); if (null === $note) { - $note = new Note; + $note = new Note(); $note->noteable()->associate($att); } $note->text = $attDescription; @@ -108,14 +107,14 @@ class MigrateAttachments extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; diff --git a/app/Console/Commands/Upgrade/MigrateJournalNotes.php b/app/Console/Commands/Upgrade/MigrateJournalNotes.php index 8469fa7285..96b92b349b 100644 --- a/app/Console/Commands/Upgrade/MigrateJournalNotes.php +++ b/app/Console/Commands/Upgrade/MigrateJournalNotes.php @@ -23,12 +23,14 @@ declare(strict_types=1); namespace FireflyIII\Console\Commands\Upgrade; -use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Note; use FireflyIII\Models\TransactionJournalMeta; use Illuminate\Console\Command; +use Illuminate\Database\QueryException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class MigrateJournalNotes @@ -79,12 +81,7 @@ class MigrateJournalNotes extends Command $note->text = $meta->data; $note->save(); Log::debug(sprintf('Migrated meta note #%d to Note #%d', $meta->id, $note->id)); - try { - $meta->delete(); - - } catch (Exception $e) { // @phpstan-ignore-line - Log::error(sprintf('Could not delete old meta entry #%d: %s', $meta->id, $e->getMessage())); - } + $meta->delete(); $count++; } @@ -106,14 +103,14 @@ class MigrateJournalNotes extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; diff --git a/app/Console/Commands/Upgrade/MigrateRecurrenceMeta.php b/app/Console/Commands/Upgrade/MigrateRecurrenceMeta.php index a1b3c2aa80..267f93ec5f 100644 --- a/app/Console/Commands/Upgrade/MigrateRecurrenceMeta.php +++ b/app/Console/Commands/Upgrade/MigrateRecurrenceMeta.php @@ -25,10 +25,13 @@ declare(strict_types=1); namespace FireflyIII\Console\Commands\Upgrade; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Recurrence; use FireflyIII\Models\RecurrenceMeta; use FireflyIII\Models\RecurrenceTransactionMeta; use Illuminate\Console\Command; use JsonException; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class MigrateRecurrenceMeta @@ -84,14 +87,14 @@ class MigrateRecurrenceMeta extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -115,13 +118,14 @@ class MigrateRecurrenceMeta extends Command } /** - * @param RecurrenceMeta $meta + * @param RecurrenceMeta $meta * * @return int * @throws JsonException */ private function migrateEntry(RecurrenceMeta $meta): int { + /** @var Recurrence|null $recurrence */ $recurrence = $meta->recurrence; if (null === $recurrence) { return 0; diff --git a/app/Console/Commands/Upgrade/MigrateRecurrenceType.php b/app/Console/Commands/Upgrade/MigrateRecurrenceType.php index d86e719aea..485aa4ca9a 100644 --- a/app/Console/Commands/Upgrade/MigrateRecurrenceType.php +++ b/app/Console/Commands/Upgrade/MigrateRecurrenceType.php @@ -29,6 +29,8 @@ use FireflyIII\Models\Recurrence; use FireflyIII\Models\RecurrenceTransaction; use FireflyIII\Models\TransactionType; use Illuminate\Console\Command; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class MigrateRecurrenceType @@ -77,14 +79,14 @@ class MigrateRecurrenceType extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -106,7 +108,7 @@ class MigrateRecurrenceType extends Command private function migrateRecurrence(Recurrence $recurrence): void { - $originalType = (int) $recurrence->transaction_type_id; + $originalType = (int)$recurrence->transaction_type_id; $newType = $this->getInvalidType(); $recurrence->transaction_type_id = $newType->id; $recurrence->save(); diff --git a/app/Console/Commands/Upgrade/MigrateTagLocations.php b/app/Console/Commands/Upgrade/MigrateTagLocations.php index ad36e4a605..97bd4d1368 100644 --- a/app/Console/Commands/Upgrade/MigrateTagLocations.php +++ b/app/Console/Commands/Upgrade/MigrateTagLocations.php @@ -28,13 +28,14 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Location; use FireflyIII\Models\Tag; use Illuminate\Console\Command; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class MigrateTagLocations */ class MigrateTagLocations extends Command { - public const CONFIG_NAME = '500_migrate_tag_locations'; /** * The console command description. @@ -75,14 +76,14 @@ class MigrateTagLocations extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -100,7 +101,7 @@ class MigrateTagLocations extends Command } /** - * @param Tag $tag + * @param Tag $tag * * @return bool */ @@ -110,11 +111,11 @@ class MigrateTagLocations extends Command } /** - * @param Tag $tag + * @param Tag $tag */ private function migrateLocationDetails(Tag $tag): void { - $location = new Location; + $location = new Location(); $location->longitude = $tag->longitude; $location->latitude = $tag->latitude; $location->zoom_level = $tag->zoomLevel; diff --git a/app/Console/Commands/Upgrade/MigrateToGroups.php b/app/Console/Commands/Upgrade/MigrateToGroups.php index ec13761b51..2266b06b96 100644 --- a/app/Console/Commands/Upgrade/MigrateToGroups.php +++ b/app/Console/Commands/Upgrade/MigrateToGroups.php @@ -37,6 +37,8 @@ use FireflyIII\Services\Internal\Destroy\JournalDestroyService; use Illuminate\Console\Command; use Illuminate\Support\Collection; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * This command will take split transactions and migrate them to "transaction groups". @@ -59,7 +61,7 @@ class MigrateToGroups extends Command * * @var string */ - protected $signature = 'firefly-iii:migrate-to-groups {--F|force : Force the migration, even if it fired before.}'; + protected $signature = 'firefly-iii:migrate-to-groups {--F|force : Force the migration, even if it fired before.}'; private JournalCLIRepositoryInterface $cliRepository; private int $count; private TransactionGroupFactory $groupFactory; @@ -129,14 +131,14 @@ class MigrateToGroups extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isMigrated(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -161,7 +163,7 @@ class MigrateToGroups extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @throws Exception */ @@ -169,11 +171,9 @@ class MigrateToGroups extends Command { // double check transaction count. if ($journal->transactions->count() <= 2) { - Log::debug(sprintf('Will not try to convert journal #%d because it has 2 or less transactions.', $journal->id)); return; - } Log::debug(sprintf('Will now try to convert journal #%d', $journal->id)); @@ -221,7 +221,6 @@ class MigrateToGroups extends Command $opposingTr = $this->findOpposingTransaction($journal, $transaction); if (null === $opposingTr) { - $this->error( sprintf( 'Journal #%d has no opposing transaction for transaction #%d. Cannot upgrade this entry.', @@ -230,7 +229,6 @@ class MigrateToGroups extends Command ) ); continue; - } // overrule journal category with transaction category. @@ -307,7 +305,7 @@ class MigrateToGroups extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Collection */ @@ -321,8 +319,8 @@ class MigrateToGroups extends Command } /** - * @param TransactionJournal $journal - * @param Transaction $transaction + * @param TransactionJournal $journal + * @param Transaction $transaction * * @return Transaction|null */ @@ -330,7 +328,7 @@ class MigrateToGroups extends Command { $set = $journal->transactions->filter( static function (Transaction $subject) use ($transaction) { - $amount = (float) $transaction->amount * -1 === (float) $subject->amount; // intentional float + $amount = (float)$transaction->amount * -1 === (float)$subject->amount; // intentional float $identifier = $transaction->identifier === $subject->identifier; Log::debug(sprintf('Amount the same? %s', var_export($amount, true))); Log::debug(sprintf('ID the same? %s', var_export($identifier, true))); @@ -343,8 +341,8 @@ class MigrateToGroups extends Command } /** - * @param Transaction $left - * @param Transaction $right + * @param Transaction $left + * @param Transaction $right * * @return int|null */ @@ -353,21 +351,21 @@ class MigrateToGroups extends Command Log::debug('Now in getTransactionBudget()'); // try to get a budget ID from the left transaction: - /** @var Budget $budget */ + /** @var Budget|null $budget */ $budget = $left->budgets()->first(); if (null !== $budget) { Log::debug(sprintf('Return budget #%d, from transaction #%d', $budget->id, $left->id)); - return (int) $budget->id; + return (int)$budget->id; } // try to get a budget ID from the right transaction: - /** @var Budget $budget */ + /** @var Budget|null $budget */ $budget = $right->budgets()->first(); if (null !== $budget) { Log::debug(sprintf('Return budget #%d, from transaction #%d', $budget->id, $right->id)); - return (int) $budget->id; + return (int)$budget->id; } Log::debug('Neither left or right have a budget, return NULL'); @@ -376,8 +374,8 @@ class MigrateToGroups extends Command } /** - * @param Transaction $left - * @param Transaction $right + * @param Transaction $left + * @param Transaction $right * * @return int|null */ @@ -386,21 +384,21 @@ class MigrateToGroups extends Command Log::debug('Now in getTransactionCategory()'); // try to get a category ID from the left transaction: - /** @var Category $category */ + /** @var Category|null $category */ $category = $left->categories()->first(); if (null !== $category) { Log::debug(sprintf('Return category #%d, from transaction #%d', $category->id, $left->id)); - return (int) $category->id; + return (int)$category->id; } // try to get a category ID from the left transaction: - /** @var Category $category */ + /** @var Category|null $category */ $category = $right->categories()->first(); if (null !== $category) { Log::debug(sprintf('Return category #%d, from transaction #%d', $category->id, $category->id)); - return (int) $category->id; + return (int)$category->id; } Log::debug('Neither left or right have a category, return NULL'); @@ -429,7 +427,7 @@ class MigrateToGroups extends Command } /** - * @param array $array + * @param array $array */ private function giveGroup(array $array): void { diff --git a/app/Console/Commands/Upgrade/MigrateToRules.php b/app/Console/Commands/Upgrade/MigrateToRules.php index 6f726a6ac8..fd2c3b41d0 100644 --- a/app/Console/Commands/Upgrade/MigrateToRules.php +++ b/app/Console/Commands/Upgrade/MigrateToRules.php @@ -33,6 +33,8 @@ use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\Repositories\User\UserRepositoryInterface; use FireflyIII\User; use Illuminate\Console\Command; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class MigrateToRules @@ -120,14 +122,14 @@ class MigrateToRules extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -136,7 +138,7 @@ class MigrateToRules extends Command /** * Migrate bills to new rule structure for a specific user. * - * @param User $user + * @param User $user * * @throws FireflyException */ @@ -148,14 +150,14 @@ class MigrateToRules extends Command /** @var Preference $lang */ $lang = app('preferences')->getForUser($user, 'language', 'en_US'); - $groupTitle = (string) trans('firefly.rulegroup_for_bills_title', [], $lang->data); + $groupTitle = (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data); $ruleGroup = $this->ruleGroupRepository->findByTitle($groupTitle); if (null === $ruleGroup) { $ruleGroup = $this->ruleGroupRepository->store( [ - 'title' => (string) trans('firefly.rulegroup_for_bills_title', [], $lang->data), - 'description' => (string) trans('firefly.rulegroup_for_bills_description', [], $lang->data), + 'title' => (string)trans('firefly.rulegroup_for_bills_title', [], $lang->data), + 'description' => (string)trans('firefly.rulegroup_for_bills_description', [], $lang->data), 'active' => true, ] ); @@ -166,13 +168,12 @@ class MigrateToRules extends Command foreach ($bills as $bill) { $this->migrateBill($ruleGroup, $bill, $lang); } - } /** - * @param RuleGroup $ruleGroup - * @param Bill $bill - * @param Preference $language + * @param RuleGroup $ruleGroup + * @param Bill $bill + * @param Preference $language */ private function migrateBill(RuleGroup $ruleGroup, Bill $bill, Preference $language): void { @@ -187,8 +188,8 @@ class MigrateToRules extends Command 'active' => true, 'strict' => false, 'stop_processing' => false, // field is no longer used. - 'title' => (string) trans('firefly.rule_for_bill_title', ['name' => $bill->name], $language->data), - 'description' => (string) trans('firefly.rule_for_bill_description', ['name' => $bill->name], $language->data), + 'title' => (string)trans('firefly.rule_for_bill_title', ['name' => $bill->name], $language->data), + 'description' => (string)trans('firefly.rule_for_bill_description', ['name' => $bill->name], $language->data), 'trigger' => 'store-journal', 'triggers' => [ [ diff --git a/app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php b/app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php index 4dbe770611..dd3761e175 100644 --- a/app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php +++ b/app/Console/Commands/Upgrade/OtherCurrenciesCorrections.php @@ -35,6 +35,8 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalCLIRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Illuminate\Console\Command; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class OtherCurrenciesCorrections @@ -54,18 +56,12 @@ class OtherCurrenciesCorrections extends Command * @var string */ protected $signature = 'firefly-iii:other-currencies {--F|force : Force the execution of this command.}'; - /** @var array */ - private $accountCurrencies; - /** @var AccountRepositoryInterface */ - private $accountRepos; - /** @var JournalCLIRepositoryInterface */ - private $cliRepos; - /** @var int */ - private $count; - /** @var CurrencyRepositoryInterface */ - private $currencyRepos; - /** @var JournalRepositoryInterface */ - private $journalRepos; + private array $accountCurrencies; + private AccountRepositoryInterface $accountRepos; + private JournalCLIRepositoryInterface $cliRepos; + private int $count; + private CurrencyRepositoryInterface $currencyRepos; + private JournalRepositoryInterface $journalRepos; /** * Execute the console command. @@ -115,14 +111,14 @@ class OtherCurrenciesCorrections extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -147,7 +143,7 @@ class OtherCurrenciesCorrections extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal */ private function updateJournalCurrency(TransactionJournal $journal): void { @@ -159,26 +155,25 @@ class OtherCurrenciesCorrections extends Command $leadTransaction = $this->getLeadTransaction($journal); if (null === $leadTransaction) { - $this->error(sprintf('Could not reliably determine which transaction is in the lead for transaction journal #%d.', $journal->id)); return; - } $account = $leadTransaction->account; $currency = $this->getCurrency($account); if (null === $currency) { - $this->error( sprintf( - 'Account #%d ("%s") has no currency preference, so transaction journal #%d can\'t be corrected', $account->id, $account->name, $journal->id + 'Account #%d ("%s") has no currency preference, so transaction journal #%d can\'t be corrected', + $account->id, + $account->name, + $journal->id ) ); $this->count++; return; - } // fix each transaction: $journal->transactions->each( @@ -189,8 +184,8 @@ class OtherCurrenciesCorrections extends Command } // when mismatch in transaction: - if ((int) $transaction->transaction_currency_id !== (int) $currency->id) { - $transaction->foreign_currency_id = (int) $transaction->transaction_currency_id; + if ((int)$transaction->transaction_currency_id !== (int)$currency->id) { + $transaction->foreign_currency_id = (int)$transaction->transaction_currency_id; $transaction->foreign_amount = $transaction->amount; $transaction->transaction_currency_id = $currency->id; $transaction->save(); @@ -207,7 +202,7 @@ class OtherCurrenciesCorrections extends Command * Gets the transaction that determines the transaction that "leads" and will determine * the currency to be used by all transactions, and the journal itself. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Transaction|null */ @@ -227,13 +222,19 @@ class OtherCurrenciesCorrections extends Command case TransactionType::OPENING_BALANCE: // whichever isn't an initial balance account: $lead = $journal->transactions()->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')->leftJoin( - 'account_types', 'accounts.account_type_id', '=', 'account_types.id' + 'account_types', + 'accounts.account_type_id', + '=', + 'account_types.id' )->where('account_types.type', '!=', AccountType::INITIAL_BALANCE)->first(['transactions.*']); break; case TransactionType::RECONCILIATION: // whichever isn't the reconciliation account: $lead = $journal->transactions()->leftJoin('accounts', 'transactions.account_id', '=', 'accounts.id')->leftJoin( - 'account_types', 'accounts.account_type_id', '=', 'account_types.id' + 'account_types', + 'accounts.account_type_id', + '=', + 'account_types.id' )->where('account_types.type', '!=', AccountType::RECONCILIATION)->first(['transactions.*']); break; } @@ -242,7 +243,7 @@ class OtherCurrenciesCorrections extends Command } /** - * @param Account $account + * @param Account $account * * @return TransactionCurrency|null */ @@ -257,11 +258,9 @@ class OtherCurrenciesCorrections extends Command } $currency = $this->accountRepos->getAccountCurrency($account); if (null === $currency) { - $this->accountCurrencies[$accountId] = 0; return null; - } $this->accountCurrencies[$accountId] = $currency; diff --git a/app/Console/Commands/Upgrade/RenameAccountMeta.php b/app/Console/Commands/Upgrade/RenameAccountMeta.php index 1591dbe898..8f4dd04373 100644 --- a/app/Console/Commands/Upgrade/RenameAccountMeta.php +++ b/app/Console/Commands/Upgrade/RenameAccountMeta.php @@ -26,6 +26,8 @@ namespace FireflyIII\Console\Commands\Upgrade; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\AccountMeta; use Illuminate\Console\Command; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class RenameAccountMeta @@ -99,14 +101,14 @@ class RenameAccountMeta extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; diff --git a/app/Console/Commands/Upgrade/TransactionIdentifier.php b/app/Console/Commands/Upgrade/TransactionIdentifier.php index 752743716c..bb04bb7bb1 100644 --- a/app/Console/Commands/Upgrade/TransactionIdentifier.php +++ b/app/Console/Commands/Upgrade/TransactionIdentifier.php @@ -31,6 +31,8 @@ use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use Illuminate\Console\Command; use Illuminate\Database\QueryException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; use Schema; /** @@ -55,8 +57,6 @@ class TransactionIdentifier extends Command private $cliRepository; /** @var int */ private $count; - /** @var JournalRepositoryInterface */ - private $journalRepository; /** * This method gives all transactions which are part of a split journal (so more than 2) a sort of "order" so they are easier @@ -115,7 +115,6 @@ class TransactionIdentifier extends Command */ private function stupidLaravel(): void { - $this->journalRepository = app(JournalRepositoryInterface::class); $this->cliRepository = app(JournalCLIRepositoryInterface::class); $this->count = 0; } @@ -123,14 +122,14 @@ class TransactionIdentifier extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -140,7 +139,7 @@ class TransactionIdentifier extends Command * Grab all positive transactions from this journal that are not deleted. for each one, grab the negative opposing one * which has 0 as an identifier and give it the same identifier. * - * @param TransactionJournal $transactionJournal + * @param TransactionJournal $transactionJournal */ private function updateJournalIdentifiers(TransactionJournal $transactionJournal): void { @@ -163,19 +162,18 @@ class TransactionIdentifier extends Command } ++$identifier; } - } /** - * @param Transaction $transaction - * @param array $exclude + * @param Transaction $transaction + * @param array $exclude * * @return Transaction|null */ private function findOpposing(Transaction $transaction, array $exclude): ?Transaction { // find opposing: - $amount = bcmul((string) $transaction->amount, '-1'); + $amount = bcmul((string)$transaction->amount, '-1'); try { /** @var Transaction $opposing */ @@ -183,7 +181,6 @@ class TransactionIdentifier extends Command ->where('amount', $amount)->where('identifier', '=', 0) ->whereNotIn('id', $exclude) ->first(); - } catch (QueryException $e) { Log::error($e->getMessage()); $this->error('Firefly III could not find the "identifier" field in the "transactions" table.'); diff --git a/app/Console/Commands/Upgrade/TransferCurrenciesCorrections.php b/app/Console/Commands/Upgrade/TransferCurrenciesCorrections.php index 6113eb260b..295b8e6e87 100644 --- a/app/Console/Commands/Upgrade/TransferCurrenciesCorrections.php +++ b/app/Console/Commands/Upgrade/TransferCurrenciesCorrections.php @@ -33,6 +33,8 @@ use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Journal\JournalCLIRepositoryInterface; use Illuminate\Console\Command; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class TransferCurrenciesCorrections @@ -51,7 +53,7 @@ class TransferCurrenciesCorrections extends Command * * @var string */ - protected $signature = 'firefly-iii:transfer-currencies {--F|force : Force the execution of this command.}'; + protected $signature = 'firefly-iii:transfer-currencies {--F|force : Force the execution of this command.}'; private array $accountCurrencies; private AccountRepositoryInterface $accountRepos; private JournalCLIRepositoryInterface $cliRepos; @@ -69,8 +71,8 @@ class TransferCurrenciesCorrections extends Command * * @return int * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function handle(): int { @@ -137,14 +139,14 @@ class TransferCurrenciesCorrections extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -168,7 +170,7 @@ class TransferCurrenciesCorrections extends Command } /** - * @param TransactionJournal $transfer + * @param TransactionJournal $transfer */ private function updateTransferCurrency(TransactionJournal $transfer): void { @@ -233,7 +235,7 @@ class TransferCurrenciesCorrections extends Command /** * Is this a split transaction journal? * - * @param TransactionJournal $transfer + * @param TransactionJournal $transfer * * @return bool * @codeCoverageIgnore @@ -246,7 +248,7 @@ class TransferCurrenciesCorrections extends Command /** * Extract source transaction, source account + source account currency from the journal. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @codeCoverageIgnore */ @@ -258,7 +260,7 @@ class TransferCurrenciesCorrections extends Command } /** - * @param TransactionJournal $transfer + * @param TransactionJournal $transfer * * @return Transaction|null * @codeCoverageIgnore @@ -269,7 +271,7 @@ class TransferCurrenciesCorrections extends Command } /** - * @param Account $account + * @param Account $account * * @return TransactionCurrency|null */ @@ -284,11 +286,9 @@ class TransferCurrenciesCorrections extends Command } $currency = $this->accountRepos->getAccountCurrency($account); if (null === $currency) { - $this->accountCurrencies[$accountId] = 0; return null; - } $this->accountCurrencies[$accountId] = $currency; @@ -298,7 +298,7 @@ class TransferCurrenciesCorrections extends Command /** * Extract destination transaction, destination account + destination account currency from the journal. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @codeCoverageIgnore */ @@ -310,7 +310,7 @@ class TransferCurrenciesCorrections extends Command } /** - * @param TransactionJournal $transfer + * @param TransactionJournal $transfer * * @return Transaction|null * @codeCoverageIgnore @@ -373,7 +373,7 @@ class TransferCurrenciesCorrections extends Command if (null === $this->sourceTransaction->transaction_currency_id && null !== $this->sourceCurrency) { $this->sourceTransaction ->transaction_currency_id - = (int) $this->sourceCurrency->id; + = (int)$this->sourceCurrency->id; $message = sprintf( 'Transaction #%d has no currency setting, now set to %s.', $this->sourceTransaction->id, @@ -394,7 +394,7 @@ class TransferCurrenciesCorrections extends Command { if (null !== $this->sourceCurrency && null === $this->sourceTransaction->foreign_amount - && (int) $this->sourceTransaction->transaction_currency_id !== (int) $this->sourceCurrency->id + && (int)$this->sourceTransaction->transaction_currency_id !== (int)$this->sourceCurrency->id ) { $message = sprintf( 'Transaction #%d has a currency setting #%d that should be #%d. Amount remains %s, currency is changed.', @@ -406,7 +406,7 @@ class TransferCurrenciesCorrections extends Command Log::debug($message); $this->line($message); $this->count++; - $this->sourceTransaction->transaction_currency_id = (int) $this->sourceCurrency->id; + $this->sourceTransaction->transaction_currency_id = (int)$this->sourceCurrency->id; $this->sourceTransaction->save(); } } @@ -420,7 +420,7 @@ class TransferCurrenciesCorrections extends Command if (null === $this->destinationTransaction->transaction_currency_id && null !== $this->destinationCurrency) { $this->destinationTransaction ->transaction_currency_id - = (int) $this->destinationCurrency->id; + = (int)$this->destinationCurrency->id; $message = sprintf( 'Transaction #%d has no currency setting, now set to %s.', $this->destinationTransaction->id, @@ -441,7 +441,7 @@ class TransferCurrenciesCorrections extends Command { if (null !== $this->destinationCurrency && null === $this->destinationTransaction->foreign_amount - && (int) $this->destinationTransaction->transaction_currency_id !== (int) $this->destinationCurrency->id + && (int)$this->destinationTransaction->transaction_currency_id !== (int)$this->destinationCurrency->id ) { $message = sprintf( 'Transaction #%d has a currency setting #%d that should be #%d. Amount remains %s, currency is changed.', @@ -453,7 +453,7 @@ class TransferCurrenciesCorrections extends Command Log::debug($message); $this->line($message); $this->count++; - $this->destinationTransaction->transaction_currency_id = (int) $this->destinationCurrency->id; + $this->destinationTransaction->transaction_currency_id = (int)$this->destinationCurrency->id; $this->destinationTransaction->save(); } } @@ -465,7 +465,7 @@ class TransferCurrenciesCorrections extends Command */ private function fixInvalidForeignCurrency(): void { - if ((int) $this->destinationCurrency->id === (int) $this->sourceCurrency->id) { + if ((int)$this->destinationCurrency->id === (int)$this->sourceCurrency->id) { // update both transactions to match: $this->sourceTransaction->foreign_amount = null; $this->sourceTransaction->foreign_currency_id = null; @@ -499,7 +499,7 @@ class TransferCurrenciesCorrections extends Command */ private function fixMismatchedForeignCurrency(): void { - if ((int) $this->sourceCurrency->id !== (int) $this->destinationCurrency->id) { + if ((int)$this->sourceCurrency->id !== (int)$this->destinationCurrency->id) { $this->sourceTransaction->transaction_currency_id = $this->sourceCurrency->id; $this->sourceTransaction->foreign_currency_id = $this->destinationCurrency->id; $this->destinationTransaction->transaction_currency_id = $this->sourceCurrency->id; @@ -519,7 +519,7 @@ class TransferCurrenciesCorrections extends Command private function fixSourceNullForeignAmount(): void { if (null === $this->sourceTransaction->foreign_amount && null !== $this->destinationTransaction->foreign_amount) { - $this->sourceTransaction->foreign_amount = bcmul((string) $this->destinationTransaction->foreign_amount, '-1'); + $this->sourceTransaction->foreign_amount = bcmul((string)$this->destinationTransaction->foreign_amount, '-1'); $this->sourceTransaction->save(); $this->count++; Log::debug( @@ -539,7 +539,7 @@ class TransferCurrenciesCorrections extends Command private function fixDestNullForeignAmount(): void { if (null === $this->destinationTransaction->foreign_amount && null !== $this->sourceTransaction->foreign_amount) { - $this->destinationTransaction->foreign_amount = bcmul((string) $this->sourceTransaction->foreign_amount, '-1'); + $this->destinationTransaction->foreign_amount = bcmul((string)$this->sourceTransaction->foreign_amount, '-1'); $this->destinationTransaction->save(); $this->count++; Log::debug( @@ -555,11 +555,11 @@ class TransferCurrenciesCorrections extends Command /** * This method makes sure that the transaction journal uses the currency given in the source transaction. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal */ private function fixTransactionJournalCurrency(TransactionJournal $journal): void { - if ((int) $journal->transaction_currency_id !== (int) $this->sourceCurrency->id) { + if ((int)$journal->transaction_currency_id !== (int)$this->sourceCurrency->id) { $oldCurrencyCode = $journal->transactionCurrency->code ?? '(nothing)'; $journal->transaction_currency_id = $this->sourceCurrency->id; $message = sprintf( diff --git a/app/Console/Commands/Upgrade/UpgradeDatabase.php b/app/Console/Commands/Upgrade/UpgradeDatabase.php index 9364bc59bb..5a493abe57 100644 --- a/app/Console/Commands/Upgrade/UpgradeDatabase.php +++ b/app/Console/Commands/Upgrade/UpgradeDatabase.php @@ -55,7 +55,6 @@ class UpgradeDatabase extends Command */ public function handle(): int { - $this->callInitialCommands(); $commands = [ // there are 14 upgrade commands. @@ -100,6 +99,7 @@ class UpgradeDatabase extends Command 'firefly-iii:fix-transaction-types', 'firefly-iii:fix-frontpage-accounts', 'firefly-iii:fix-ibans', + 'firefly-iii:upgrade-group-information', // two report commands 'firefly-iii:report-empty-objects', @@ -121,9 +121,9 @@ class UpgradeDatabase extends Command echo $result; } // set new DB version. - app('fireflyconfig')->set('db_version', (int) config('firefly.db_version')); + app('fireflyconfig')->set('db_version', (int)config('firefly.db_version')); // index will set FF3 version. - app('fireflyconfig')->set('ff3_version', (string) config('firefly.version')); + app('fireflyconfig')->set('ff3_version', (string)config('firefly.version')); return 0; } diff --git a/app/Console/Commands/Upgrade/UpgradeLiabilities.php b/app/Console/Commands/Upgrade/UpgradeLiabilities.php index 7d971a12f1..43c2cc68c5 100644 --- a/app/Console/Commands/Upgrade/UpgradeLiabilities.php +++ b/app/Console/Commands/Upgrade/UpgradeLiabilities.php @@ -34,6 +34,8 @@ use FireflyIII\Services\Internal\Support\CreditRecalculateService; use FireflyIII\User; use Illuminate\Console\Command; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class UpgradeLiabilities @@ -81,14 +83,14 @@ class UpgradeLiabilities extends Command /** * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function isExecuted(): bool { $configVar = app('fireflyconfig')->get(self::CONFIG_NAME, false); if (null !== $configVar) { - return (bool) $configVar->data; + return (bool)$configVar->data; } return false; @@ -108,7 +110,7 @@ class UpgradeLiabilities extends Command } /** - * @param User $user + * @param User $user */ private function upgradeForUser(User $user): void { @@ -127,7 +129,7 @@ class UpgradeLiabilities extends Command } /** - * @param Account $account + * @param Account $account */ private function upgradeLiability(Account $account): void { @@ -150,8 +152,8 @@ class UpgradeLiabilities extends Command } /** - * @param Account $account - * @param TransactionJournal $openingBalance + * @param Account $account + * @param TransactionJournal $openingBalance */ private function correctOpeningBalance(Account $account, TransactionJournal $openingBalance): void { @@ -161,10 +163,10 @@ class UpgradeLiabilities extends Command return; } // source MUST be the liability. - if ((int) $destination->account_id === (int) $account->id) { + if ((int)$destination->account_id === (int)$account->id) { Log::debug(sprintf('Must switch around, because account #%d is the destination.', $destination->account_id)); // so if not, switch things around: - $sourceAccountId = (int) $source->account_id; + $sourceAccountId = (int)$source->account_id; $source->account_id = $destination->account_id; $destination->account_id = $sourceAccountId; $source->save(); @@ -175,7 +177,7 @@ class UpgradeLiabilities extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Transaction|null */ @@ -185,7 +187,7 @@ class UpgradeLiabilities extends Command } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Transaction|null */ @@ -201,5 +203,4 @@ class UpgradeLiabilities extends Command { app('fireflyconfig')->set(self::CONFIG_NAME, true); } - } diff --git a/app/Console/Commands/UpgradeFireflyInstructions.php b/app/Console/Commands/UpgradeFireflyInstructions.php index 63b19a6315..06c27d32fa 100644 --- a/app/Console/Commands/UpgradeFireflyInstructions.php +++ b/app/Console/Commands/UpgradeFireflyInstructions.php @@ -54,10 +54,10 @@ class UpgradeFireflyInstructions extends Command public function handle(): int { $this->generateInstallationId(); - if ('update' === (string) $this->argument('task')) { + if ('update' === (string)$this->argument('task')) { $this->updateInstructions(); } - if ('install' === (string) $this->argument('task')) { + if ('install' === (string)$this->argument('task')) { $this->installInstructions(); } @@ -112,26 +112,26 @@ class UpgradeFireflyInstructions extends Command /** * Show a nice box. * - * @param string $text + * @param string $text */ private function boxed(string $text): void { $parts = explode("\n", wordwrap($text)); foreach ($parts as $string) { - $this->line('| ' . sprintf('%-77s', $string) . '|'); + $this->line('| '.sprintf('%-77s', $string).'|'); } } /** * Show a nice info box. * - * @param string $text + * @param string $text */ private function boxedInfo(string $text): void { $parts = explode("\n", wordwrap($text)); foreach ($parts as $string) { - $this->info('| ' . sprintf('%-77s', $string) . '|'); + $this->info('| '.sprintf('%-77s', $string).'|'); } } diff --git a/app/Console/Commands/VerifiesAccessToken.php b/app/Console/Commands/VerifiesAccessToken.php index 7a8c06e076..d5b4783acc 100644 --- a/app/Console/Commands/VerifiesAccessToken.php +++ b/app/Console/Commands/VerifiesAccessToken.php @@ -43,7 +43,7 @@ trait VerifiesAccessToken */ public function getUser(): User { - $userId = (int) $this->option('user'); + $userId = (int)$this->option('user'); /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); $user = $repository->find($userId); @@ -57,7 +57,7 @@ trait VerifiesAccessToken /** * Abstract method to make sure trait knows about method "option". * - * @param string|null $key + * @param string|null $key * * @return mixed */ @@ -71,8 +71,8 @@ trait VerifiesAccessToken */ protected function verifyAccessToken(): bool { - $userId = (int) $this->option('user'); - $token = (string) $this->option('token'); + $userId = (int)$this->option('user'); + $token = (string)$this->option('token'); /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); $user = $repository->find($userId); diff --git a/app/Console/Commands/VerifySecurityAlerts.php b/app/Console/Commands/VerifySecurityAlerts.php index 4427f91a4d..6c1f9dbf48 100644 --- a/app/Console/Commands/VerifySecurityAlerts.php +++ b/app/Console/Commands/VerifySecurityAlerts.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Console\Commands; use Illuminate\Console\Command; +use League\Flysystem\FilesystemException; use Log; use Storage; @@ -50,7 +51,7 @@ class VerifySecurityAlerts extends Command * Execute the console command. * * @return int - * @throws \League\Flysystem\FilesystemException + * @throws FilesystemException */ public function handle(): int { @@ -61,7 +62,8 @@ class VerifySecurityAlerts extends Command // check for security advisories. $version = config('firefly.version'); $disk = Storage::disk('resources'); - if (!$disk->has('alerts.json')) { + // Next line is ignored because it's a Laravel Facade. + if (!$disk->has('alerts.json')) { // @phpstan-ignore-line Log::debug('No alerts.json file present.'); return 0; diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 28fa63e7fb..53d1d5ef07 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -40,7 +40,7 @@ class Kernel extends ConsoleKernel */ protected function commands(): void { - $this->load(__DIR__ . '/Commands'); + $this->load(__DIR__.'/Commands'); require base_path('routes/console.php'); } @@ -48,7 +48,7 @@ class Kernel extends ConsoleKernel /** * Define the application's command schedule. * - * @param Schedule $schedule + * @param Schedule $schedule */ protected function schedule(Schedule $schedule): void { diff --git a/app/Enums/AccountTypeEnum.php b/app/Enums/AccountTypeEnum.php new file mode 100644 index 0000000000..e14aaf7d3c --- /dev/null +++ b/app/Enums/AccountTypeEnum.php @@ -0,0 +1,46 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Enums; + +/** + * enum AccountTypeEnum + */ +enum AccountTypeEnum: string +{ + case ASSET = 'Asset account'; + case BENEFICIARY = 'Beneficiary account'; + case CASH = 'Cash account'; + case CREDITCARD = 'Credit card'; + case DEBT = 'Debt'; + case DEFAULT = 'Default account'; + case EXPENSE = 'Expense account'; + case IMPORT = 'Import account'; + case INITIAL_BALANCE = 'Initial balance account'; + case LIABILITY_CREDIT = 'Liability credit account'; + case LOAN = 'Loan'; + case MORTGAGE = 'Mortgage'; + case RECONCILIATION = 'Reconciliation account'; + case REVENUE = 'Revenue account'; +} diff --git a/app/Enums/AutoBudgetType.php b/app/Enums/AutoBudgetType.php new file mode 100644 index 0000000000..a9d8719021 --- /dev/null +++ b/app/Enums/AutoBudgetType.php @@ -0,0 +1,34 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Enums; + +/** + * Enum AutoBudgetType + */ +enum AutoBudgetType: int +{ + case AUTO_BUDGET_RESET = 1; + case AUTO_BUDGET_ROLLOVER = 2; +} diff --git a/app/Enums/RecurrenceRepetitionWeekend.php b/app/Enums/RecurrenceRepetitionWeekend.php new file mode 100644 index 0000000000..f647b7b9e6 --- /dev/null +++ b/app/Enums/RecurrenceRepetitionWeekend.php @@ -0,0 +1,33 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Enums; + +enum RecurrenceRepetitionWeekend: int +{ + case WEEKEND_DO_NOTHING = 1; + case WEEKEND_SKIP_CREATION = 2; + case WEEKEND_TO_FRIDAY = 3; + case WEEKEND_TO_MONDAY = 4; +} diff --git a/app/Enums/TransactionTypeEnum.php b/app/Enums/TransactionTypeEnum.php new file mode 100644 index 0000000000..039a117bb7 --- /dev/null +++ b/app/Enums/TransactionTypeEnum.php @@ -0,0 +1,39 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Enums; + +/** + * Class TransactionTypeEnum + */ +enum TransactionTypeEnum: string +{ + case DEPOSIT = 'Deposit'; + case INVALID = 'Invalid'; + case LIABILITY_CREDIT = 'Liability credit'; + case OPENING_BALANCE = 'Opening balance'; + case RECONCILIATION = 'Reconciliation'; + case TRANSFER = 'Transfer'; + case WITHDRAWAL = 'Withdrawal'; +} diff --git a/app/Enums/UserRoleEnum.php b/app/Enums/UserRoleEnum.php new file mode 100644 index 0000000000..e053bf5ae8 --- /dev/null +++ b/app/Enums/UserRoleEnum.php @@ -0,0 +1,37 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Enums; + +enum UserRoleEnum: string +{ + case CHANGE_PIGGY_BANKS = 'change_piggies'; + case CHANGE_REPETITIONS = 'change_reps'; + case CHANGE_RULES = 'change_rules'; + case CHANGE_TRANSACTIONS = 'change_tx'; + case FULL = 'full'; + case OWNER = 'owner'; + case READ_ONLY = 'ro'; + case VIEW_REPORTS = 'view_reports'; +} diff --git a/app/Enums/WebhookDelivery.php b/app/Enums/WebhookDelivery.php new file mode 100644 index 0000000000..3544cf950a --- /dev/null +++ b/app/Enums/WebhookDelivery.php @@ -0,0 +1,31 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Enums; + +enum WebhookDelivery: int +{ + //case XML = 200; + case JSON = 300; +} diff --git a/app/Enums/WebhookResponse.php b/app/Enums/WebhookResponse.php new file mode 100644 index 0000000000..ca7057f468 --- /dev/null +++ b/app/Enums/WebhookResponse.php @@ -0,0 +1,32 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Enums; + +enum WebhookResponse: int +{ + case TRANSACTIONS = 200; + case ACCOUNTS = 210; + case NONE = 220; +} diff --git a/app/Enums/WebhookTrigger.php b/app/Enums/WebhookTrigger.php new file mode 100644 index 0000000000..4e48851ba1 --- /dev/null +++ b/app/Enums/WebhookTrigger.php @@ -0,0 +1,38 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Enums; + +/** + * Class WebhookTrigger + */ +enum WebhookTrigger: int +{ + case STORE_TRANSACTION = 100; + //case BEFORE_STORE_TRANSACTION = 101; + case UPDATE_TRANSACTION = 110; + //case BEFORE_UPDATE_TRANSACTION = 111; + case DESTROY_TRANSACTION = 120; + //case BEFORE_DESTROY_TRANSACTION = 121; +} diff --git a/app/Events/ActuallyLoggedIn.php b/app/Events/ActuallyLoggedIn.php index 557dad3b38..6f0d07e691 100644 --- a/app/Events/ActuallyLoggedIn.php +++ b/app/Events/ActuallyLoggedIn.php @@ -37,7 +37,7 @@ class ActuallyLoggedIn extends Event public User $user; /** - * @param User $user + * @param User $user */ public function __construct(User $user) { diff --git a/app/Events/Admin/InvitationCreated.php b/app/Events/Admin/InvitationCreated.php new file mode 100644 index 0000000000..37fab9cbd2 --- /dev/null +++ b/app/Events/Admin/InvitationCreated.php @@ -0,0 +1,52 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Events\Admin; + +use FireflyIII\Events\Event; +use FireflyIII\Models\InvitedUser; +use FireflyIII\Models\TransactionGroup; +use Illuminate\Queue\SerializesModels; + +/** + * Class InvitationCreated + */ +class InvitationCreated extends Event +{ + use SerializesModels; + + public InvitedUser $invitee; + + public TransactionGroup $transactionGroup; + + /** + * Create a new event instance. + * + * @param InvitedUser $invitee + */ + public function __construct(InvitedUser $invitee) + { + $this->invitee = $invitee; + } +} diff --git a/app/Events/AdminRequestedTestMessage.php b/app/Events/AdminRequestedTestMessage.php index 97836998c4..ed83fd47d0 100644 --- a/app/Events/AdminRequestedTestMessage.php +++ b/app/Events/AdminRequestedTestMessage.php @@ -42,7 +42,7 @@ class AdminRequestedTestMessage extends Event /** * Create a new event instance. * - * @param User $user + * @param User $user */ public function __construct(User $user) { diff --git a/app/Events/ChangedPiggyBankAmount.php b/app/Events/ChangedPiggyBankAmount.php index e93b4c4903..9434224d39 100644 --- a/app/Events/ChangedPiggyBankAmount.php +++ b/app/Events/ChangedPiggyBankAmount.php @@ -37,10 +37,10 @@ class ChangedPiggyBankAmount extends Event { use SerializesModels; - public PiggyBank $piggyBank; - public ?TransactionJournal $transactionJournal; - public ?TransactionGroup $transactionGroup; public string $amount; + public PiggyBank $piggyBank; + public ?TransactionGroup $transactionGroup; + public ?TransactionJournal $transactionJournal; /** * Create a new event instance. diff --git a/app/Events/DestroyedTransactionGroup.php b/app/Events/DestroyedTransactionGroup.php index 09c9c66107..1b6e8aa4ae 100644 --- a/app/Events/DestroyedTransactionGroup.php +++ b/app/Events/DestroyedTransactionGroup.php @@ -26,6 +26,7 @@ namespace FireflyIII\Events; use FireflyIII\Models\TransactionGroup; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\Log; /** * Class DestroyedTransactionGroup. @@ -41,10 +42,11 @@ class DestroyedTransactionGroup extends Event /** * Create a new event instance. * - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup */ public function __construct(TransactionGroup $transactionGroup) { + Log::debug(sprintf('Now in %s', __METHOD__)); $this->transactionGroup = $transactionGroup; } } diff --git a/app/Events/DestroyedTransactionLink.php b/app/Events/DestroyedTransactionLink.php index 1c9629f526..b795515e72 100644 --- a/app/Events/DestroyedTransactionLink.php +++ b/app/Events/DestroyedTransactionLink.php @@ -33,12 +33,12 @@ class DestroyedTransactionLink extends Event { use SerializesModels; - private TransactionJournalLink $link; + private TransactionJournalLink $link; /// @phpstan-ignore-line PHPStan thinks this property is never read. /** * DestroyedTransactionLink constructor. * - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link */ public function __construct(TransactionJournalLink $link) { diff --git a/app/Events/DetectedNewIPAddress.php b/app/Events/DetectedNewIPAddress.php index 567bba32cc..2e8de8ebbf 100644 --- a/app/Events/DetectedNewIPAddress.php +++ b/app/Events/DetectedNewIPAddress.php @@ -39,8 +39,8 @@ class DetectedNewIPAddress extends Event /** * Create a new event instance. This event is triggered when a new user registers. * - * @param User $user - * @param string $ipAddress + * @param User $user + * @param string $ipAddress */ public function __construct(User $user, string $ipAddress) { diff --git a/app/Events/NewVersionAvailable.php b/app/Events/NewVersionAvailable.php new file mode 100644 index 0000000000..358441d766 --- /dev/null +++ b/app/Events/NewVersionAvailable.php @@ -0,0 +1,44 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Events; + +use Illuminate\Queue\SerializesModels; + +class NewVersionAvailable extends Event +{ + use SerializesModels; + + public string $message; + + /** + * Create a new event instance. This event is triggered when a new version is available. + * + * @param string $message + */ + public function __construct(string $message) + { + $this->message = $message; + } +} diff --git a/app/Events/RegisteredUser.php b/app/Events/RegisteredUser.php index 1d91c81412..01070ef152 100644 --- a/app/Events/RegisteredUser.php +++ b/app/Events/RegisteredUser.php @@ -40,7 +40,7 @@ class RegisteredUser extends Event /** * Create a new event instance. This event is triggered when a new user registers. - * @param User $user + * @param User $user */ public function __construct(User $user) { diff --git a/app/Events/RequestedNewPassword.php b/app/Events/RequestedNewPassword.php index 1706faa15c..17dc3fe6dd 100644 --- a/app/Events/RequestedNewPassword.php +++ b/app/Events/RequestedNewPassword.php @@ -46,9 +46,9 @@ class RequestedNewPassword extends Event /** * Create a new event instance. This event is triggered when a users tries to reset his or her password. * - * @param User $user - * @param string $token - * @param string $ipAddress + * @param User $user + * @param string $token + * @param string $ipAddress */ public function __construct(User $user, string $token, string $ipAddress) { diff --git a/app/Events/RequestedReportOnJournals.php b/app/Events/RequestedReportOnJournals.php index ac59c8f3a7..93cdf990d1 100644 --- a/app/Events/RequestedReportOnJournals.php +++ b/app/Events/RequestedReportOnJournals.php @@ -38,7 +38,9 @@ use Log; */ class RequestedReportOnJournals { - use Dispatchable, InteractsWithSockets, SerializesModels; + use Dispatchable; + use InteractsWithSockets; + use SerializesModels; public Collection $groups; public int $userId; @@ -46,8 +48,8 @@ class RequestedReportOnJournals /** * Create a new event instance. * - * @param int $userId - * @param Collection $groups + * @param int $userId + * @param Collection $groups */ public function __construct(int $userId, Collection $groups) { diff --git a/app/Events/RequestedVersionCheckStatus.php b/app/Events/RequestedVersionCheckStatus.php index 5bc88c617d..2f16f75f01 100644 --- a/app/Events/RequestedVersionCheckStatus.php +++ b/app/Events/RequestedVersionCheckStatus.php @@ -43,7 +43,7 @@ class RequestedVersionCheckStatus extends Event * Create a new event instance. This event is triggered when Firefly III wants to know * what the deal is with the version checker. * - * @param User $user + * @param User $user */ public function __construct(User $user) { diff --git a/app/Events/StoredAccount.php b/app/Events/StoredAccount.php index b8a77937b9..9ccbe3a56d 100644 --- a/app/Events/StoredAccount.php +++ b/app/Events/StoredAccount.php @@ -39,11 +39,10 @@ class StoredAccount extends Event /** * Create a new event instance. * - * @param Account $account + * @param Account $account */ public function __construct(Account $account) { $this->account = $account; } - } diff --git a/app/Events/StoredTransactionGroup.php b/app/Events/StoredTransactionGroup.php index 880c6b8de7..147b56f68e 100644 --- a/app/Events/StoredTransactionGroup.php +++ b/app/Events/StoredTransactionGroup.php @@ -43,11 +43,11 @@ class StoredTransactionGroup extends Event /** * Create a new event instance. * - * @param TransactionGroup $transactionGroup - * @param bool $applyRules - * @param bool $fireWebhooks + * @param TransactionGroup $transactionGroup + * @param bool $applyRules + * @param bool $fireWebhooks */ - public function __construct(TransactionGroup $transactionGroup, bool $applyRules = true, bool $fireWebhooks = true) + public function __construct(TransactionGroup $transactionGroup, bool $applyRules, bool $fireWebhooks) { $this->transactionGroup = $transactionGroup; $this->fireWebhooks = $fireWebhooks; diff --git a/app/Events/TriggeredAuditLog.php b/app/Events/TriggeredAuditLog.php new file mode 100644 index 0000000000..95f7fe5b71 --- /dev/null +++ b/app/Events/TriggeredAuditLog.php @@ -0,0 +1,54 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Events; + +use Illuminate\Database\Eloquent\Model; +use Illuminate\Queue\SerializesModels; + +/** + * Class TriggeredAuditLog + */ +class TriggeredAuditLog extends Event +{ + use SerializesModels; + + public mixed $after; + public Model $auditable; + public mixed $before; + public Model $changer; + public string $field; + + /** + * Create a new event instance. + */ + public function __construct(Model $changer, Model $auditable, string $field, mixed $before, mixed $after) + { + $this->changer = $changer; + $this->auditable = $auditable; + $this->field = $field; + $this->before = $before; + $this->after = $after; + } +} diff --git a/app/Events/UpdatedAccount.php b/app/Events/UpdatedAccount.php index a71e50b357..05f107a5d4 100644 --- a/app/Events/UpdatedAccount.php +++ b/app/Events/UpdatedAccount.php @@ -22,7 +22,6 @@ declare(strict_types=1); - namespace FireflyIII\Events; use FireflyIII\Models\Account; @@ -40,11 +39,10 @@ class UpdatedAccount extends Event /** * Create a new event instance. * - * @param Account $account + * @param Account $account */ public function __construct(Account $account) { $this->account = $account; } - } diff --git a/app/Events/UpdatedTransactionGroup.php b/app/Events/UpdatedTransactionGroup.php index 89ba4e1378..ce4e61252e 100644 --- a/app/Events/UpdatedTransactionGroup.php +++ b/app/Events/UpdatedTransactionGroup.php @@ -43,11 +43,11 @@ class UpdatedTransactionGroup extends Event /** * Create a new event instance. * - * @param TransactionGroup $transactionGroup - * @param bool $applyRules - * @param bool $fireWebhooks + * @param TransactionGroup $transactionGroup + * @param bool $applyRules + * @param bool $fireWebhooks */ - public function __construct(TransactionGroup $transactionGroup, bool $applyRules = true, bool $fireWebhooks = true) + public function __construct(TransactionGroup $transactionGroup, bool $applyRules, bool $fireWebhooks) { $this->transactionGroup = $transactionGroup; $this->fireWebhooks = $fireWebhooks; diff --git a/app/Events/UserChangedEmail.php b/app/Events/UserChangedEmail.php index 31777767a2..0f2e90428b 100644 --- a/app/Events/UserChangedEmail.php +++ b/app/Events/UserChangedEmail.php @@ -43,9 +43,9 @@ class UserChangedEmail extends Event /** * UserChangedEmail constructor. * - * @param User $user - * @param string $newEmail - * @param string $oldEmail + * @param User $user + * @param string $newEmail + * @param string $oldEmail */ public function __construct(User $user, string $newEmail, string $oldEmail) { diff --git a/app/Events/WarnUserAboutBill.php b/app/Events/WarnUserAboutBill.php index de6ae49021..f1cba5aa1e 100644 --- a/app/Events/WarnUserAboutBill.php +++ b/app/Events/WarnUserAboutBill.php @@ -41,9 +41,9 @@ class WarnUserAboutBill extends Event public string $field; /** - * @param Bill $bill - * @param string $field - * @param int $diff + * @param Bill $bill + * @param string $field + * @param int $diff */ public function __construct(Bill $bill, string $field, int $diff) { diff --git a/app/Exceptions/BadHttpHeaderException.php b/app/Exceptions/BadHttpHeaderException.php new file mode 100644 index 0000000000..1ac5a5359c --- /dev/null +++ b/app/Exceptions/BadHttpHeaderException.php @@ -0,0 +1,35 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Exceptions; + +use Exception; + +/** + * + */ +class BadHttpHeaderException extends Exception +{ + public int $statusCode = 406; +} diff --git a/app/Exceptions/GracefulNotFoundHandler.php b/app/Exceptions/GracefulNotFoundHandler.php index 92edf65763..7b444427e2 100644 --- a/app/Exceptions/GracefulNotFoundHandler.php +++ b/app/Exceptions/GracefulNotFoundHandler.php @@ -48,8 +48,8 @@ class GracefulNotFoundHandler extends ExceptionHandler /** * Render an exception into an HTTP response. * - * @param Request $request - * @param Throwable $e + * @param Request $request + * @param Throwable $e * * @return Application|JsonResponse|\Illuminate\Http\Response|Redirector|RedirectResponse|Response * @throws Throwable @@ -67,7 +67,7 @@ class GracefulNotFoundHandler extends ExceptionHandler switch ($name) { default: - Log::warning(sprintf('GracefulNotFoundHandler cannot handle route with name "%s"', $name)); + app('log')->warning(sprintf('GracefulNotFoundHandler cannot handle route with name "%s"', $name)); return parent::render($request, $e); case 'accounts.show': @@ -132,24 +132,29 @@ class GracefulNotFoundHandler extends ExceptionHandler return parent::render($request, $e); } - } /** - * @param Request $request - * @param Throwable $exception + * @param Request $request + * @param Throwable $exception * - * @return Redirector|Response + * @return Response * @throws Throwable */ private function handleAccount(Request $request, Throwable $exception) { Log::debug('404 page is probably a deleted account. Redirect to overview of account types.'); /** @var User $user */ - $user = auth()->user(); - $route = $request->route(); - $accountId = (int) $route->parameter('account'); - /** @var Account $account */ + $user = auth()->user(); + $route = $request->route(); + $param = $route->parameter('account'); + if ($param instanceof Account) { + $accountId = (int)$param->id; + } + if (!($param instanceof Account)) { + $accountId = (int)$param; + } + /** @var Account|null $account */ $account = $user->accounts()->with(['accountType'])->withTrashed()->find($accountId); if (null === $account) { Log::error(sprintf('Could not find account %d, so give big fat error.', $accountId)); @@ -164,10 +169,10 @@ class GracefulNotFoundHandler extends ExceptionHandler } /** - * @param Request $request - * @param Throwable $exception + * @param Request $request + * @param Throwable $exception * - * @return RedirectResponse|\Illuminate\Http\Response|Redirector|Response + * @return Response * @throws Throwable */ private function handleGroup(Request $request, Throwable $exception) @@ -176,16 +181,16 @@ class GracefulNotFoundHandler extends ExceptionHandler /** @var User $user */ $user = auth()->user(); $route = $request->route(); - $groupId = (int) $route->parameter('transactionGroup'); + $groupId = (int)$route->parameter('transactionGroup'); - /** @var TransactionGroup $group */ + /** @var TransactionGroup|null $group */ $group = $user->transactionGroups()->withTrashed()->find($groupId); if (null === $group) { Log::error(sprintf('Could not find group %d, so give big fat error.', $groupId)); return parent::render($request, $exception); } - /** @var TransactionJournal $journal */ + /** @var TransactionJournal|null $journal */ $journal = $group->transactionJournals()->withTrashed()->first(); if (null === $journal) { Log::error(sprintf('Could not find journal for group %d, so give big fat error.', $groupId)); @@ -200,14 +205,13 @@ class GracefulNotFoundHandler extends ExceptionHandler } return redirect(route('transactions.index', [strtolower($type)])); - } /** - * @param Request $request - * @param Throwable $exception + * @param Request $request + * @param Throwable $exception * - * @return RedirectResponse|Redirector|Response + * @return Response * @throws Throwable */ private function handleAttachment(Request $request, Throwable $exception) @@ -216,7 +220,7 @@ class GracefulNotFoundHandler extends ExceptionHandler /** @var User $user */ $user = auth()->user(); $route = $request->route(); - $attachmentId = (int) $route->parameter('attachment'); + $attachmentId = (int)$route->parameter('attachment'); /** @var Attachment $attachment */ $attachment = $user->attachments()->withTrashed()->find($attachmentId); if (null === $attachment) { @@ -232,7 +236,6 @@ class GracefulNotFoundHandler extends ExceptionHandler if (null !== $journal) { return redirect(route('transactions.show', [$journal->transaction_group_id])); } - } if (Bill::class === $attachment->attachable_type) { // is linked to bill. @@ -247,5 +250,4 @@ class GracefulNotFoundHandler extends ExceptionHandler return parent::render($request, $exception); } - } diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 79d6c52b29..98ee8323bd 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -20,8 +20,6 @@ * along with this program. If not, see . */ -/** @noinspection MultipleReturnStatementsInspection */ - declare(strict_types=1); namespace FireflyIII\Exceptions; @@ -30,6 +28,7 @@ use ErrorException; use FireflyIII\Jobs\MailError; use Illuminate\Auth\AuthenticationException; use Illuminate\Contracts\Foundation\Application; +use Illuminate\Database\QueryException; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -40,7 +39,9 @@ use Illuminate\Validation\ValidationException as LaravelValidationException; use Laravel\Passport\Exceptions\OAuthServerException as LaravelOAuthException; use League\OAuth2\Server\Exception\OAuthServerException; use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Throwable; @@ -52,7 +53,7 @@ use Throwable; class Handler extends ExceptionHandler { /** - * @var array + * @var array> */ protected $dontReport = [ @@ -63,14 +64,14 @@ class Handler extends ExceptionHandler LaravelOAuthException::class, TokenMismatchException::class, HttpException::class, - SuspiciousOperationException::class + SuspiciousOperationException::class, ]; /** * Render an exception into an HTTP response. * - * @param Request $request - * @param Throwable $e + * @param Request $request + * @param Throwable $e * * @return mixed * @throws Throwable @@ -95,8 +96,19 @@ class Handler extends ExceptionHandler // somehow Laravel handler does not catch this: return response()->json(['message' => $e->getMessage(), 'exception' => 'OAuthServerException'], 401); } + if ($e instanceof BadRequestHttpException) { + return response()->json(['message' => $e->getMessage(), 'exception' => 'BadRequestHttpException'], 400); + } + + if ($e instanceof BadHttpHeaderException) { + // is always API exception. + return response()->json(['message' => $e->getMessage(), 'exception' => 'BadHttpHeaderException'], $e->statusCode); + } if ($request->expectsJson()) { + $errorCode = 500; + $errorCode = $e instanceof MethodNotAllowedHttpException ? 405 : $errorCode; + $isDebug = config('app.debug', false); if ($isDebug) { return response()->json( @@ -107,12 +119,13 @@ class Handler extends ExceptionHandler 'file' => $e->getFile(), 'trace' => $e->getTrace(), ], - 500 + $errorCode ); } return response()->json( - ['message' => sprintf('Internal Firefly III Exception: %s', $e->getMessage()), 'exception' => get_class($e)], 500 + ['message' => sprintf('Internal Firefly III Exception: %s', $e->getMessage()), 'exception' => get_class($e)], + $errorCode ); } @@ -126,6 +139,14 @@ class Handler extends ExceptionHandler return response()->view('errors.FireflyException', ['exception' => $e, 'debug' => $isDebug], 500); } + // special view for database errors with extra instructions + if ($e instanceof QueryException) { + $isDebug = config('app.debug'); + + return response()->view('errors.DatabaseException', ['exception' => $e, 'debug' => $isDebug], 500); + } + + //var_dump($e);exit; return parent::render($request, $e); } @@ -133,7 +154,7 @@ class Handler extends ExceptionHandler /** * Report or log an exception. * - * @param Throwable $e + * @param Throwable $e * * @return void * @throws Throwable @@ -156,10 +177,7 @@ class Handler extends ExceptionHandler $userData['email'] = auth()->user()->email; } - $headers = []; - if (request()->headers) { - $headers = request()->headers->all(); - } + $headers = request()->headers->all(); $data = [ 'class' => get_class($e), @@ -179,14 +197,14 @@ class Handler extends ExceptionHandler // create job that will mail. $ipAddress = request()->ip() ?? '0.0.0.0'; - $job = new MailError($userData, (string) config('firefly.site_owner'), $ipAddress, $data); + $job = new MailError($userData, (string)config('firefly.site_owner'), $ipAddress, $data); dispatch($job); parent::report($e); } /** - * @param Throwable $e + * @param Throwable $e * * @return bool */ @@ -194,9 +212,10 @@ class Handler extends ExceptionHandler { return !is_null( Arr::first( - $this->dontReport, function ($type) use ($e) { - return $e instanceof $type; - } + $this->dontReport, + function ($type) use ($e) { + return $e instanceof $type; + } ) ); } @@ -204,8 +223,8 @@ class Handler extends ExceptionHandler /** * Convert a validation exception into a response. * - * @param Request $request - * @param LaravelValidationException $exception + * @param Request $request + * @param LaravelValidationException $exception * * @return Application|RedirectResponse|Redirector */ @@ -223,7 +242,7 @@ class Handler extends ExceptionHandler /** * Only return the redirectTo property from the exception if it is a valid URL. Return NULL otherwise. * - * @param LaravelValidationException $exception + * @param LaravelValidationException $exception * * @return string|null */ diff --git a/app/Factory/AccountFactory.php b/app/Factory/AccountFactory.php index 4a67a1d87c..6bc903098c 100644 --- a/app/Factory/AccountFactory.php +++ b/app/Factory/AccountFactory.php @@ -43,7 +43,8 @@ use Log; */ class AccountFactory { - use AccountServiceTrait, LocationServiceTrait; + use AccountServiceTrait; + use LocationServiceTrait; protected AccountRepositoryInterface $accountRepository; protected array $validAssetFields; @@ -69,8 +70,8 @@ class AccountFactory } /** - * @param string $accountName - * @param string $accountType + * @param string $accountName + * @param string $accountType * * @return Account * @throws FireflyException @@ -105,7 +106,7 @@ class AccountFactory } /** - * @param array $data + * @param array $data * * @return Account * @throws FireflyException @@ -131,14 +132,14 @@ class AccountFactory } /** - * @param array $data + * @param array $data * * @return AccountType|null * @throws FireflyException */ protected function getAccountType(array $data): ?AccountType { - $accountTypeId = array_key_exists('account_type_id', $data) ? (int) $data['account_type_id'] : 0; + $accountTypeId = array_key_exists('account_type_id', $data) ? (int)$data['account_type_id'] : 0; $accountTypeName = array_key_exists('account_type_name', $data) ? $data['account_type_name'] : null; $result = null; // find by name or ID @@ -152,12 +153,12 @@ class AccountFactory // try with type: if (null === $result) { $types = config(sprintf('firefly.accountTypeByIdentifier.%s', $accountTypeName)) ?? []; - if (!empty($types)) { + if (0 !== count($types)) { $result = AccountType::whereIn('type', $types)->first(); } } if (null === $result) { - Log::warning(sprintf('Found NO account type based on %d and "%s"', $accountTypeId, $accountTypeName)); + app('log')->warning(sprintf('Found NO account type based on %d and "%s"', $accountTypeId, $accountTypeName)); throw new FireflyException(sprintf('AccountFactory::create() was unable to find account type #%d ("%s").', $accountTypeId, $accountTypeName)); } Log::debug(sprintf('Found account type based on %d and "%s": "%s"', $accountTypeId, $accountTypeName, $result->type)); @@ -166,8 +167,8 @@ class AccountFactory } /** - * @param string $accountName - * @param string $accountType + * @param string $accountName + * @param string $accountType * * @return Account|null */ @@ -179,8 +180,8 @@ class AccountFactory } /** - * @param AccountType $type - * @param array $data + * @param AccountType $type + * @param array $data * * @return Account * @throws FireflyException @@ -193,19 +194,20 @@ class AccountFactory // create it: $virtualBalance = array_key_exists('virtual_balance', $data) ? $data['virtual_balance'] : null; $active = array_key_exists('active', $data) ? $data['active'] : true; - $databaseData = ['user_id' => $this->user->id, - 'account_type_id' => $type->id, - 'name' => $data['name'], - 'order' => 25000, - 'virtual_balance' => $virtualBalance, - 'active' => $active, - 'iban' => $data['iban'], + $databaseData = [ + 'user_id' => $this->user->id, + 'account_type_id' => $type->id, + 'name' => $data['name'], + 'order' => 25000, + 'virtual_balance' => $virtualBalance, + 'active' => $active, + 'iban' => $data['iban'], ]; // fix virtual balance when it's empty - if ('' === (string) $databaseData['virtual_balance']) { + if ('' === (string)$databaseData['virtual_balance']) { $databaseData['virtual_balance'] = null; } - // remove virtual balance when not an asset account or a liability + // remove virtual balance when not an asset account if (!in_array($type->type, $this->canHaveVirtual, true)) { $databaseData['virtual_balance'] = null; } @@ -216,14 +218,14 @@ class AccountFactory $data = $this->cleanMetaDataArray($account, $data); $this->storeMetaData($account, $data); - // create opening balance + // create opening balance (only asset accounts) try { $this->storeOpeningBalance($account, $data); } catch (FireflyException $e) { Log::error($e->getMessage()); } - // create credit liability data (if relevant) + // create credit liability data (only liabilities) try { $this->storeCreditLiability($account, $data); } catch (FireflyException $e) { @@ -247,16 +249,16 @@ class AccountFactory } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @return array */ private function cleanMetaDataArray(Account $account, array $data): array { - $currencyId = array_key_exists('currency_id', $data) ? (int) $data['currency_id'] : 0; - $currencyCode = array_key_exists('currency_code', $data) ? (string) $data['currency_code'] : ''; - $accountRole = array_key_exists('account_role', $data) ? (string) $data['account_role'] : null; + $currencyId = array_key_exists('currency_id', $data) ? (int)$data['currency_id'] : 0; + $currencyCode = array_key_exists('currency_code', $data) ? (string)$data['currency_code'] : ''; + $accountRole = array_key_exists('account_role', $data) ? (string)$data['account_role'] : null; $currency = $this->getCurrency($currencyId, $currencyCode); // only asset account may have a role: @@ -274,12 +276,11 @@ class AccountFactory } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data */ private function storeMetaData(Account $account, array $data): void { - $fields = $this->validFields; if ($account->accountType->type === AccountType::ASSET) { $fields = $this->validAssetFields; @@ -292,7 +293,7 @@ class AccountFactory $type = $account->accountType->type; $list = config('firefly.valid_currency_account_types'); if (!in_array($type, $list, true)) { - $pos = array_search('currency_id', $fields); + $pos = array_search('currency_id', $fields, true); if ($pos !== false) { unset($fields[$pos]); } @@ -312,14 +313,14 @@ class AccountFactory $data[$field] = 1; } - $factory->crud($account, $field, (string) $data[$field]); + $factory->crud($account, $field, (string)$data[$field]); } } } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @throws FireflyException */ @@ -340,8 +341,8 @@ class AccountFactory } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @throws FireflyException */ @@ -352,24 +353,25 @@ class AccountFactory $accountType = $account->accountType->type; $direction = $this->accountRepository->getMetaValue($account, 'liability_direction'); $valid = config('firefly.valid_liabilities'); - if (in_array($accountType, $valid, true) && 'credit' === $direction) { - Log::debug('Is a liability with credit direction.'); + if (in_array($accountType, $valid, true)) { + Log::debug('Is a liability with credit ("i am owed") direction.'); if ($this->validOBData($data)) { Log::debug('Has valid CL data.'); $openingBalance = $data['opening_balance']; $openingBalanceDate = $data['opening_balance_date']; - $this->updateCreditTransaction($account, $openingBalance, $openingBalanceDate); + // store credit transaction. + $this->updateCreditTransaction($account, $direction, $openingBalance, $openingBalanceDate); } if (!$this->validOBData($data)) { - Log::debug('Has NOT valid CL data.'); + Log::debug('Does NOT have valid CL data, deletr any CL transaction.'); $this->deleteCreditTransaction($account); } } } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @throws FireflyException */ @@ -382,7 +384,7 @@ class AccountFactory $order = $maxOrder + 1; } if (array_key_exists('order', $data)) { - $order = (int) ($data['order'] > $maxOrder ? $maxOrder + 1 : $data['order']); + $order = (int)($data['order'] > $maxOrder ? $maxOrder + 1 : $data['order']); $order = 0 === $order ? $maxOrder + 1 : $order; } @@ -392,13 +394,11 @@ class AccountFactory } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; $this->accountRepository->setUser($user); } - - } diff --git a/app/Factory/AccountMetaFactory.php b/app/Factory/AccountMetaFactory.php index 9c48b74b82..1a927edb24 100644 --- a/app/Factory/AccountMetaFactory.php +++ b/app/Factory/AccountMetaFactory.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Factory; -use Exception; use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; use Log; @@ -37,19 +36,18 @@ class AccountMetaFactory /** * Create update or delete meta data. * - * @param Account $account - * @param string $field - * @param string $value + * @param Account $account + * @param string $field + * @param string $value * * @return AccountMeta|null */ public function crud(Account $account, string $field, string $value): ?AccountMeta { - /** @var AccountMeta $entry */ + /** @var AccountMeta|null $entry */ $entry = $account->accountMeta()->where('name', $field)->first(); // must not be an empty string: if ('' !== $value) { - // if $data has field and $entry is null, create new one: if (null === $entry) { Log::debug(sprintf('Created meta-field "%s":"%s" for account #%d ("%s") ', $field, $value, $account->id, $account->name)); @@ -63,11 +61,7 @@ class AccountMetaFactory Log::debug(sprintf('Updated meta-field "%s":"%s" for #%d ("%s") ', $field, $value, $account->id, $account->name)); } if ('' === $value && null !== $entry) { - try { - $entry->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - Log::debug(sprintf('Could not delete entry: %s', $e->getMessage())); - } + $entry->delete(); return null; } @@ -76,7 +70,7 @@ class AccountMetaFactory } /** - * @param array $data + * @param array $data * * @return AccountMeta|null */ @@ -84,5 +78,4 @@ class AccountMetaFactory { return AccountMeta::create($data); } - } diff --git a/app/Factory/AttachmentFactory.php b/app/Factory/AttachmentFactory.php index 96bbd1d55d..54402dde9d 100644 --- a/app/Factory/AttachmentFactory.php +++ b/app/Factory/AttachmentFactory.php @@ -38,7 +38,7 @@ class AttachmentFactory private User $user; /** - * @param array $data + * @param array $data * * @return Attachment|null * @throws FireflyException @@ -51,8 +51,8 @@ class AttachmentFactory // get journal instead of transaction. if (Transaction::class === $model) { - /** @var Transaction $transaction */ - $transaction = $this->user->transactions()->find((int) $data['attachable_id']); + /** @var Transaction|null $transaction */ + $transaction = $this->user->transactions()->find((int)$data['attachable_id']); if (null === $transaction) { throw new FireflyException('Unexpectedly could not find transaction'); } @@ -75,9 +75,9 @@ class AttachmentFactory 'uploaded' => 0, ] ); - $notes = (string) ($data['notes'] ?? ''); + $notes = (string)($data['notes'] ?? ''); if ('' !== $notes) { - $note = new Note; + $note = new Note(); $note->noteable()->associate($attachment); $note->text = $notes; $note->save(); @@ -87,11 +87,10 @@ class AttachmentFactory } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; } - } diff --git a/app/Factory/BillFactory.php b/app/Factory/BillFactory.php index 96ea82bd50..2f1582db76 100644 --- a/app/Factory/BillFactory.php +++ b/app/Factory/BillFactory.php @@ -30,6 +30,7 @@ use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups; use FireflyIII\Services\Internal\Support\BillServiceTrait; use FireflyIII\User; use Illuminate\Database\QueryException; +use JsonException; use Log; /** @@ -37,22 +38,23 @@ use Log; */ class BillFactory { - use BillServiceTrait, CreatesObjectGroups; + use BillServiceTrait; + use CreatesObjectGroups; private User $user; /** - * @param array $data + * @param array $data * * @return Bill|null * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ public function create(array $data): ?Bill { Log::debug(sprintf('Now in %s', __METHOD__), $data); $factory = app(TransactionCurrencyFactory::class); - $currency = $factory->find((int) ($data['currency_id'] ?? null), (string) ($data['currency_code'] ?? null)) ?? + $currency = $factory->find((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null)) ?? app('amount')->getDefaultCurrencyByUser($this->user); try { @@ -83,7 +85,7 @@ class BillFactory } if (array_key_exists('notes', $data)) { - $this->updateNote($bill, (string) $data['notes']); + $this->updateNote($bill, (string)$data['notes']); } $objectGroupTitle = $data['object_group_title'] ?? ''; if ('' !== $objectGroupTitle) { @@ -94,7 +96,7 @@ class BillFactory } } // try also with ID: - $objectGroupId = (int) ($data['object_group_id'] ?? 0); + $objectGroupId = (int)($data['object_group_id'] ?? 0); if (0 !== $objectGroupId) { $objectGroup = $this->findObjectGroupById($objectGroupId); if (null !== $objectGroup) { @@ -107,15 +109,15 @@ class BillFactory } /** - * @param int|null $billId - * @param null|string $billName + * @param int|null $billId + * @param null|string $billName * * @return Bill|null */ public function find(?int $billId, ?string $billName): ?Bill { - $billId = (int) $billId; - $billName = (string) $billName; + $billId = (int)$billId; + $billName = (string)$billName; $bill = null; // first find by ID: if ($billId > 0) { @@ -129,11 +131,10 @@ class BillFactory } return $bill; - } /** - * @param string $name + * @param string $name * * @return Bill|null */ @@ -143,11 +144,10 @@ class BillFactory } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; } - } diff --git a/app/Factory/BudgetFactory.php b/app/Factory/BudgetFactory.php index 69a25e6b92..87b5a4fe9e 100644 --- a/app/Factory/BudgetFactory.php +++ b/app/Factory/BudgetFactory.php @@ -1,4 +1,5 @@ . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; @@ -34,15 +34,15 @@ class BudgetFactory private User $user; /** - * @param int|null $budgetId - * @param null|string $budgetName + * @param int|null $budgetId + * @param null|string $budgetName * * @return Budget|null */ public function find(?int $budgetId, ?string $budgetName): ?Budget { - $budgetId = (int) $budgetId; - $budgetName = (string) $budgetName; + $budgetId = (int)$budgetId; + $budgetName = (string)$budgetName; if (0 === $budgetId && '' === $budgetName) { return null; @@ -68,7 +68,7 @@ class BudgetFactory } /** - * @param string $name + * @param string $name * * @return Budget|null */ @@ -78,11 +78,10 @@ class BudgetFactory } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; } - } diff --git a/app/Factory/CategoryFactory.php b/app/Factory/CategoryFactory.php index 8979d5068b..3e4caf335a 100644 --- a/app/Factory/CategoryFactory.php +++ b/app/Factory/CategoryFactory.php @@ -1,4 +1,5 @@ . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; @@ -37,16 +37,16 @@ class CategoryFactory private User $user; /** - * @param int|null $categoryId - * @param null|string $categoryName + * @param int|null $categoryId + * @param null|string $categoryName * * @return Category|null * @throws FireflyException */ public function findOrCreate(?int $categoryId, ?string $categoryName): ?Category { - $categoryId = (int) $categoryId; - $categoryName = (string) $categoryName; + $categoryId = (int)$categoryId; + $categoryName = (string)$categoryName; Log::debug(sprintf('Going to find category with ID %d and name "%s"', $categoryId, $categoryName)); @@ -84,7 +84,7 @@ class CategoryFactory } /** - * @param string $name + * @param string $name * * @return Category|null */ @@ -94,11 +94,10 @@ class CategoryFactory } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; } - } diff --git a/app/Factory/PiggyBankEventFactory.php b/app/Factory/PiggyBankEventFactory.php index 008f5348ed..1dca07b8ab 100644 --- a/app/Factory/PiggyBankEventFactory.php +++ b/app/Factory/PiggyBankEventFactory.php @@ -1,4 +1,5 @@ . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; -use FireflyIII\Events\ChangedPiggyBankAmount; use FireflyIII\Models\PiggyBank; -use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; @@ -39,8 +37,8 @@ use Log; class PiggyBankEventFactory { /** - * @param TransactionJournal $journal - * @param PiggyBank|null $piggyBank + * @param TransactionJournal $journal + * @param PiggyBank|null $piggyBank */ public function create(TransactionJournal $journal, ?PiggyBank $piggyBank): void { diff --git a/app/Factory/PiggyBankFactory.php b/app/Factory/PiggyBankFactory.php index 6709c3fa64..0bcd6a367e 100644 --- a/app/Factory/PiggyBankFactory.php +++ b/app/Factory/PiggyBankFactory.php @@ -1,4 +1,5 @@ . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; @@ -34,15 +34,15 @@ class PiggyBankFactory private User $user; /** - * @param int|null $piggyBankId - * @param null|string $piggyBankName + * @param int|null $piggyBankId + * @param null|string $piggyBankName * * @return PiggyBank|null */ public function find(?int $piggyBankId, ?string $piggyBankName): ?PiggyBank { - $piggyBankId = (int) $piggyBankId; - $piggyBankName = (string) $piggyBankName; + $piggyBankId = (int)$piggyBankId; + $piggyBankName = (string)$piggyBankName; if ('' === $piggyBankName && 0 === $piggyBankId) { return null; } @@ -65,11 +65,10 @@ class PiggyBankFactory } return null; - } /** - * @param string $name + * @param string $name * * @return PiggyBank|null */ @@ -79,12 +78,10 @@ class PiggyBankFactory } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; - } - } diff --git a/app/Factory/RecurrenceFactory.php b/app/Factory/RecurrenceFactory.php index 3c02765372..4ac23e9375 100644 --- a/app/Factory/RecurrenceFactory.php +++ b/app/Factory/RecurrenceFactory.php @@ -18,7 +18,6 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); @@ -38,8 +37,8 @@ use Log; */ class RecurrenceFactory { - - use TransactionTypeTrait, RecurringTransactionTrait; + use TransactionTypeTrait; + use RecurringTransactionTrait; private MessageBag $errors; private User $user; @@ -51,11 +50,11 @@ class RecurrenceFactory */ public function __construct() { - $this->errors = new MessageBag; + $this->errors = new MessageBag(); } /** - * @param array $data + * @param array $data * * @return Recurrence * @throws FireflyException @@ -84,7 +83,7 @@ class RecurrenceFactory $firstDate = $data['recurrence']['first_date']; } if (array_key_exists('nr_of_repetitions', $data['recurrence'])) { - $repetitions = (int) $data['recurrence']['nr_of_repetitions']; + $repetitions = (int)$data['recurrence']['nr_of_repetitions']; } if (array_key_exists('repeat_until', $data['recurrence'])) { $repeatUntil = $data['recurrence']['repeat_until']; @@ -120,21 +119,18 @@ class RecurrenceFactory $recurrence->save(); if (array_key_exists('notes', $data['recurrence'])) { - $this->updateNote($recurrence, (string) $data['recurrence']['notes']); - + $this->updateNote($recurrence, (string)$data['recurrence']['notes']); } $this->createRepetitions($recurrence, $data['repetitions'] ?? []); try { $this->createTransactions($recurrence, $data['transactions'] ?? []); - } catch (FireflyException $e) { Log::error($e->getMessage()); $recurrence->forceDelete(); $message = sprintf('Could not create recurring transaction: %s', $e->getMessage()); $this->errors->add('store', $message); throw new FireflyException($message, 0, $e); - } @@ -150,12 +146,10 @@ class RecurrenceFactory } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; } - - } diff --git a/app/Factory/TagFactory.php b/app/Factory/TagFactory.php index 2803bdcdd9..b7dab2d4a3 100644 --- a/app/Factory/TagFactory.php +++ b/app/Factory/TagFactory.php @@ -18,7 +18,6 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); @@ -37,7 +36,7 @@ class TagFactory private User $user; /** - * @param string $tag + * @param string $tag * * @return Tag|null */ @@ -46,7 +45,7 @@ class TagFactory $tag = trim($tag); Log::debug(sprintf('Now in TagFactory::findOrCreate("%s")', $tag)); - /** @var Tag $dbTag */ + /** @var Tag|null $dbTag */ $dbTag = $this->user->tags()->where('tag', $tag)->first(); if (null !== $dbTag) { Log::debug(sprintf('Tag exists (#%d), return it.', $dbTag->id)); @@ -74,15 +73,15 @@ class TagFactory } /** - * @param array $data + * @param array $data * * @return Tag|null */ public function create(array $data): ?Tag { - $zoomLevel = 0 === (int) $data['zoom_level'] ? null : (int) $data['zoom_level']; - $latitude = 0.0 === (float) $data['latitude'] ? null : (float) $data['latitude']; // intentional float - $longitude = 0.0 === (float) $data['longitude'] ? null : (float) $data['longitude']; // intentional float + $zoomLevel = 0 === (int)$data['zoom_level'] ? null : (int)$data['zoom_level']; + $latitude = 0.0 === (float)$data['latitude'] ? null : (float)$data['latitude']; // intentional float + $longitude = 0.0 === (float)$data['longitude'] ? null : (float)$data['longitude']; // intentional float $array = [ 'user_id' => $this->user->id, 'tag' => trim($data['tag']), @@ -96,7 +95,7 @@ class TagFactory $tag = Tag::create($array); if (null !== $tag && null !== $latitude && null !== $longitude) { // create location object. - $location = new Location; + $location = new Location(); $location->latitude = $latitude; $location->longitude = $longitude; $location->zoom_level = $zoomLevel; @@ -108,11 +107,10 @@ class TagFactory } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; } - } diff --git a/app/Factory/TransactionCurrencyFactory.php b/app/Factory/TransactionCurrencyFactory.php index d29e963fb4..0068e63352 100644 --- a/app/Factory/TransactionCurrencyFactory.php +++ b/app/Factory/TransactionCurrencyFactory.php @@ -19,8 +19,6 @@ * along with this program. If not, see . */ -/** @noinspection MultipleReturnStatementsInspection */ - declare(strict_types=1); namespace FireflyIII\Factory; @@ -36,7 +34,7 @@ use Log; class TransactionCurrencyFactory { /** - * @param array $data + * @param array $data * * @return TransactionCurrency * @throws FireflyException @@ -49,7 +47,7 @@ class TransactionCurrencyFactory if (1 === $count) { $old = TransactionCurrency::withTrashed()->whereCode($data['code'])->first(); $old->forceDelete(); - Log::warning(sprintf('Force deleted old currency with ID #%d and code "%s".', $old->id, $data['code'])); + app('log')->warning(sprintf('Force deleted old currency with ID #%d and code "%s".', $old->id, $data['code'])); } try { @@ -73,15 +71,15 @@ class TransactionCurrencyFactory } /** - * @param int|null $currencyId - * @param null|string $currencyCode + * @param int|null $currencyId + * @param null|string $currencyCode * * @return TransactionCurrency|null */ public function find(?int $currencyId, ?string $currencyCode): ?TransactionCurrency { - $currencyCode = (string) $currencyCode; - $currencyId = (int) $currencyId; + $currencyCode = (string)$currencyCode; + $currencyId = (int)$currencyId; if ('' === $currencyCode && 0 === $currencyId) { Log::debug('Cannot find anything on empty currency code and empty currency ID!'); @@ -95,7 +93,7 @@ class TransactionCurrencyFactory if (null !== $currency) { return $currency; } - Log::warning(sprintf('Currency ID is %d but found nothing!', $currencyId)); + app('log')->warning(sprintf('Currency ID is %d but found nothing!', $currencyId)); } // then by code: if ('' !== $currencyCode) { @@ -103,9 +101,9 @@ class TransactionCurrencyFactory if (null !== $currency) { return $currency; } - Log::warning(sprintf('Currency code is %d but found nothing!', $currencyCode)); + app('log')->warning(sprintf('Currency code is %d but found nothing!', $currencyCode)); } - Log::warning('Found nothing for currency.'); + app('log')->warning('Found nothing for currency.'); return null; } diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php index bc8f9ad0c6..40e9e9d27b 100644 --- a/app/Factory/TransactionFactory.php +++ b/app/Factory/TransactionFactory.php @@ -43,7 +43,6 @@ class TransactionFactory private ?TransactionCurrency $foreignCurrency; private TransactionJournal $journal; private bool $reconciled; - private User $user; /** * Constructor. @@ -58,8 +57,8 @@ class TransactionFactory /** * Create transaction with negative amount (for source accounts). * - * @param string $amount - * @param string|null $foreignAmount + * @param string $amount + * @param string|null $foreignAmount * * @return Transaction * @throws FireflyException @@ -77,15 +76,14 @@ class TransactionFactory } /** - * @param string $amount - * @param string|null $foreignAmount + * @param string $amount + * @param string|null $foreignAmount * * @return Transaction * @throws FireflyException */ private function create(string $amount, ?string $foreignAmount): Transaction { - $result = null; if ('' === $foreignAmount) { $foreignAmount = null; } @@ -101,8 +99,8 @@ class TransactionFactory 'identifier' => 0, ]; try { + /** @var Transaction|null $result */ $result = Transaction::create($data); - } catch (QueryException $e) { Log::error(sprintf('Could not create transaction: %s', $e->getMessage()), $data); Log::error($e->getMessage()); @@ -113,25 +111,23 @@ class TransactionFactory throw new FireflyException('Transaction is NULL.'); } - if (null !== $result) { - Log::debug( - sprintf( - 'Created transaction #%d (%s %s, account %s), part of journal #%d', - $result->id, - $this->currency->code, - $amount, - $this->account->name, - $this->journal->id - ) - ); + Log::debug( + sprintf( + 'Created transaction #%d (%s %s, account %s), part of journal #%d', + $result->id, + $this->currency->code, + $amount, + $this->account->name, + $this->journal->id + ) + ); - // do foreign currency thing: add foreign currency info to $one and $two if necessary. - if (null !== $this->foreignCurrency && null !== $foreignAmount && $this->foreignCurrency->id !== $this->currency->id && '' !== $foreignAmount) { - $result->foreign_currency_id = $this->foreignCurrency->id; - $result->foreign_amount = $foreignAmount; - } - $result->save(); + // do foreign currency thing: add foreign currency info to $one and $two if necessary. + if (null !== $this->foreignCurrency && null !== $foreignAmount && $this->foreignCurrency->id !== $this->currency->id && '' !== $foreignAmount) { + $result->foreign_currency_id = $this->foreignCurrency->id; + $result->foreign_amount = $foreignAmount; } + $result->save(); return $result; } @@ -139,8 +135,8 @@ class TransactionFactory /** * Create transaction with positive amount (for destination accounts). * - * @param string $amount - * @param string|null $foreignAmount + * @param string $amount + * @param string|null $foreignAmount * * @return Transaction * @throws FireflyException @@ -158,7 +154,7 @@ class TransactionFactory } /** - * @param Account $account + * @param Account $account * * @codeCoverageIgnore */ @@ -168,7 +164,7 @@ class TransactionFactory } /** - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @codeCoverageIgnore */ @@ -178,7 +174,7 @@ class TransactionFactory } /** - * @param TransactionCurrency|null $foreignCurrency |null + * @param TransactionCurrency|null $foreignCurrency |null * * @codeCoverageIgnore */ @@ -188,7 +184,7 @@ class TransactionFactory } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @codeCoverageIgnore */ @@ -198,7 +194,7 @@ class TransactionFactory } /** - * @param bool $reconciled + * @param bool $reconciled * * @codeCoverageIgnore */ @@ -208,12 +204,12 @@ class TransactionFactory } /** - * @param User $user + * @param User $user * * @codeCoverageIgnore */ public function setUser(User $user): void { - $this->user = $user; + // empty function. } } diff --git a/app/Factory/TransactionGroupFactory.php b/app/Factory/TransactionGroupFactory.php index dae181b197..d71880386a 100644 --- a/app/Factory/TransactionGroupFactory.php +++ b/app/Factory/TransactionGroupFactory.php @@ -27,6 +27,7 @@ use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionGroup; use FireflyIII\User; +use JsonException; use Log; /** @@ -37,7 +38,7 @@ use Log; class TransactionGroupFactory { private TransactionJournalFactory $journalFactory; - private User $user; + private User $user; /** * TransactionGroupFactory constructor. @@ -50,12 +51,12 @@ class TransactionGroupFactory /** * Store a new transaction journal. * - * @param array $data + * @param array $data * * @return TransactionGroup * @throws DuplicateTransactionException * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ public function create(array $data): TransactionGroup { @@ -65,7 +66,7 @@ class TransactionGroupFactory try { $collection = $this->journalFactory->create($data); } catch (DuplicateTransactionException $e) { - Log::warning('GroupFactory::create() caught journalFactory::create() with a duplicate!'); + app('log')->warning('GroupFactory::create() caught journalFactory::create() with a duplicate!'); throw new DuplicateTransactionException($e->getMessage(), 0, $e); } $title = $data['group_title'] ?? null; @@ -78,7 +79,7 @@ class TransactionGroupFactory throw new FireflyException('Created zero transaction journals.'); } - $group = new TransactionGroup; + $group = new TransactionGroup(); $group->user()->associate($this->user); $group->title = $title; $group->save(); @@ -91,7 +92,7 @@ class TransactionGroupFactory /** * Set the user. * - * @param User $user + * @param User $user */ public function setUser(User $user): void { diff --git a/app/Factory/TransactionJournalFactory.php b/app/Factory/TransactionJournalFactory.php index 8cf056b3ee..662a3d3b8b 100644 --- a/app/Factory/TransactionJournalFactory.php +++ b/app/Factory/TransactionJournalFactory.php @@ -24,10 +24,12 @@ declare(strict_types=1); namespace FireflyIII\Factory; +use Carbon\Carbon; use Exception; use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; +use FireflyIII\Models\Preference; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Models\TransactionJournal; @@ -106,12 +108,12 @@ class TransactionJournalFactory $dataObject = new NullArrayObject($data); Log::debug('Start of TransactionJournalFactory::create()'); - $collection = new Collection; + $collection = new Collection(); $transactions = $dataObject['transactions'] ?? []; - if (empty($transactions)) { + if (0 === count($transactions)) { Log::error('There are no transactions in the array, the TransactionJournalFactory cannot continue.'); - return new Collection; + return new Collection(); } try { /** @var array $row */ @@ -126,13 +128,13 @@ class TransactionJournalFactory } } } catch (DuplicateTransactionException $e) { - Log::warning('TransactionJournalFactory::create() caught a duplicate journal in createJournal()'); + app('log')->warning('TransactionJournalFactory::create() caught a duplicate journal in createJournal()'); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); $this->forceDeleteOnError($collection); throw new DuplicateTransactionException($e->getMessage(), 0, $e); } catch (FireflyException $e) { - Log::warning('TransactionJournalFactory::create() caught an exception.'); + app('log')->warning('TransactionJournalFactory::create() caught an exception.'); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); $this->forceDeleteOnError($collection); @@ -207,11 +209,19 @@ class TransactionJournalFactory Log::debug('Now calling getAccount for the destination.'); $destinationAccount = $this->getAccount($type->type, 'destination', $destInfo); Log::debug('Done with getAccount(2x)'); + + // this is the moment for a reconciliation sanity check (again). + if (TransactionType::RECONCILIATION === $type->type) { + [$sourceAccount, $destinationAccount] = $this->reconciliationSanityCheck($sourceAccount, $destinationAccount); + } + $currency = $this->getCurrencyByAccount($type->type, $currency, $sourceAccount, $destinationAccount); $foreignCurrency = $this->compareCurrencies($currency, $foreignCurrency); $foreignCurrency = $this->getForeignByAccount($type->type, $foreignCurrency, $destinationAccount); $description = $this->getDescription($description); + Log::debug(sprintf('Date: %s (%s)', $carbon->toW3cString(), $carbon->getTimezone()->getName())); + /** Create a basic journal. */ $journal = TransactionJournal::create( [ @@ -261,7 +271,7 @@ class TransactionJournalFactory Log::error('Exception creating positive transaction.'); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); - Log::warning('Delete negative transaction.'); + app('log')->warning('Delete negative transaction.'); $this->forceTrDelete($negative); $this->forceDeleteOnError(new Collection([$journal])); throw new FireflyException($e->getMessage(), 0, $e); @@ -305,10 +315,6 @@ class TransactionJournalFactory unset($dataRow['import_hash_v2'], $dataRow['original_source']); $json = json_encode($dataRow, JSON_THROW_ON_ERROR); - if (false === $json) { - $json = json_encode((string)microtime(), JSON_THROW_ON_ERROR); - Log::error(sprintf('Could not hash the original row! %s', json_last_error_msg()), $dataRow); - } $hash = hash('sha256', $json); Log::debug(sprintf('The hash is: %s', $hash), $dataRow); @@ -329,17 +335,14 @@ class TransactionJournalFactory if (false === $this->errorOnHash) { return; } - $result = null; - if ($this->errorOnHash) { - Log::debug('Will verify duplicate!'); - /** @var TransactionJournalMeta $result */ - $result = TransactionJournalMeta::withTrashed() - ->where('data', json_encode($hash, JSON_THROW_ON_ERROR)) - ->with(['transactionJournal', 'transactionJournal.transactionGroup']) - ->first(); - } + Log::debug('Will verify duplicate!'); + /** @var TransactionJournalMeta|null $result */ + $result = TransactionJournalMeta::withTrashed() + ->where('data', json_encode($hash, JSON_THROW_ON_ERROR)) + ->with(['transactionJournal', 'transactionJournal.transactionGroup']) + ->first(); if (null !== $result) { - Log::warning(sprintf('Found a duplicate in errorIfDuplicate because hash %s is not unique!', $hash)); + app('log')->warning(sprintf('Found a duplicate in errorIfDuplicate because hash %s is not unique!', $hash)); $journal = $result->transactionJournal()->withTrashed()->first(); $group = $journal?->transactionGroup()->withTrashed()->first(); $groupId = $group?->id; @@ -392,6 +395,52 @@ class TransactionJournalFactory } } + /** + * Set the user. + * + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + $this->currencyRepository->setUser($this->user); + $this->tagFactory->setUser($user); + $this->billRepository->setUser($this->user); + $this->budgetRepository->setUser($this->user); + $this->categoryRepository->setUser($this->user); + $this->piggyRepository->setUser($this->user); + $this->accountRepository->setUser($this->user); + } + + /** + * @param Account|null $sourceAccount + * @param Account|null $destinationAccount + * @return array + */ + private function reconciliationSanityCheck(?Account $sourceAccount, ?Account $destinationAccount): array + { + Log::debug(sprintf('Now in %s', __METHOD__)); + if (null !== $sourceAccount && null !== $destinationAccount) { + Log::debug('Both accounts exist, simply return them.'); + return [$sourceAccount, $destinationAccount]; + } + if (null !== $sourceAccount && null === $destinationAccount) { + Log::debug('Destination account is NULL, source account is not.'); + $account = $this->accountRepository->getReconciliation($sourceAccount); + Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type)); + return [$sourceAccount, $account]; + } + + if (null === $sourceAccount && null !== $destinationAccount) { + Log::debug('Source account is NULL, destination account is not.'); + $account = $this->accountRepository->getReconciliation($destinationAccount); + Log::debug(sprintf('Will return account #%d ("%s") of type "%s"', $account->id, $account->name, $account->accountType->type)); + return [$account, $destinationAccount]; + } + Log::debug('Unused fallback'); + return [$sourceAccount, $destinationAccount]; + } + /** * @param string $type * @param TransactionCurrency|null $currency @@ -421,6 +470,7 @@ class TransactionJournalFactory private function getCurrency(?TransactionCurrency $currency, Account $account): TransactionCurrency { Log::debug('Now in getCurrency()'); + /** @var Preference|null $preference */ $preference = $this->accountRepository->getAccountCurrency($account); if (null === $preference && null === $currency) { // return user's default: @@ -502,13 +552,7 @@ class TransactionJournalFactory */ private function forceTrDelete(Transaction $transaction): void { - try { - $transaction->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - Log::error($e->getMessage()); - Log::error($e->getTraceAsString()); - Log::error('Could not delete negative transaction.'); - } + $transaction->delete(); } /** @@ -560,8 +604,13 @@ class TransactionJournalFactory 'name' => $field, 'data' => (string)($data[$field] ?? ''), ]; + if ($data[$field] instanceof Carbon) { + $data[$field]->setTimezone(config('app.timezone')); + Log::debug(sprintf('%s Date: %s (%s)', $field, $data[$field], $data[$field]->timezone->getName())); + $set['data'] = $data[$field]->format('Y-m-d H:i:s'); + } - //Log::debug(sprintf('Going to store meta-field "%s", with value "%s".', $set['name'], $set['data'])); + Log::debug(sprintf('Going to store meta-field "%s", with value "%s".', $set['name'], $set['data'])); /** @var TransactionJournalMetaFactory $factory */ $factory = app(TransactionJournalMetaFactory::class); @@ -578,21 +627,4 @@ class TransactionJournalFactory Log::info('Will trigger duplication alert for this journal.'); } } - - /** - * Set the user. - * - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - $this->currencyRepository->setUser($this->user); - $this->tagFactory->setUser($user); - $this->billRepository->setUser($this->user); - $this->budgetRepository->setUser($this->user); - $this->categoryRepository->setUser($this->user); - $this->piggyRepository->setUser($this->user); - $this->accountRepository->setUser($this->user); - } } diff --git a/app/Factory/TransactionJournalMetaFactory.php b/app/Factory/TransactionJournalMetaFactory.php index 99dc2c746c..c22da98f58 100644 --- a/app/Factory/TransactionJournalMetaFactory.php +++ b/app/Factory/TransactionJournalMetaFactory.php @@ -18,15 +18,14 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Factory; use Carbon\Carbon; -use Exception; use FireflyIII\Models\TransactionJournalMeta; +use Illuminate\Database\QueryException; use Log; /** @@ -35,7 +34,7 @@ use Log; class TransactionJournalMetaFactory { /** - * @param array $data + * @param array $data * * @return TransactionJournalMeta|null */ @@ -43,33 +42,25 @@ class TransactionJournalMetaFactory { //Log::debug('In updateOrCreate()'); $value = $data['data']; - /** @var TransactionJournalMeta $entry */ + /** @var TransactionJournalMeta|null $entry */ $entry = $data['journal']->transactionJournalMeta()->where('name', $data['name'])->first(); if (null === $value && null !== $entry) { //Log::debug('Value is empty, delete meta value.'); - try { - $entry->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - Log::error(sprintf('Could not delete transaction journal meta: %s', $e->getMessage())); - } + $entry->delete(); return null; } if ($data['data'] instanceof Carbon) { - //Log::debug('Is a carbon object.'); + Log::debug('Is a carbon object.'); $value = $data['data']->toW3cString(); } - if ('' === (string) $value) { + if ('' === (string)$value) { // Log::debug('Is an empty string.'); // don't store blank strings. if (null !== $entry) { Log::debug('Will not store empty strings, delete meta value'); - try { - $entry->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - Log::error(sprintf('Could not delete transaction journal meta: %s', $e->getMessage())); - } + $entry->delete(); } return null; @@ -88,5 +79,4 @@ class TransactionJournalMetaFactory return $entry; } - } diff --git a/app/Factory/TransactionTypeFactory.php b/app/Factory/TransactionTypeFactory.php index 4a95c67a0b..87b60c2b11 100644 --- a/app/Factory/TransactionTypeFactory.php +++ b/app/Factory/TransactionTypeFactory.php @@ -32,7 +32,7 @@ use FireflyIII\Models\TransactionType; class TransactionTypeFactory { /** - * @param string $type + * @param string $type * * @return TransactionType|null */ @@ -40,5 +40,4 @@ class TransactionTypeFactory { return TransactionType::whereType(ucfirst($type))->first(); } - } diff --git a/app/Generator/Chart/Basic/ChartJsGenerator.php b/app/Generator/Chart/Basic/ChartJsGenerator.php index 18d45c86a6..217cfa7933 100644 --- a/app/Generator/Chart/Basic/ChartJsGenerator.php +++ b/app/Generator/Chart/Basic/ChartJsGenerator.php @@ -1,4 +1,5 @@ [value => x, 'currency_symbol' => 'x'] * - * @param array $data + * @param array $data * * @return array */ @@ -50,7 +51,7 @@ class ChartJsGenerator implements GeneratorInterface $amounts = array_column($data, 'amount'); $next = next($amounts); $sortFlag = SORT_ASC; - if (!is_bool($next) && 1 === bccomp((string) $next, '0')) { + if (!is_bool($next) && 1 === bccomp((string)$next, '0')) { $sortFlag = SORT_DESC; } array_multisort($amounts, $sortFlag, $data); @@ -59,7 +60,7 @@ class ChartJsGenerator implements GeneratorInterface $index = 0; foreach ($data as $key => $valueArray) { // make larger than 0 - $chartData['datasets'][0]['data'][] = app('steam')->positive((string) $valueArray['amount']); + $chartData['datasets'][0]['data'][] = app('steam')->positive((string)$valueArray['amount']); $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); $chartData['datasets'][0]['currency_symbol'][] = $valueArray['currency_symbol']; $chartData['labels'][] = $key; @@ -99,7 +100,7 @@ class ChartJsGenerator implements GeneratorInterface * * // it's five. * - * @param array $data + * @param array $data * * @return array */ @@ -148,7 +149,7 @@ class ChartJsGenerator implements GeneratorInterface * * key => value * - * @param array $data + * @param array $data * * @return array */ @@ -165,7 +166,7 @@ class ChartJsGenerator implements GeneratorInterface // different sort when values are positive and when they're negative. asort($data); $next = next($data); - if (!is_bool($next) && 1 === bccomp((string) $next, '0')) { + if (!is_bool($next) && 1 === bccomp((string)$next, '0')) { // next is positive, sort other way around. arsort($data); } @@ -174,7 +175,7 @@ class ChartJsGenerator implements GeneratorInterface $index = 0; foreach ($data as $key => $value) { // make larger than 0 - $chartData['datasets'][0]['data'][] = app('steam')->positive((string) $value); + $chartData['datasets'][0]['data'][] = app('steam')->positive((string)$value); $chartData['datasets'][0]['backgroundColor'][] = ChartColour::getColour($index); $chartData['labels'][] = $key; @@ -189,8 +190,8 @@ class ChartJsGenerator implements GeneratorInterface * * 'label-of-entry' => value * - * @param string $setLabel - * @param array $data + * @param string $setLabel + * @param array $data * * @return array */ diff --git a/app/Generator/Chart/Basic/GeneratorInterface.php b/app/Generator/Chart/Basic/GeneratorInterface.php index b92994f858..e2209ccee1 100644 --- a/app/Generator/Chart/Basic/GeneratorInterface.php +++ b/app/Generator/Chart/Basic/GeneratorInterface.php @@ -1,4 +1,5 @@ value * - * @param array $data + * @param array $data * * @return array */ @@ -84,8 +85,8 @@ interface GeneratorInterface * * 'label-of-entry' => value * - * @param string $setLabel - * @param array $data + * @param string $setLabel + * @param array $data * * @return array */ diff --git a/app/Generator/Report/Account/MonthReportGenerator.php b/app/Generator/Report/Account/MonthReportGenerator.php index 937548f453..d14f6d6bb6 100644 --- a/app/Generator/Report/Account/MonthReportGenerator.php +++ b/app/Generator/Report/Account/MonthReportGenerator.php @@ -1,4 +1,5 @@ with('start', $this->start)->with('end', $this->end) ->with('doubles', $this->expense) ->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.double.report: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; @@ -77,7 +81,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return ReportGeneratorInterface */ @@ -91,7 +95,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set budgets. * - * @param Collection $budgets + * @param Collection $budgets * * @return ReportGeneratorInterface */ @@ -103,7 +107,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set categories. * - * @param Collection $categories + * @param Collection $categories * * @return ReportGeneratorInterface */ @@ -115,7 +119,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set end date. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -129,7 +133,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set expense collection. * - * @param Collection $expense + * @param Collection $expense * * @return ReportGeneratorInterface */ @@ -143,7 +147,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set start date. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -157,7 +161,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set collection of tags. * - * @param Collection $tags + * @param Collection $tags * * @return ReportGeneratorInterface */ diff --git a/app/Generator/Report/Account/MultiYearReportGenerator.php b/app/Generator/Report/Account/MultiYearReportGenerator.php index a4148663e1..0d2e3db05e 100644 --- a/app/Generator/Report/Account/MultiYearReportGenerator.php +++ b/app/Generator/Report/Account/MultiYearReportGenerator.php @@ -1,4 +1,5 @@ accounts->pluck('id')->toArray()); - $hideable = ['buttons', 'icon', 'description', 'balance_before', 'amount', 'balance_after', 'date', + $hideable = [ + 'buttons', + 'icon', + 'description', + 'balance_before', + 'amount', + 'balance_after', + 'date', - 'from', 'to', 'budget', 'category', 'bill', + 'from', + 'to', + 'budget', + 'category', + 'bill', - // more new optional fields - 'create_date', 'update_date', + // more new optional fields + 'create_date', + 'update_date', - // date fields. - 'interest_date', 'book_date', 'process_date', - 'due_date', 'payment_date', 'invoice_date', + // date fields. + 'interest_date', + 'book_date', + 'process_date', + 'due_date', + 'payment_date', + 'invoice_date', ]; try { $result = view('reports.audit.report', compact('reportType', 'accountIds', 'auditData', 'hideable', 'defaultShow')) ->with('start', $this->start)->with('end', $this->end)->with('accounts', $this->accounts) ->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.audit.report: %s', $e->getMessage())); Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; @@ -95,15 +111,14 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Get the audit report. * - * @param Account $account - * @param Carbon $date + * @param Account $account + * @param Carbon $date * * @return array * @throws FireflyException * @throws JsonException */ - #[ArrayShape(['journals' => "array", 'currency' => "mixed", 'exists' => "bool", 'end' => "string", 'endBalance' => "mixed", 'dayBefore' => "string", - 'dayBeforeBalance' => "mixed"])] public function getAuditReport(Account $account, Carbon $date): array + public function getAuditReport(Account $account, Carbon $date): array { /** @var AccountRepositoryInterface $accountRepository */ $accountRepository = app(AccountRepositoryInterface::class); @@ -151,17 +166,16 @@ class MonthReportGenerator implements ReportGeneratorInterface $journals[$index]['due_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'due_date'); $journals[$index]['payment_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'payment_date'); $journals[$index]['invoice_date'] = $journalRepository->getMetaDateById($journal['transaction_journal_id'], 'invoice_date'); - } $locale = app('steam')->getLocale(); return [ 'journals' => $journals, 'currency' => $currency, - 'exists' => !empty($journals), - 'end' => $this->end->isoFormat((string) trans('config.month_and_day_moment_js', [], $locale)), + 'exists' => 0 !== count($journals), + 'end' => $this->end->isoFormat((string)trans('config.month_and_day_moment_js', [], $locale)), 'endBalance' => app('steam')->balance($account, $this->end), - 'dayBefore' => $date->isoFormat((string) trans('config.month_and_day_moment_js', [], $locale)), + 'dayBefore' => $date->isoFormat((string)trans('config.month_and_day_moment_js', [], $locale)), 'dayBeforeBalance' => $dayBeforeBalance, ]; } @@ -169,7 +183,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Account collection setter. * - * @param Collection $accounts + * @param Collection $accounts * * @return ReportGeneratorInterface * @codeCoverageIgnore @@ -184,7 +198,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Budget collection setter. * - * @param Collection $budgets + * @param Collection $budgets * * @return ReportGeneratorInterface * @codeCoverageIgnore @@ -197,7 +211,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Category collection setter. * - * @param Collection $categories + * @param Collection $categories * * @return ReportGeneratorInterface * @codeCoverageIgnore @@ -210,7 +224,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * End date setter. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface * @codeCoverageIgnore @@ -225,7 +239,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Expenses collection setter. * - * @param Collection $expense + * @param Collection $expense * * @return ReportGeneratorInterface * @codeCoverageIgnore @@ -239,7 +253,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Start date collection setter. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface * @codeCoverageIgnore @@ -254,7 +268,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Tags collection setter. * - * @param Collection $tags + * @param Collection $tags * * @return ReportGeneratorInterface * @codeCoverageIgnore diff --git a/app/Generator/Report/Audit/MultiYearReportGenerator.php b/app/Generator/Report/Audit/MultiYearReportGenerator.php index 591251938c..ff654bc090 100644 --- a/app/Generator/Report/Audit/MultiYearReportGenerator.php +++ b/app/Generator/Report/Audit/MultiYearReportGenerator.php @@ -1,4 +1,5 @@ . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Generator\Report\Budget; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; -use FireflyIII\Generator\Report\Support; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Models\TransactionType; use Illuminate\Support\Collection; @@ -34,7 +34,7 @@ use Throwable; /** * Class MonthReportGenerator. - * See reference nr. 19 + * TODO include info about tags. * * @codeCoverageIgnore */ @@ -72,46 +72,19 @@ class MonthReportGenerator implements ReportGeneratorInterface ->with('budgets', $this->budgets) ->with('accounts', $this->accounts) ->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); $result = sprintf('Could not render report view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; } - /** - * Set the involved accounts. - * - * @param Collection $accounts - * - * @return ReportGeneratorInterface - */ - public function setAccounts(Collection $accounts): ReportGeneratorInterface - { - $this->accounts = $accounts; - - return $this; - } - - /** - * Set the involved budgets. - * - * @param Collection $budgets - * - * @return ReportGeneratorInterface - */ - public function setBudgets(Collection $budgets): ReportGeneratorInterface - { - $this->budgets = $budgets; - - return $this; - } - /** * Unused category setter. * - * @param Collection $categories + * @param Collection $categories * * @return ReportGeneratorInterface */ @@ -123,7 +96,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the end date of the report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -137,7 +110,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Unused expense setter. * - * @param Collection $expense + * @param Collection $expense * * @return ReportGeneratorInterface */ @@ -149,7 +122,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the start date of the report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -163,7 +136,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Unused tags setter. * - * @param Collection $tags + * @param Collection $tags * * @return ReportGeneratorInterface */ @@ -179,7 +152,7 @@ class MonthReportGenerator implements ReportGeneratorInterface */ protected function getExpenses(): array { - if (!empty($this->expenses)) { + if (0 !== count($this->expenses)) { Log::debug('Return previous set of expenses.'); return $this->expenses; @@ -198,4 +171,32 @@ class MonthReportGenerator implements ReportGeneratorInterface return $journals; } + + /** + * Set the involved budgets. + * + * @param Collection $budgets + * + * @return ReportGeneratorInterface + */ + public function setBudgets(Collection $budgets): ReportGeneratorInterface + { + $this->budgets = $budgets; + + return $this; + } + + /** + * Set the involved accounts. + * + * @param Collection $accounts + * + * @return ReportGeneratorInterface + */ + public function setAccounts(Collection $accounts): ReportGeneratorInterface + { + $this->accounts = $accounts; + + return $this; + } } diff --git a/app/Generator/Report/Budget/MultiYearReportGenerator.php b/app/Generator/Report/Budget/MultiYearReportGenerator.php index e9368a9834..54b36d8566 100644 --- a/app/Generator/Report/Budget/MultiYearReportGenerator.php +++ b/app/Generator/Report/Budget/MultiYearReportGenerator.php @@ -1,4 +1,5 @@ . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Generator\Report\Category; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; -use FireflyIII\Generator\Report\Support; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Models\TransactionType; use Illuminate\Support\Collection; -use JetBrains\PhpStorm\Pure; use Log; use Throwable; /** * Class MonthReportGenerator. - * See reference nr. 18 + * TODO include info about tags * * @codeCoverageIgnore */ class MonthReportGenerator implements ReportGeneratorInterface { - /** @var Collection The included accounts */ - private $accounts; - /** @var Collection The included categories */ - private $categories; - /** @var Carbon The end date */ - private $end; - /** @var array The expenses */ - private $expenses; - /** @var array The income in the report. */ - private $income; - /** @var Carbon The start date. */ - private $start; + private Collection $accounts; + private Collection $categories; + private Carbon $end; + private array $expenses; + private array $income; + private Carbon $start; /** * MonthReportGenerator constructor. */ - #[Pure] public function __construct() + public function __construct() { - $this->income = new Collection; - $this->expenses = new Collection; + $this->income = []; + $this->expenses = []; } /** @@ -81,32 +74,17 @@ class MonthReportGenerator implements ReportGeneratorInterface ->with('categories', $this->categories) ->with('accounts', $this->accounts) ->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.category.month: %s', $e->getMessage())); $result = sprintf('Could not render report view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } - - return $result; - } - - /** - * Set the involved accounts. - * - * @param Collection $accounts - * - * @return ReportGeneratorInterface - */ - public function setAccounts(Collection $accounts): ReportGeneratorInterface - { - $this->accounts = $accounts; - - return $this; } /** * Empty budget setter. * - * @param Collection $budgets + * @param Collection $budgets * * @return ReportGeneratorInterface */ @@ -115,24 +93,10 @@ class MonthReportGenerator implements ReportGeneratorInterface return $this; } - /** - * Set the categories involved in this report. - * - * @param Collection $categories - * - * @return ReportGeneratorInterface - */ - public function setCategories(Collection $categories): ReportGeneratorInterface - { - $this->categories = $categories; - - return $this; - } - /** * Set the end date for this report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -146,7 +110,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the expenses involved in this report. * - * @param Collection $expense + * @param Collection $expense * * @return ReportGeneratorInterface */ @@ -158,7 +122,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the start date for this report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -172,7 +136,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Unused tag setter. * - * @param Collection $tags + * @param Collection $tags * * @return ReportGeneratorInterface */ @@ -188,7 +152,7 @@ class MonthReportGenerator implements ReportGeneratorInterface */ protected function getExpenses(): array { - if (!empty($this->expenses)) { + if (0 !== count($this->expenses)) { Log::debug('Return previous set of expenses.'); return $this->expenses; @@ -206,6 +170,34 @@ class MonthReportGenerator implements ReportGeneratorInterface return $transactions; } + /** + * Set the categories involved in this report. + * + * @param Collection $categories + * + * @return ReportGeneratorInterface + */ + public function setCategories(Collection $categories): ReportGeneratorInterface + { + $this->categories = $categories; + + return $this; + } + + /** + * Set the involved accounts. + * + * @param Collection $accounts + * + * @return ReportGeneratorInterface + */ + public function setAccounts(Collection $accounts): ReportGeneratorInterface + { + $this->accounts = $accounts; + + return $this; + } + /** * Get the income for this report. * @@ -213,7 +205,7 @@ class MonthReportGenerator implements ReportGeneratorInterface */ protected function getIncome(): array { - if (!empty($this->income)) { + if (0 !== count($this->income)) { return $this->income; } diff --git a/app/Generator/Report/Category/MultiYearReportGenerator.php b/app/Generator/Report/Category/MultiYearReportGenerator.php index 16e08dae65..832836929a 100644 --- a/app/Generator/Report/Category/MultiYearReportGenerator.php +++ b/app/Generator/Report/Category/MultiYearReportGenerator.php @@ -1,4 +1,5 @@ with('start', $this->start)->with('end', $this->end)->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.default.month: %s', $e->getMessage())); $result = 'Could not render report view.'; + throw new FireflyException($result, 0, $e); } - - return $result; } /** * Sets the accounts involved in the report. * - * @param Collection $accounts + * @param Collection $accounts * * @return ReportGeneratorInterface */ @@ -79,7 +80,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Unused budget setter. * - * @param Collection $budgets + * @param Collection $budgets * * @return ReportGeneratorInterface */ @@ -91,7 +92,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Unused category setter. * - * @param Collection $categories + * @param Collection $categories * * @return ReportGeneratorInterface */ @@ -103,7 +104,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the end date of the report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -117,7 +118,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the expenses used in this report. * - * @param Collection $expense + * @param Collection $expense * * @return ReportGeneratorInterface */ @@ -129,7 +130,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the start date of this report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -143,7 +144,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the tags used in this report. * - * @param Collection $tags + * @param Collection $tags * * @return ReportGeneratorInterface */ diff --git a/app/Generator/Report/Standard/MultiYearReportGenerator.php b/app/Generator/Report/Standard/MultiYearReportGenerator.php index 09794671e0..79c5441a1e 100644 --- a/app/Generator/Report/Standard/MultiYearReportGenerator.php +++ b/app/Generator/Report/Standard/MultiYearReportGenerator.php @@ -1,4 +1,5 @@ with('start', $this->start)->with('end', $this->end)->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.default.multi-year: %s', $e->getMessage())); $result = sprintf('Could not render report view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } - - return $result; } /** * Sets the accounts used in the report. * - * @param Collection $accounts + * @param Collection $accounts * * @return ReportGeneratorInterface */ @@ -83,7 +84,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface /** * Sets the budgets used in the report. * - * @param Collection $budgets + * @param Collection $budgets * * @return ReportGeneratorInterface */ @@ -95,7 +96,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface /** * Sets the categories used in the report. * - * @param Collection $categories + * @param Collection $categories * * @return ReportGeneratorInterface */ @@ -107,7 +108,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface /** * Sets the end date used in the report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -121,7 +122,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface /** * Unused setter for expenses. * - * @param Collection $expense + * @param Collection $expense * * @return ReportGeneratorInterface */ @@ -133,7 +134,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface /** * Set the start date of the report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -147,7 +148,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface /** * Set the tags for the report. * - * @param Collection $tags + * @param Collection $tags * * @return ReportGeneratorInterface */ diff --git a/app/Generator/Report/Standard/YearReportGenerator.php b/app/Generator/Report/Standard/YearReportGenerator.php index 95f52190db..2d537f0ec5 100644 --- a/app/Generator/Report/Standard/YearReportGenerator.php +++ b/app/Generator/Report/Standard/YearReportGenerator.php @@ -1,4 +1,5 @@ with('start', $this->start)->with('end', $this->end)->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); $result = 'Could not render report view.'; + throw new FireflyException($result, 0, $e); } return $result; @@ -69,7 +72,7 @@ class YearReportGenerator implements ReportGeneratorInterface /** * Set the accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return ReportGeneratorInterface */ @@ -83,7 +86,7 @@ class YearReportGenerator implements ReportGeneratorInterface /** * Unused budget setter. * - * @param Collection $budgets + * @param Collection $budgets * * @return ReportGeneratorInterface */ @@ -95,7 +98,7 @@ class YearReportGenerator implements ReportGeneratorInterface /** * Unused categories setter. * - * @param Collection $categories + * @param Collection $categories * * @return ReportGeneratorInterface */ @@ -107,7 +110,7 @@ class YearReportGenerator implements ReportGeneratorInterface /** * Set the end date. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -121,7 +124,7 @@ class YearReportGenerator implements ReportGeneratorInterface /** * Set the expenses used. * - * @param Collection $expense + * @param Collection $expense * * @return ReportGeneratorInterface */ @@ -133,7 +136,7 @@ class YearReportGenerator implements ReportGeneratorInterface /** * Set the start date. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -147,7 +150,7 @@ class YearReportGenerator implements ReportGeneratorInterface /** * Unused tags setter. * - * @param Collection $tags + * @param Collection $tags * * @return ReportGeneratorInterface */ diff --git a/app/Generator/Report/Tag/MonthReportGenerator.php b/app/Generator/Report/Tag/MonthReportGenerator.php index 87feaf83a9..bc974e2943 100644 --- a/app/Generator/Report/Tag/MonthReportGenerator.php +++ b/app/Generator/Report/Tag/MonthReportGenerator.php @@ -19,16 +19,14 @@ * along with this program. If not, see . */ -/** @noinspection MultipleReturnStatementsInspection */ declare(strict_types=1); namespace FireflyIII\Generator\Report\Tag; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Generator\Report\ReportGeneratorInterface; -use FireflyIII\Generator\Report\Support; use Illuminate\Support\Collection; -use JetBrains\PhpStorm\Pure; use Log; use Throwable; @@ -39,27 +37,18 @@ use Throwable; */ class MonthReportGenerator implements ReportGeneratorInterface { - /** @var Collection The accounts involved */ - private $accounts; - /** @var Carbon The end date */ - private $end; - /** @var array The expenses involved */ - private $expenses; - /** @var array The income involved */ - private $income; - /** @var Carbon The start date */ - private $start; - /** @var Collection The tags involved. */ - private $tags; + private Collection $accounts; + private Carbon $end; + private Carbon $start; + private Collection $tags; /** * MonthReportGenerator constructor. */ - #[Pure] public function __construct() + public function __construct() { - $this->expenses = new Collection; - $this->income = new Collection; - $this->tags = new Collection; + $this->tags = new Collection(); + $this->accounts = new Collection(); } /** @@ -79,9 +68,10 @@ class MonthReportGenerator implements ReportGeneratorInterface 'reports.tag.month', compact('accountIds', 'reportType', 'tagIds') )->with('start', $this->start)->with('end', $this->end)->with('tags', $this->tags)->with('accounts', $this->accounts)->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.tag.month: %s', $e->getMessage())); $result = sprintf('Could not render report view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; @@ -90,7 +80,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return ReportGeneratorInterface */ @@ -104,7 +94,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Unused budget setter. * - * @param Collection $budgets + * @param Collection $budgets * * @return ReportGeneratorInterface */ @@ -116,7 +106,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Unused category setter. * - * @param Collection $categories + * @param Collection $categories * * @return ReportGeneratorInterface */ @@ -128,7 +118,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the end date of the report. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -142,7 +132,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the expenses in this report. * - * @param Collection $expense + * @param Collection $expense * * @return ReportGeneratorInterface */ @@ -154,7 +144,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the start date. * - * @param Carbon $date + * @param Carbon $date * * @return ReportGeneratorInterface */ @@ -168,7 +158,7 @@ class MonthReportGenerator implements ReportGeneratorInterface /** * Set the tags used in this report. * - * @param Collection $tags + * @param Collection $tags * * @return ReportGeneratorInterface */ diff --git a/app/Generator/Report/Tag/MultiYearReportGenerator.php b/app/Generator/Report/Tag/MultiYearReportGenerator.php index f9fa197e21..493b9eea88 100644 --- a/app/Generator/Report/Tag/MultiYearReportGenerator.php +++ b/app/Generator/Report/Tag/MultiYearReportGenerator.php @@ -1,4 +1,5 @@ objects = new Collection(); + $this->webhooks = new Collection(); + } + /** * */ @@ -57,7 +69,9 @@ class StandardMessageGenerator implements MessageGeneratorInterface { Log::debug(__METHOD__); // get the webhooks: - $this->webhooks = $this->getWebhooks(); + if (0 === $this->webhooks->count()) { + $this->webhooks = $this->getWebhooks(); + } // do some debugging Log::debug( @@ -88,7 +102,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface } /** - * @param Webhook $webhook + * @param Webhook $webhook */ private function runWebhook(Webhook $webhook): void { @@ -100,22 +114,23 @@ class StandardMessageGenerator implements MessageGeneratorInterface } /** - * @param Webhook $webhook - * @param Model $model + * @param Webhook $webhook + * @param Model $model * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ private function generateMessage(Webhook $webhook, Model $model): void { $class = get_class($model); - Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id)); + // Line is ignored because all of Firefly III's Models have an id property. + Log::debug(sprintf('Now in generateMessage(#%d, %s#%d)', $webhook->id, $class, $model->id)); // @phpstan-ignore-line $uuid = Uuid::uuid4(); $basicMessage = [ 'uuid' => $uuid->toString(), 'user_id' => 0, - 'trigger' => config('firefly.webhooks.triggers')[$webhook->trigger], - 'response' => config('firefly.webhooks.responses')[$webhook->response], + 'trigger' => WebhookTrigger::from($webhook->trigger)->name, + 'response' => WebhookResponse::from($webhook->response)->name, 'url' => $webhook->url, 'version' => sprintf('v%d', $this->getVersion()), 'content' => [], @@ -124,7 +139,10 @@ class StandardMessageGenerator implements MessageGeneratorInterface // depends on the model how user_id is set: switch ($class) { default: - Log::error(sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id)); + // Line is ignored because all of Firefly III's Models have an id property. + Log::error( + sprintf('Webhook #%d was given %s#%d to deal with but can\'t extract user ID from it.', $webhook->id, $class, $model->id) + ); // @phpstan-ignore-line return; case TransactionGroup::class: @@ -141,11 +159,11 @@ class StandardMessageGenerator implements MessageGeneratorInterface ); return; - case Webhook::RESPONSE_NONE: + case WebhookResponse::NONE->value: $basicMessage['content'] = []; break; - case Webhook::RESPONSE_TRANSACTIONS: - $transformer = new TransactionGroupTransformer; + case WebhookResponse::TRANSACTIONS->value: + $transformer = new TransactionGroupTransformer(); try { $basicMessage['content'] = $transformer->transformObject($model); } catch (FireflyException $e) { @@ -156,11 +174,11 @@ class StandardMessageGenerator implements MessageGeneratorInterface return; } break; - case Webhook::RESPONSE_ACCOUNTS: + case WebhookResponse::ACCOUNTS->value: $accounts = $this->collectAccounts($model); foreach ($accounts as $account) { - $transformer = new AccountTransformer; - $transformer->setParameters(new ParameterBag); + $transformer = new AccountTransformer(); + $transformer->setParameters(new ParameterBag()); $basicMessage['content'][] = $transformer->transform($account); } } @@ -176,13 +194,13 @@ class StandardMessageGenerator implements MessageGeneratorInterface } /** - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return Collection */ private function collectAccounts(TransactionGroup $transactionGroup): Collection { - $accounts = new Collection; + $accounts = new Collection(); /** @var TransactionJournal $journal */ foreach ($transactionGroup->transactionJournals as $journal) { /** @var Transaction $transaction */ @@ -195,14 +213,14 @@ class StandardMessageGenerator implements MessageGeneratorInterface } /** - * @param Webhook $webhook - * @param array $message + * @param Webhook $webhook + * @param array $message * * @return void */ private function storeMessage(Webhook $webhook, array $message): void { - $webhookMessage = new WebhookMessage; + $webhookMessage = new WebhookMessage(); $webhookMessage->webhook()->associate($webhook); $webhookMessage->sent = false; $webhookMessage->errored = false; @@ -210,11 +228,10 @@ class StandardMessageGenerator implements MessageGeneratorInterface $webhookMessage->message = $message; $webhookMessage->save(); Log::debug(sprintf('Stored new webhook message #%d', $webhookMessage->id)); - } /** - * @param Collection $objects + * @param Collection $objects */ public function setObjects(Collection $objects): void { @@ -222,7 +239,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface } /** - * @param int $trigger + * @param int $trigger */ public function setTrigger(int $trigger): void { @@ -230,10 +247,18 @@ class StandardMessageGenerator implements MessageGeneratorInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; } + + /** + * @inheritDoc + */ + public function setWebhooks(Collection $webhooks): void + { + $this->webhooks = $webhooks; + } } diff --git a/app/Handlers/Events/APIEventHandler.php b/app/Handlers/Events/APIEventHandler.php index b3fdd0222c..8dcef4bc8f 100644 --- a/app/Handlers/Events/APIEventHandler.php +++ b/app/Handlers/Events/APIEventHandler.php @@ -23,14 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Handlers\Events; -use Exception; use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Mail\AccessTokenCreatedMail; +use FireflyIII\Notifications\User\NewAccessToken; use FireflyIII\Repositories\User\UserRepositoryInterface; +use Illuminate\Support\Facades\Notification; use Laravel\Passport\Events\AccessTokenCreated; use Log; -use Mail; -use Session; /** * Class APIEventHandler @@ -40,46 +38,19 @@ class APIEventHandler /** * Respond to the creation of an access token. * - * @param AccessTokenCreated $event + * @param AccessTokenCreated $event * - * @return bool * @throws FireflyException */ - public function accessTokenCreated(AccessTokenCreated $event): bool + public function accessTokenCreated(AccessTokenCreated $event): void { + Log::debug(__METHOD__); /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); - $user = $repository->find((int) $event->userId); + $user = $repository->find((int)$event->userId); + if (null !== $user) { - $email = $user->email; - - // if user is demo user, send to owner: - if ($user->hasRole('demo')) { - $email = config('firefly.site_owner'); - } - - // see if user has alternative email address: - $pref = app('preferences')->getForUser($user, 'remote_guard_alt_email'); - if (null !== $pref) { - $email = (string) (is_array($pref->data) ? $email : $pref->data); - } - - Log::debug(sprintf('Now in APIEventHandler::accessTokenCreated. Email is %s', $email)); - try { - Log::debug('Trying to send message...'); - Mail::to($email)->send(new AccessTokenCreatedMail); - - } catch (Exception $e) { // @phpstan-ignore-line - 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.'); + Notification::send($user, new NewAccessToken()); } - - return true; } - } diff --git a/app/Handlers/Events/AdminEventHandler.php b/app/Handlers/Events/AdminEventHandler.php index d35ab1c2c4..768ba63f11 100644 --- a/app/Handlers/Events/AdminEventHandler.php +++ b/app/Handlers/Events/AdminEventHandler.php @@ -1,4 +1,5 @@ data; + if (false === $sendMail) { + return; + } + + /** @var UserRepositoryInterface $repository */ + $repository = app(UserRepositoryInterface::class); + $all = $repository->all(); + foreach ($all as $user) { + if ($repository->hasRole($user, 'owner')) { + Notification::send($user, new UserInvitation($event->invitee)); + } + } + } + + /** + * Send new version message to admin. + * + * @param NewVersionAvailable $event + * @return void + */ + public function sendNewVersion(NewVersionAvailable $event): void + { + $sendMail = FireflyConfig::get('notification_new_version', true)->data; + if (false === $sendMail) { + return; + } + + /** @var UserRepositoryInterface $repository */ + $repository = app(UserRepositoryInterface::class); + $all = $repository->all(); + foreach ($all as $user) { + if ($repository->hasRole($user, 'owner')) { + Notification::send($user, new VersionCheckResult($event->message)); + } + } + } + /** * Sends a test message to an administrator. * - * @param AdminRequestedTestMessage $event + * @param AdminRequestedTestMessage $event * - * @return bool - * @throws FireflyException + * @return void */ - public function sendTestMessage(AdminRequestedTestMessage $event): bool + public function sendTestMessage(AdminRequestedTestMessage $event): void { /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); - // is user even admin? - if ($repository->hasRole($event->user, 'owner')) { - $email = $event->user->email; - - // if user is demo user, send to owner: - if ($event->user->hasRole('demo')) { - $email = config('firefly.site_owner'); - } - - // see if user has alternative email address: - $pref = app('preferences')->getForUser($event->user, 'remote_guard_alt_email'); - if (null !== $pref) { - $email = $pref->data; - } - - Log::debug(sprintf('Now in sendTestMessage event handler. Email is %s', $email)); - try { - Log::debug('Trying to send message...'); - Mail::to($email)->send(new AdminTestMail($email)); - - // Laravel cannot pretend this process failed during testing. - } catch (Exception $e) { // @phpstan-ignore-line - 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.'); + if (!$repository->hasRole($event->user, 'owner')) { + return; } - return true; + Notification::send($event->user, new TestNotification($event->user->email)); } } diff --git a/app/Handlers/Events/AuditEventHandler.php b/app/Handlers/Events/AuditEventHandler.php new file mode 100644 index 0000000000..b5a0471aff --- /dev/null +++ b/app/Handlers/Events/AuditEventHandler.php @@ -0,0 +1,49 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Handlers\Events; + +use FireflyIII\Events\TriggeredAuditLog; +use FireflyIII\Repositories\AuditLogEntry\ALERepositoryInterface; + +class AuditEventHandler +{ + /** + * @param TriggeredAuditLog $event + * @return void + */ + public function storeAuditEvent(TriggeredAuditLog $event) + { + $array = [ + 'auditable' => $event->auditable, + 'changer' => $event->changer, + 'action' => $event->field, + 'before' => $event->before, + 'after' => $event->after, + ]; + /** @var ALERepositoryInterface $repository */ + $repository = app(ALERepositoryInterface::class); + $repository->store($array); + } +} diff --git a/app/Handlers/Events/AutomationHandler.php b/app/Handlers/Events/AutomationHandler.php index cd72404822..6cdace98b6 100644 --- a/app/Handlers/Events/AutomationHandler.php +++ b/app/Handlers/Events/AutomationHandler.php @@ -23,53 +23,48 @@ declare(strict_types=1); namespace FireflyIII\Handlers\Events; -use Exception; use FireflyIII\Events\RequestedReportOnJournals; -use FireflyIII\Exceptions\FireflyException; -use FireflyIII\Mail\ReportNewJournalsMail; +use FireflyIII\Models\TransactionGroup; +use FireflyIII\Notifications\User\TransactionCreation; use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\Transformers\TransactionGroupTransformer; +use Illuminate\Support\Facades\Notification; use Log; -use Mail; /** * Class AutomationHandler */ class AutomationHandler { - /** * Respond to the creation of X journals. * - * @param RequestedReportOnJournals $event - * - * @return bool + * @param RequestedReportOnJournals $event */ - public function reportJournals(RequestedReportOnJournals $event): bool + public function reportJournals(RequestedReportOnJournals $event): void { + Log::debug('In reportJournals.'); $sendReport = config('firefly.send_report_journals'); - if (false === $sendReport) { - return true; + return; } - Log::debug('In reportJournals.'); /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); $user = $repository->find($event->userId); - if (null !== $user && 0 !== $event->groups->count()) { - try { - Log::debug('Trying to mail...'); - Mail::to($user->email)->send(new ReportNewJournalsMail($event->groups)); - - } catch (Exception $e) { // @phpstan-ignore-line - Log::debug('Send message failed! :('); - Log::error($e->getMessage()); - Log::error($e->getTraceAsString()); - } - - Log::debug('Done!'); + if (null === $user || 0 === $event->groups->count()) { + return; } - return true; + // transform groups into array: + /** @var TransactionGroupTransformer $transformer */ + $transformer = app(TransactionGroupTransformer::class); + $groups = []; + /** @var TransactionGroup $group */ + foreach ($event->groups as $group) { + $groups[] = $transformer->transformObject($group); + } + + Notification::send($user, new TransactionCreation($groups)); } } diff --git a/app/Handlers/Events/BillEventHandler.php b/app/Handlers/Events/BillEventHandler.php index 21b04d7cce..48b9e7c306 100644 --- a/app/Handlers/Events/BillEventHandler.php +++ b/app/Handlers/Events/BillEventHandler.php @@ -25,9 +25,10 @@ declare(strict_types=1); namespace FireflyIII\Handlers\Events; use FireflyIII\Events\WarnUserAboutBill; -use FireflyIII\Mail\BillWarningMail; -use Log; -use Mail; +use FireflyIII\Notifications\User\BillReminder; +use FireflyIII\Support\Facades\Preferences; +use Illuminate\Support\Facades\Log; +use Illuminate\Support\Facades\Notification; /** * Class BillEventHandler @@ -35,30 +36,23 @@ use Mail; class BillEventHandler { /** - * @param WarnUserAboutBill $event + * @param WarnUserAboutBill $event * @return void - * @throws \FireflyIII\Exceptions\FireflyException */ public function warnAboutBill(WarnUserAboutBill $event): void { - $bill = $event->bill; - $field = $event->field; - $diff = $event->diff; - $user = $bill->user; - $address = $user->email; - $ipAddress = request()?->ip(); + Log::debug(sprintf('Now in %s', __METHOD__)); - // see if user has alternative email address: - $pref = app('preferences')->getForUser($user, 'remote_guard_alt_email'); - if (null !== $pref) { - $address = $pref->data; + $bill = $event->bill; + /** @var bool $preference */ + $preference = Preferences::getForUser($bill->user, 'notification_bill_reminder', true)->data; + + if (true === $preference) { + Log::debug('Bill reminder is true!'); + Notification::send($bill->user, new BillReminder($bill, $event->field, $event->diff)); + } + if (false === $preference) { + Log::debug('User has disabled bill reminders.'); } - - // send message: - Mail::to($address)->send(new BillWarningMail($bill, $field, $diff, $ipAddress)); - - - Log::debug('warnAboutBill'); } - } diff --git a/app/Handlers/Events/DestroyedGroupEventHandler.php b/app/Handlers/Events/DestroyedGroupEventHandler.php index 7d6837cd14..093f3e48d8 100644 --- a/app/Handlers/Events/DestroyedGroupEventHandler.php +++ b/app/Handlers/Events/DestroyedGroupEventHandler.php @@ -23,10 +23,10 @@ declare(strict_types=1); namespace FireflyIII\Handlers\Events; +use FireflyIII\Enums\WebhookTrigger; use FireflyIII\Events\DestroyedTransactionGroup; use FireflyIII\Events\RequestedSendWebhookMessages; use FireflyIII\Generator\Webhook\MessageGeneratorInterface; -use FireflyIII\Models\Webhook; use Illuminate\Support\Collection; use Log; @@ -36,7 +36,7 @@ use Log; class DestroyedGroupEventHandler { /** - * @param DestroyedTransactionGroup $destroyedGroupEvent + * @param DestroyedTransactionGroup $destroyedGroupEvent */ public function triggerWebhooks(DestroyedTransactionGroup $destroyedGroupEvent): void { @@ -47,9 +47,9 @@ class DestroyedGroupEventHandler $engine = app(MessageGeneratorInterface::class); $engine->setUser($user); $engine->setObjects(new Collection([$group])); - $engine->setTrigger(Webhook::TRIGGER_DESTROY_TRANSACTION); + $engine->setTrigger(WebhookTrigger::DESTROY_TRANSACTION->value); $engine->generateMessages(); - event(new RequestedSendWebhookMessages); + event(new RequestedSendWebhookMessages()); } } diff --git a/app/Handlers/Events/PiggyBankEventHandler.php b/app/Handlers/Events/PiggyBankEventHandler.php index dc4edf6cbf..33b81f7e60 100644 --- a/app/Handlers/Events/PiggyBankEventHandler.php +++ b/app/Handlers/Events/PiggyBankEventHandler.php @@ -29,7 +29,6 @@ use FireflyIII\Events\ChangedPiggyBankAmount; use FireflyIII\Models\PiggyBankEvent; use Illuminate\Support\Facades\Log; - /** * Class PiggyBankEventHandler */ @@ -53,7 +52,7 @@ class PiggyBankEventHandler $exists = PiggyBankEvent::where('piggy_bank_id', $event->piggyBank->id) ->where('transaction_journal_id', $journal->id) ->exists(); - if($exists) { + if ($exists) { Log::warning('Already have event for this journal and piggy, will not create another.'); return; } @@ -68,5 +67,4 @@ class PiggyBankEventHandler ] ); } - } diff --git a/app/Handlers/Events/StoredAccountEventHandler.php b/app/Handlers/Events/StoredAccountEventHandler.php index 59c670e135..e28febaa47 100644 --- a/app/Handlers/Events/StoredAccountEventHandler.php +++ b/app/Handlers/Events/StoredAccountEventHandler.php @@ -33,7 +33,7 @@ use FireflyIII\Services\Internal\Support\CreditRecalculateService; class StoredAccountEventHandler { /** - * @param StoredAccount $event + * @param StoredAccount $event */ public function recalculateCredit(StoredAccount $event): void { @@ -43,5 +43,4 @@ class StoredAccountEventHandler $object->setAccount($account); $object->recalculate(); } - } diff --git a/app/Handlers/Events/StoredGroupEventHandler.php b/app/Handlers/Events/StoredGroupEventHandler.php index ab85c412c3..4b6e549dc4 100644 --- a/app/Handlers/Events/StoredGroupEventHandler.php +++ b/app/Handlers/Events/StoredGroupEventHandler.php @@ -1,4 +1,5 @@ setUser($user); // tell the generator which trigger it should look for - $engine->setTrigger(Webhook::TRIGGER_STORE_TRANSACTION); + $engine->setTrigger(WebhookTrigger::STORE_TRANSACTION->value); // tell the generator which objects to process $engine->setObjects(new Collection([$group])); // tell the generator to generate the messages $engine->generateMessages(); // trigger event to send them: - event(new RequestedSendWebhookMessages); + event(new RequestedSendWebhookMessages()); } - } diff --git a/app/Handlers/Events/UpdatedAccountEventHandler.php b/app/Handlers/Events/UpdatedAccountEventHandler.php index 096ab5f99c..0de35afd9b 100644 --- a/app/Handlers/Events/UpdatedAccountEventHandler.php +++ b/app/Handlers/Events/UpdatedAccountEventHandler.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Handlers\Events; - use FireflyIII\Events\UpdatedAccount; use FireflyIII\Services\Internal\Support\CreditRecalculateService; @@ -34,7 +33,7 @@ use FireflyIII\Services\Internal\Support\CreditRecalculateService; class UpdatedAccountEventHandler { /** - * @param UpdatedAccount $event + * @param UpdatedAccount $event */ public function recalculateCredit(UpdatedAccount $event): void { diff --git a/app/Handlers/Events/UpdatedGroupEventHandler.php b/app/Handlers/Events/UpdatedGroupEventHandler.php index 7000166584..af1882d7b0 100644 --- a/app/Handlers/Events/UpdatedGroupEventHandler.php +++ b/app/Handlers/Events/UpdatedGroupEventHandler.php @@ -1,4 +1,5 @@ setUser($user); $engine->setObjects(new Collection([$group])); - $engine->setTrigger(Webhook::TRIGGER_UPDATE_TRANSACTION); + $engine->setTrigger(WebhookTrigger::UPDATE_TRANSACTION->value); $engine->generateMessages(); - event(new RequestedSendWebhookMessages); + event(new RequestedSendWebhookMessages()); } /** * This method will make sure all source / destination accounts are the same. * - * @param UpdatedTransactionGroup $updatedGroupEvent + * @param UpdatedTransactionGroup $updatedGroupEvent */ public function unifyAccounts(UpdatedTransactionGroup $updatedGroupEvent): void { @@ -124,7 +125,7 @@ class UpdatedGroupEventHandler return; } // first journal: - /** @var TransactionJournal $first */ + /** @var TransactionJournal|null $first */ $first = $group->transactionJournals() ->orderBy('transaction_journals.date', 'DESC') ->orderBy('transaction_journals.order', 'ASC') @@ -133,7 +134,7 @@ class UpdatedGroupEventHandler ->first(); if (null === $first) { - Log::warning(sprintf('Group #%d has no transaction journals.', $group->id)); + app('log')->warning(sprintf('Group #%d has no transaction journals.', $group->id)); return; } @@ -154,6 +155,5 @@ class UpdatedGroupEventHandler Transaction::whereIn('transaction_journal_id', $all) ->where('amount', '>', 0)->update(['account_id' => $destAccount->id]); } - } } diff --git a/app/Handlers/Events/UserEventHandler.php b/app/Handlers/Events/UserEventHandler.php index 2d8c2ca22d..2c23b85cdc 100644 --- a/app/Handlers/Events/UserEventHandler.php +++ b/app/Handlers/Events/UserEventHandler.php @@ -1,4 +1,5 @@ . */ -/** @noinspection NullPointerExceptionInspection */ declare(strict_types=1); namespace FireflyIII\Handlers\Events; use Carbon\Carbon; +use Database\Seeders\ExchangeRateSeeder; use Exception; use FireflyIII\Events\ActuallyLoggedIn; +use FireflyIII\Events\Admin\InvitationCreated; use FireflyIII\Events\DetectedNewIPAddress; use FireflyIII\Events\RegisteredUser; use FireflyIII\Events\RequestedNewPassword; use FireflyIII\Events\UserChangedEmail; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Mail\ConfirmEmailChangeMail; -use FireflyIII\Mail\NewIPAddressWarningMail; -use FireflyIII\Mail\RegisteredUser as RegisteredUserMail; -use FireflyIII\Mail\RequestedNewPassword as RequestedNewPasswordMail; +use FireflyIII\Mail\InvitationMail; use FireflyIII\Mail\UndoEmailChangeMail; use FireflyIII\Models\GroupMembership; use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserRole; +use FireflyIII\Notifications\Admin\UserRegistration as AdminRegistrationNotification; +use FireflyIII\Notifications\User\UserLogin; +use FireflyIII\Notifications\User\UserNewPassword; +use FireflyIII\Notifications\User\UserRegistration as UserRegistrationNotification; use FireflyIII\Repositories\User\UserRepositoryInterface; +use FireflyIII\Support\Facades\FireflyConfig; use FireflyIII\User; use Illuminate\Auth\Events\Login; +use Illuminate\Support\Facades\Notification; use Log; use Mail; @@ -57,11 +63,9 @@ class UserEventHandler /** * This method will bestow upon a user the "owner" role if he is the first user in the system. * - * @param RegisteredUser $event - * - * @return bool + * @param RegisteredUser $event */ - public function attachUserRole(RegisteredUser $event): bool + public function attachUserRole(RegisteredUser $event): void { /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); @@ -71,18 +75,14 @@ class UserEventHandler Log::debug('User count is one, attach role.'); $repository->attachRole($event->user, 'owner'); } - - return true; } /** * Fires to see if a user is admin. * - * @param Login $event - * - * @return bool + * @param Login $event */ - public function checkSingleUserIsAdmin(Login $event): bool + public function checkSingleUserIsAdmin(Login $event): void { /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); @@ -105,22 +105,30 @@ class UserEventHandler // give user the role $repository->attachRole($user, 'owner'); } - - return true; } /** - * @param RegisteredUser $event + * @param RegisteredUser $event + */ + public function createExchangeRates(RegisteredUser $event): void + { + $seeder = new ExchangeRateSeeder(); + $seeder->run(); + } + + /** + * @param RegisteredUser $event * - * @return bool * @throws FireflyException */ - public function createGroupMembership(RegisteredUser $event): bool + public function createGroupMembership(RegisteredUser $event): void { $user = $event->user; $groupExists = true; $groupTitle = $user->email; $index = 1; + /** @var UserGroup $group */ + $group = null; // create a new group. while (true === $groupExists) { @@ -135,6 +143,7 @@ class UserEventHandler throw new FireflyException('Email address can no longer be used for registrations.'); } } + /** @var UserRole|null $role */ $role = UserRole::where('title', UserRole::OWNER)->first(); if (null === $role) { throw new FireflyException('The user role is unexpectedly empty. Did you run all migrations?'); @@ -148,19 +157,16 @@ class UserEventHandler ); $user->user_group_id = $group->id; $user->save(); - - return true; } /** * Set the demo user back to English. * - * @param Login $event + * @param Login $event * - * @return bool * @throws FireflyException */ - public function demoUserBackToEnglish(Login $event): bool + public function demoUserBackToEnglish(Login $event): void { /** @var UserRepositoryInterface $repository */ $repository = app(UserRepositoryInterface::class); @@ -173,12 +179,10 @@ class UserEventHandler app('preferences')->setForUser($user, 'locale', 'equal'); app('preferences')->mark(); } - - return true; } /** - * @param DetectedNewIPAddress $event + * @param DetectedNewIPAddress $event * * @throws FireflyException */ @@ -194,21 +198,10 @@ class UserEventHandler $list = app('preferences')->getForUser($user, 'login_ip_history', [])->data; - // see if user has alternative email address: - $pref = app('preferences')->getForUser($user, 'remote_guard_alt_email'); - if (null !== $pref) { - $email = $pref->data; - } - /** @var array $entry */ foreach ($list as $index => $entry) { if (false === $entry['notified']) { - try { - Mail::to($email)->send(new NewIPAddressWarningMail($ipAddress)); - - } catch (Exception $e) { // @phpstan-ignore-line - Log::error($e->getMessage()); - } + Notification::send($user, new UserLogin($ipAddress)); } $list[$index]['notified'] = true; } @@ -217,134 +210,128 @@ class UserEventHandler } /** - * Send email to confirm email change. + * @param RegisteredUser $event + */ + public function sendAdminRegistrationNotification(RegisteredUser $event): void + { + $sendMail = FireflyConfig::get('notification_admin_new_reg', true)->data; + if ($sendMail) { + /** @var UserRepositoryInterface $repository */ + $repository = app(UserRepositoryInterface::class); + $all = $repository->all(); + foreach ($all as $user) { + if ($repository->hasRole($user, 'owner')) { + Notification::send($user, new AdminRegistrationNotification($event->user)); + } + } + } + } + + /** + * Send email to confirm email change. Will not be made into a notification, because + * this requires some custom fields from the user and not just the "user" object. * - * @param UserChangedEmail $event + * @param UserChangedEmail $event * - * @return bool * @throws FireflyException */ - public function sendEmailChangeConfirmMail(UserChangedEmail $event): bool + public function sendEmailChangeConfirmMail(UserChangedEmail $event): void { $newEmail = $event->newEmail; $oldEmail = $event->oldEmail; $user = $event->user; $token = app('preferences')->getForUser($user, 'email_change_confirm_token', 'invalid'); $url = route('profile.confirm-email-change', [$token->data]); + try { Mail::to($newEmail)->send(new ConfirmEmailChangeMail($newEmail, $oldEmail, $url)); - - } catch (Exception $e) { // @phpstan-ignore-line + } catch (Exception $e) { // intentional generic exception Log::error($e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } - - return true; } /** - * Send email to be able to undo email change. + * Send email to be able to undo email change. Will not be made into a notification, because + * this requires some custom fields from the user and not just the "user" object. * - * @param UserChangedEmail $event + * @param UserChangedEmail $event * - * @return bool * @throws FireflyException */ - public function sendEmailChangeUndoMail(UserChangedEmail $event): bool + public function sendEmailChangeUndoMail(UserChangedEmail $event): void { $newEmail = $event->newEmail; $oldEmail = $event->oldEmail; $user = $event->user; $token = app('preferences')->getForUser($user, 'email_change_undo_token', 'invalid'); - $hashed = hash('sha256', sprintf('%s%s', (string) config('app.key'), $oldEmail)); + $hashed = hash('sha256', sprintf('%s%s', (string)config('app.key'), $oldEmail)); $url = route('profile.undo-email-change', [$token->data, $hashed]); try { Mail::to($oldEmail)->send(new UndoEmailChangeMail($newEmail, $oldEmail, $url)); - - } catch (Exception $e) { // @phpstan-ignore-line + } catch (Exception $e) { // intentional generic exception Log::error($e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } - - return true; } /** * Send a new password to the user. - * - * @param RequestedNewPassword $event - * - * @return bool + * @param RequestedNewPassword $event */ - public function sendNewPassword(RequestedNewPassword $event): bool + public function sendNewPassword(RequestedNewPassword $event): void { - $email = $event->user->email; - $ipAddress = $event->ipAddress; - $token = $event->token; + Notification::send($event->user, new UserNewPassword(route('password.reset', [$event->token]))); + } - $url = route('password.reset', [$token]); - - // send email. + /** + * @param InvitationCreated $event + * @return void + */ + public function sendRegistrationInvite(InvitationCreated $event): void + { + $invitee = $event->invitee->email; + $admin = $event->invitee->user->email; + $url = route('invite', [$event->invitee->invite_code]); try { - Mail::to($email)->send(new RequestedNewPasswordMail($url, $ipAddress)); - - } catch (Exception $e) { // @phpstan-ignore-line + Mail::to($invitee)->send(new InvitationMail($invitee, $admin, $url)); + } catch (Exception $e) { // intentional generic exception Log::error($e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } - - return true; } /** * This method will send the user a registration mail, welcoming him or her to Firefly III. * This message is only sent when the configuration of Firefly III says so. * - * @param RegisteredUser $event + * @param RegisteredUser $event * - * @return bool - * @throws FireflyException */ - public function sendRegistrationMail(RegisteredUser $event): bool + public function sendRegistrationMail(RegisteredUser $event): void { - $sendMail = config('firefly.send_registration_mail'); + $sendMail = FireflyConfig::get('notification_user_new_reg', true)->data; if ($sendMail) { - // get the email address - $email = $event->user->email; - $url = route('index'); - - // see if user has alternative email address: - $pref = app('preferences')->getForUser($event->user, 'remote_guard_alt_email'); - if (null !== $pref) { - $email = $pref->data; - } - - // send email. - try { - Mail::to($email)->send(new RegisteredUserMail($url)); - - } catch (Exception $e) { // @phpstan-ignore-line - Log::error($e->getMessage()); - } - + Notification::send($event->user, new UserRegistrationNotification()); } - - return true; } /** - * @param ActuallyLoggedIn $event + * @param ActuallyLoggedIn $event * @throws FireflyException */ public function storeUserIPAddress(ActuallyLoggedIn $event): void { Log::debug('Now in storeUserIPAddress'); $user = $event->user; - /** @var array $preference */ - if($user->hasRole('demo')) { + if ($user->hasRole('demo')) { Log::debug('Do not log demo user logins'); return; } try { + /** @var array $preference */ $preference = app('preferences')->getForUser($user, 'login_ip_history', [])->data; } catch (FireflyException $e) { // don't care. @@ -379,11 +366,12 @@ class UserEventHandler ]; } $preference = array_values($preference); + /** @var bool $send */ + $send = app('preferences')->getForUser($user, 'notification_user_login', true)->data; app('preferences')->setForUser($user, 'login_ip_history', $preference); - if (false === $inArray && true === config('firefly.warn_new_ip')) { + if (false === $inArray && true === $send) { event(new DetectedNewIPAddress($user, $ip)); } - } } diff --git a/app/Handlers/Events/VersionCheckEventHandler.php b/app/Handlers/Events/VersionCheckEventHandler.php index 6485f1d042..55794f6e5a 100644 --- a/app/Handlers/Events/VersionCheckEventHandler.php +++ b/app/Handlers/Events/VersionCheckEventHandler.php @@ -1,4 +1,5 @@ . */ -/** @noinspection MultipleReturnStatementsInspection */ -/** @noinspection NullPointerExceptionInspection */ declare(strict_types=1); namespace FireflyIII\Handlers\Events; @@ -30,6 +29,8 @@ use FireflyIII\Helpers\Update\UpdateTrait; use FireflyIII\Models\Configuration; use FireflyIII\Repositories\User\UserRepositoryInterface; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class VersionCheckEventHandler @@ -41,11 +42,12 @@ class VersionCheckEventHandler /** * Checks with GitHub to see if there is a new version. * - * @param RequestedVersionCheckStatus $event + * @param RequestedVersionCheckStatus $event * * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + * @deprecated ? */ public function checkForUpdates(RequestedVersionCheckStatus $event): void { @@ -53,7 +55,7 @@ class VersionCheckEventHandler // should not check for updates: $permission = app('fireflyconfig')->get('permission_update_check', -1); - $value = (int) $permission->data; + $value = (int)$permission->data; if (1 !== $value) { Log::info('Update check is not enabled.'); $this->warnToCheckForUpdates($event); @@ -89,11 +91,11 @@ class VersionCheckEventHandler } /** - * @param RequestedVersionCheckStatus $event + * @param RequestedVersionCheckStatus $event * * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ protected function warnToCheckForUpdates(RequestedVersionCheckStatus $event): void { @@ -119,7 +121,7 @@ class VersionCheckEventHandler // last check time was more than a week ago. Log::debug('Have warned about a new version in four weeks!'); - session()->flash('info', (string) trans('firefly.disabled_but_check')); + session()->flash('info', (string)trans('firefly.disabled_but_check')); app('fireflyconfig')->set('last_update_warning', time()); } } diff --git a/app/Handlers/Events/WebhookEventHandler.php b/app/Handlers/Events/WebhookEventHandler.php index 2a75380c21..fd8c2fc735 100644 --- a/app/Handlers/Events/WebhookEventHandler.php +++ b/app/Handlers/Events/WebhookEventHandler.php @@ -37,19 +37,24 @@ class WebhookEventHandler */ public function sendWebhookMessages(): void { + Log::debug(sprintf('Now in %s', __METHOD__)); // kick off the job! - $messages = WebhookMessage - ::where('webhook_messages.sent', 0) - //->where('webhook_messages.errored', 0) - ->get(['webhook_messages.*']) - ->filter( - function (WebhookMessage $message) { - return $message->webhookAttempts()->count() <= 2; - } - )->splice(0, 5); + $messages = WebhookMessage::where('webhook_messages.sent',false) + ->get(['webhook_messages.*']) + ->filter( + function (WebhookMessage $message) { + return $message->webhookAttempts()->count() <= 2; + } + )->splice(0, 5); Log::debug(sprintf('Found %d webhook message(s) ready to be send.', $messages->count())); foreach ($messages as $message) { - SendWebhookMessage::dispatch($message)->afterResponse(); + if (false === $message->sent) { + Log::debug(sprintf('Send message #%d', $message->id)); + SendWebhookMessage::dispatch($message)->afterResponse(); + } + if (false !== $message->sent) { + Log::debug(sprintf('Skip message #%d', $message->id)); + } } } } diff --git a/app/Helpers/Attachments/AttachmentHelper.php b/app/Helpers/Attachments/AttachmentHelper.php index 42a2001d22..0d566bfd4c 100644 --- a/app/Helpers/Attachments/AttachmentHelper.php +++ b/app/Helpers/Attachments/AttachmentHelper.php @@ -1,4 +1,5 @@ maxUploadSize = (int) config('firefly.maxUploadSize'); - $this->allowedMimes = (array) config('firefly.allowedMimes'); - $this->errors = new MessageBag; - $this->messages = new MessageBag; - $this->attachments = new Collection; + $this->maxUploadSize = (int)config('firefly.maxUploadSize'); + $this->allowedMimes = (array)config('firefly.allowedMimes'); + $this->errors = new MessageBag(); + $this->messages = new MessageBag(); + $this->attachments = new Collection(); $this->uploadDisk = Storage::disk('upload'); } @@ -70,13 +71,13 @@ class AttachmentHelper implements AttachmentHelperInterface * * @codeCoverageIgnore * - * @param Attachment $attachment + * @param Attachment $attachment * * @return string */ public function getAttachmentContent(Attachment $attachment): string { - $encryptedData = (string) $this->uploadDisk->get(sprintf('at-%d.data', $attachment->id)); + $encryptedData = (string)$this->uploadDisk->get(sprintf('at-%d.data', $attachment->id)); try { $unencryptedData = Crypt::decrypt($encryptedData); // verified } catch (DecryptException $e) { @@ -90,14 +91,14 @@ class AttachmentHelper implements AttachmentHelperInterface /** * Returns the file path relative to upload disk for an attachment, * - * @param Attachment $attachment + * @param Attachment $attachment * * @codeCoverageIgnore * @return string */ public function getAttachmentLocation(Attachment $attachment): string { - return sprintf('%sat-%d.data', DIRECTORY_SEPARATOR, (int) $attachment->id); + return sprintf('%sat-%d.data', DIRECTORY_SEPARATOR, (int)$attachment->id); } /** @@ -136,8 +137,8 @@ class AttachmentHelper implements AttachmentHelperInterface /** * Uploads a file as a string. * - * @param Attachment $attachment - * @param string $content + * @param Attachment $attachment + * @param string $content * * @return bool */ @@ -145,11 +146,9 @@ class AttachmentHelper implements AttachmentHelperInterface { $resource = tmpfile(); if (false === $resource) { - Log::error('Cannot create temp-file for file upload.'); return false; - } if ('' === $content) { @@ -187,8 +186,8 @@ class AttachmentHelper implements AttachmentHelperInterface /** * Save attachments that get uploaded with models, through the app. * - * @param object $model - * @param array|null $files + * @param object $model + * @param array|null $files * * @return bool * @throws FireflyException @@ -220,8 +219,8 @@ class AttachmentHelper implements AttachmentHelperInterface /** * Process the upload of a file. * - * @param UploadedFile $file - * @param Model $model + * @param UploadedFile $file + * @param Model $model * * @return Attachment|null * @throws FireflyException @@ -233,13 +232,13 @@ class AttachmentHelper implements AttachmentHelperInterface $validation = $this->validateUpload($file, $model); $attachment = null; if (false !== $validation) { - $class = get_class($model); - $user = $model->user; - if (PiggyBank::class === $class) { + $user = $model->user; // @phpstan-ignore-line + // ignore lines about polymorphic calls. + if ($model instanceof PiggyBank) { $user = $model->account->user; } - $attachment = new Attachment; // create Attachment object. + $attachment = new Attachment(); // create Attachment object. $attachment->user()->associate($user); $attachment->attachable()->associate($model); $attachment->md5 = md5_file($file->getRealPath()); @@ -267,7 +266,7 @@ class AttachmentHelper implements AttachmentHelperInterface $this->attachments->push($attachment); $name = e($file->getClientOriginalName()); // add message: - $msg = (string) trans('validation.file_attached', ['name' => $name]); + $msg = (string)trans('validation.file_attached', ['name' => $name]); $this->messages->add('attachments', $msg); } @@ -277,8 +276,8 @@ class AttachmentHelper implements AttachmentHelperInterface /** * Verify if the file was uploaded correctly. * - * @param UploadedFile $file - * @param Model $model + * @param UploadedFile $file + * @param Model $model * * @return bool */ @@ -310,7 +309,7 @@ class AttachmentHelper implements AttachmentHelperInterface /** * Verify if the mime of a file is valid. * - * @param UploadedFile $file + * @param UploadedFile $file * * @return bool */ @@ -324,7 +323,7 @@ class AttachmentHelper implements AttachmentHelperInterface $result = true; if (!in_array($mime, $this->allowedMimes, true)) { - $msg = (string) trans('validation.file_invalid_mime', ['name' => $name, 'mime' => $mime]); + $msg = (string)trans('validation.file_invalid_mime', ['name' => $name, 'mime' => $mime]); $this->errors->add('attachments', $msg); Log::error($msg); @@ -339,7 +338,7 @@ class AttachmentHelper implements AttachmentHelperInterface * * @codeCoverageIgnore * - * @param UploadedFile $file + * @param UploadedFile $file * * @return bool */ @@ -349,7 +348,7 @@ class AttachmentHelper implements AttachmentHelperInterface $name = e($file->getClientOriginalName()); $result = true; if ($size > $this->maxUploadSize) { - $msg = (string) trans('validation.file_too_large', ['name' => $name]); + $msg = (string)trans('validation.file_too_large', ['name' => $name]); $this->errors->add('attachments', $msg); Log::error($msg); @@ -362,8 +361,8 @@ class AttachmentHelper implements AttachmentHelperInterface /** * Check if a model already has this file attached. * - * @param UploadedFile $file - * @param Model $model + * @param UploadedFile $file + * @param Model $model * * @return bool */ @@ -373,15 +372,16 @@ class AttachmentHelper implements AttachmentHelperInterface $name = $file->getClientOriginalName(); $class = get_class($model); $count = 0; - if (PiggyBank::class === $class) { + // ignore lines about polymorphic calls. + if ($model instanceof PiggyBank) { $count = $model->account->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(); } - if (PiggyBank::class !== $class) { - $count = $model->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(); + if ($model instanceof PiggyBank) { + $count = $model->user->attachments()->where('md5', $md5)->where('attachable_id', $model->id)->where('attachable_type', $class)->count(); // @phpstan-ignore-line } $result = false; if ($count > 0) { - $msg = (string) trans('validation.file_already_attached', ['name' => $name]); + $msg = (string)trans('validation.file_already_attached', ['name' => $name]); $this->errors->add('attachments', $msg); Log::error($msg); $result = true; diff --git a/app/Helpers/Attachments/AttachmentHelperInterface.php b/app/Helpers/Attachments/AttachmentHelperInterface.php index b2fb2ae091..1b6173fc8a 100644 --- a/app/Helpers/Attachments/AttachmentHelperInterface.php +++ b/app/Helpers/Attachments/AttachmentHelperInterface.php @@ -1,4 +1,5 @@ count() > 0) { + $accountIds = $accounts->pluck('id')->toArray(); + $this->query->whereNotIn('source.account_id', $accountIds); + $this->query->whereNotIn('destination.account_id', $accountIds); + + app('log')->debug(sprintf('GroupCollector: excludeAccounts: %s', implode(', ', $accountIds))); + } + + return $this; + } /** * These accounts must not be destination accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -56,7 +75,7 @@ trait AccountCollection /** * These accounts must not be source accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -75,7 +94,7 @@ trait AccountCollection /** * Define which accounts can be part of the source and destination transactions. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -98,7 +117,7 @@ trait AccountCollection /** * Both source AND destination must be in this list of accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -121,7 +140,7 @@ trait AccountCollection /** * Define which accounts can be part of the source and destination transactions. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -137,10 +156,33 @@ trait AccountCollection return $this; } + /** + * Define which accounts can NOT be part of the source and destination transactions. + * + * @param Collection $accounts + * + * @return GroupCollectorInterface + */ + public function setNotAccounts(Collection $accounts): GroupCollectorInterface + { + if ($accounts->count() > 0) { + $accountIds = $accounts->pluck('id')->toArray(); + $this->query->where( + static function (EloquentBuilder $query) use ($accountIds) { + $query->whereNotIn('source.account_id', $accountIds); + $query->whereNotIn('destination.account_id', $accountIds); + } + ); + //app('log')->debug(sprintf('GroupCollector: setAccounts: %s', implode(', ', $accountIds))); + } + + return $this; + } + /** * Define which accounts can be part of the source and destination transactions. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -159,7 +201,7 @@ trait AccountCollection /** * Either account can be set, but NOT both. This effectively excludes internal transfers. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ diff --git a/app/Helpers/Collector/Extensions/AmountCollection.php b/app/Helpers/Collector/Extensions/AmountCollection.php index 99fe7d1742..bf4d9af521 100644 --- a/app/Helpers/Collector/Extensions/AmountCollection.php +++ b/app/Helpers/Collector/Extensions/AmountCollection.php @@ -32,11 +32,10 @@ use Illuminate\Database\Eloquent\Builder as EloquentBuilder; */ trait AmountCollection { - /** * Get transactions with a specific amount. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ @@ -51,10 +50,24 @@ trait AmountCollection return $this; } + /** + * @inheritDoc + */ + public function amountIsNot(string $amount): GroupCollectorInterface + { + $this->query->where( + static function (EloquentBuilder $q) use ($amount) { + $q->where('source.amount', '!=', app('steam')->negative($amount)); + } + ); + + return $this; + } + /** * Get transactions where the amount is less than. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ @@ -72,7 +85,7 @@ trait AmountCollection /** * Get transactions where the amount is more than. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ @@ -90,7 +103,7 @@ trait AmountCollection /** * Get transactions with a specific foreign amount. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ @@ -106,10 +119,29 @@ trait AmountCollection return $this; } + /** + * Get transactions with a specific foreign amount. + * + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function foreignAmountIsNot(string $amount): GroupCollectorInterface + { + $this->query->where( + static function (EloquentBuilder $q) use ($amount) { + $q->whereNull('source.foreign_amount'); + $q->orWhere('source.foreign_amount', '!=', app('steam')->negative($amount)); + } + ); + + return $this; + } + /** * Get transactions where the amount is less than. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ @@ -128,7 +160,7 @@ trait AmountCollection /** * Get transactions where the amount is more than. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ diff --git a/app/Helpers/Collector/Extensions/AttachmentCollection.php b/app/Helpers/Collector/Extensions/AttachmentCollection.php index e9ce1bbd4a..bc6b36f002 100644 --- a/app/Helpers/Collector/Extensions/AttachmentCollection.php +++ b/app/Helpers/Collector/Extensions/AttachmentCollection.php @@ -37,7 +37,7 @@ use Log; trait AttachmentCollection { /** - * @param string $name + * @param string $name * @return GroupCollectorInterface */ public function attachmentNameContains(string $name): GroupCollectorInterface @@ -49,7 +49,10 @@ trait AttachmentCollection foreach ($object['transactions'] as $transaction) { /** @var array $attachment */ foreach ($transaction['attachments'] as $attachment) { - $result = str_contains(strtolower($attachment['filename']), strtolower($name)) || str_contains(strtolower($attachment['title']), strtolower($name)); + $result = str_contains(strtolower($attachment['filename']), strtolower($name)) || str_contains( + strtolower($attachment['title']), + strtolower($name) + ); if (true === $result) { return true; } @@ -111,10 +114,10 @@ trait AttachmentCollection } /** - * @param string $name + * @param string $name * @return GroupCollectorInterface */ - public function attachmentNameEnds(string $name): GroupCollectorInterface + public function attachmentNameDoesNotContain(string $name): GroupCollectorInterface { $this->hasAttachments(); $this->withAttachmentInformation(); @@ -123,7 +126,10 @@ trait AttachmentCollection foreach ($object['transactions'] as $transaction) { /** @var array $attachment */ foreach ($transaction['attachments'] as $attachment) { - $result = str_ends_with(strtolower($attachment['filename']), strtolower($name)) || str_ends_with(strtolower($attachment['title']), strtolower($name)); + $result = !str_contains(strtolower($attachment['filename']), strtolower($name)) && !str_contains( + strtolower($attachment['title']), + strtolower($name) + ); if (true === $result) { return true; } @@ -137,7 +143,94 @@ trait AttachmentCollection } /** - * @param string $name + * @param string $name + * @return GroupCollectorInterface + */ + public function attachmentNameDoesNotEnd(string $name): GroupCollectorInterface + { + $this->hasAttachments(); + $this->withAttachmentInformation(); + $filter = function (int $index, array $object) use ($name): bool { + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + /** @var array $attachment */ + foreach ($transaction['attachments'] as $attachment) { + $result = !str_ends_with(strtolower($attachment['filename']), strtolower($name)) && !str_ends_with( + strtolower($attachment['title']), + strtolower($name) + ); + if (true === $result) { + return true; + } + } + } + return false; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $name + * @return GroupCollectorInterface + */ + public function attachmentNameDoesNotStart(string $name): GroupCollectorInterface + { + $this->hasAttachments(); + $this->withAttachmentInformation(); + $filter = function (int $index, array $object) use ($name): bool { + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + /** @var array $attachment */ + foreach ($transaction['attachments'] as $attachment) { + $result = !str_starts_with(strtolower($attachment['filename']), strtolower($name)) && !str_starts_with( + strtolower($attachment['title']), + strtolower($name) + ); + if (true === $result) { + return true; + } + } + } + return false; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $name + * @return GroupCollectorInterface + */ + public function attachmentNameEnds(string $name): GroupCollectorInterface + { + $this->hasAttachments(); + $this->withAttachmentInformation(); + $filter = function (int $index, array $object) use ($name): bool { + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + /** @var array $attachment */ + foreach ($transaction['attachments'] as $attachment) { + $result = str_ends_with(strtolower($attachment['filename']), strtolower($name)) || str_ends_with( + strtolower($attachment['title']), + strtolower($name) + ); + if (true === $result) { + return true; + } + } + } + return false; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $name * @return GroupCollectorInterface */ public function attachmentNameIs(string $name): GroupCollectorInterface @@ -163,10 +256,10 @@ trait AttachmentCollection } /** - * @param string $name + * @param string $name * @return GroupCollectorInterface */ - public function attachmentNameStarts(string $name): GroupCollectorInterface + public function attachmentNameIsNot(string $name): GroupCollectorInterface { $this->hasAttachments(); $this->withAttachmentInformation(); @@ -175,7 +268,7 @@ trait AttachmentCollection foreach ($object['transactions'] as $transaction) { /** @var array $attachment */ foreach ($transaction['attachments'] as $attachment) { - $result = str_starts_with(strtolower($attachment['filename']), strtolower($name)) || str_starts_with(strtolower($attachment['title']), strtolower($name)); + $result = $attachment['filename'] !== $name && $attachment['title'] !== $name; if (true === $result) { return true; } @@ -189,7 +282,36 @@ trait AttachmentCollection } /** - * @param string $value + * @param string $name + * @return GroupCollectorInterface + */ + public function attachmentNameStarts(string $name): GroupCollectorInterface + { + $this->hasAttachments(); + $this->withAttachmentInformation(); + $filter = function (int $index, array $object) use ($name): bool { + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + /** @var array $attachment */ + foreach ($transaction['attachments'] as $attachment) { + $result = str_starts_with(strtolower($attachment['filename']), strtolower($name)) || str_starts_with( + strtolower($attachment['title']), + strtolower($name) + ); + if (true === $result) { + return true; + } + } + } + return false; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $value * @return GroupCollectorInterface */ public function attachmentNotesAre(string $value): GroupCollectorInterface @@ -201,9 +323,9 @@ trait AttachmentCollection foreach ($object['transactions'] as $transaction) { /** @var array $attachment */ foreach ($transaction['attachments'] as $attachment) { - /** @var Attachment $object */ + /** @var Attachment|null $object */ $object = auth()->user()->attachments()->find($attachment['id']); - $notes = (string) $object->notes()?->first()?->text; + $notes = (string)$object?->notes()->first()?->text; return $notes !== '' && $notes === $value; } } @@ -215,7 +337,33 @@ trait AttachmentCollection } /** - * @param string $value + * @param string $value + * @return GroupCollectorInterface + */ + public function attachmentNotesAreNot(string $value): GroupCollectorInterface + { + $this->hasAttachments(); + $this->withAttachmentInformation(); + $filter = function (int $index, array $object) use ($value): bool { + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + /** @var array $attachment */ + foreach ($transaction['attachments'] as $attachment) { + /** @var Attachment|null $object */ + $object = auth()->user()->attachments()->find($attachment['id']); + $notes = (string)$object?->notes()->first()?->text; + return $notes !== '' && $notes !== $value; + } + } + return false; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $value * @return GroupCollectorInterface */ public function attachmentNotesContains(string $value): GroupCollectorInterface @@ -227,9 +375,9 @@ trait AttachmentCollection foreach ($object['transactions'] as $transaction) { /** @var array $attachment */ foreach ($transaction['attachments'] as $attachment) { - /** @var Attachment $object */ + /** @var Attachment|null $object */ $object = auth()->user()->attachments()->find($attachment['id']); - $notes = (string) $object->notes()?->first()?->text; + $notes = (string)$object?->notes()->first()?->text; return $notes !== '' && str_contains(strtolower($notes), strtolower($value)); } } @@ -241,7 +389,85 @@ trait AttachmentCollection } /** - * @param string $value + * @param string $value + * @return GroupCollectorInterface + */ + public function attachmentNotesDoNotContain(string $value): GroupCollectorInterface + { + $this->hasAttachments(); + $this->withAttachmentInformation(); + $filter = function (int $index, array $object) use ($value): bool { + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + /** @var array $attachment */ + foreach ($transaction['attachments'] as $attachment) { + /** @var Attachment|null $object */ + $object = auth()->user()->attachments()->find($attachment['id']); + $notes = (string)$object?->notes()->first()?->text; + return $notes !== '' && !str_contains(strtolower($notes), strtolower($value)); + } + } + return false; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $value + * @return GroupCollectorInterface + */ + public function attachmentNotesDoNotEnd(string $value): GroupCollectorInterface + { + $this->hasAttachments(); + $this->withAttachmentInformation(); + $filter = function (int $index, array $object) use ($value): bool { + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + /** @var array $attachment */ + foreach ($transaction['attachments'] as $attachment) { + /** @var Attachment|null $object */ + $object = auth()->user()->attachments()->find($attachment['id']); + $notes = (string)$object?->notes()->first()?->text; + return $notes !== '' && !str_ends_with(strtolower($notes), strtolower($value)); + } + } + return false; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $value + * @return GroupCollectorInterface + */ + public function attachmentNotesDoNotStart(string $value): GroupCollectorInterface + { + $this->hasAttachments(); + $this->withAttachmentInformation(); + $filter = function (int $index, array $object) use ($value): bool { + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + /** @var array $attachment */ + foreach ($transaction['attachments'] as $attachment) { + /** @var Attachment|null $object */ + $object = auth()->user()->attachments()->find($attachment['id']); + $notes = (string)$object?->notes()->first()?->text; + return $notes !== '' && !str_starts_with(strtolower($notes), strtolower($value)); + } + } + return false; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $value * @return GroupCollectorInterface */ public function attachmentNotesEnds(string $value): GroupCollectorInterface @@ -253,9 +479,9 @@ trait AttachmentCollection foreach ($object['transactions'] as $transaction) { /** @var array $attachment */ foreach ($transaction['attachments'] as $attachment) { - /** @var Attachment $object */ + /** @var Attachment|null $object */ $object = auth()->user()->attachments()->find($attachment['id']); - $notes = (string) $object->notes()?->first()?->text; + $notes = (string)$object?->notes()->first()?->text; return $notes !== '' && str_ends_with(strtolower($notes), strtolower($value)); } } @@ -267,7 +493,7 @@ trait AttachmentCollection } /** - * @param string $value + * @param string $value * @return GroupCollectorInterface */ public function attachmentNotesStarts(string $value): GroupCollectorInterface @@ -279,9 +505,9 @@ trait AttachmentCollection foreach ($object['transactions'] as $transaction) { /** @var array $attachment */ foreach ($transaction['attachments'] as $attachment) { - /** @var Attachment $object */ + /** @var Attachment|null $object */ $object = auth()->user()->attachments()->find($attachment['id']); - $notes = (string) $object->notes()?->first()?->text; + $notes = (string)$object?->notes()->first()?->text; return $notes !== '' && str_starts_with(strtolower($notes), strtolower($value)); } } diff --git a/app/Helpers/Collector/Extensions/CollectorProperties.php b/app/Helpers/Collector/Extensions/CollectorProperties.php index 39c8e50b6a..a76ed1b602 100644 --- a/app/Helpers/Collector/Extensions/CollectorProperties.php +++ b/app/Helpers/Collector/Extensions/CollectorProperties.php @@ -32,8 +32,8 @@ use Illuminate\Database\Eloquent\Relations\HasMany; */ trait CollectorProperties { + const TEST = 'Test'; private array $fields; - private array $stringFields; private bool $hasAccountInfo; private bool $hasBillInformation; private bool $hasBudgetInformation; @@ -47,6 +47,7 @@ trait CollectorProperties private ?int $page; private array $postFilters; private HasMany $query; + private array $stringFields; private int $total; private ?User $user; } diff --git a/app/Helpers/Collector/Extensions/MetaCollection.php b/app/Helpers/Collector/Extensions/MetaCollection.php index 99bb44d16a..dff810fd7f 100644 --- a/app/Helpers/Collector/Extensions/MetaCollection.php +++ b/app/Helpers/Collector/Extensions/MetaCollection.php @@ -30,6 +30,7 @@ use FireflyIII\Models\Budget; use FireflyIII\Models\Category; use FireflyIII\Models\Tag; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Query\JoinClause; use Illuminate\Support\Collection; @@ -38,6 +39,200 @@ use Illuminate\Support\Collection; */ trait MetaCollection { + /** + * @inheritDoc + */ + public function excludeBills(Collection $bills): GroupCollectorInterface + { + $this->withBillInformation(); + $this->query->where(static function (EloquentBuilder $q1) use ($bills) { + $q1->whereNotIn('transaction_journals.bill_id', $bills->pluck('id')->toArray()); + $q1->orWhereNull('transaction_journals.bill_id'); + }); + + return $this; + } + + /** + * Will include bill name + ID, if any. + * + * @return GroupCollectorInterface + */ + public function withBillInformation(): GroupCollectorInterface + { + if (false === $this->hasBillInformation) { + // join bill table + $this->query->leftJoin('bills', 'bills.id', '=', 'transaction_journals.bill_id'); + // add fields + $this->fields[] = 'bills.id as bill_id'; + $this->fields[] = 'bills.name as bill_name'; + $this->hasBillInformation = true; + } + + return $this; + } + + /** + * Exclude a specific budget. + * + * @param Budget $budget + * + * @return GroupCollectorInterface + */ + public function excludeBudget(Budget $budget): GroupCollectorInterface + { + $this->withBudgetInformation(); + + $this->query->where(static function (EloquentBuilder $q2) use ($budget) { + $q2->where('budgets.id', '!=', $budget->id); + $q2->orWhereNull('budgets.id'); + }); + + return $this; + } + + /** + * Will include budget ID + name, if any. + * + * @return GroupCollectorInterface + */ + public function withBudgetInformation(): GroupCollectorInterface + { + if (false === $this->hasBudgetInformation) { + // join link table + $this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); + // join cat table + $this->query->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id'); + // add fields + $this->fields[] = 'budgets.id as budget_id'; + $this->fields[] = 'budgets.name as budget_name'; + $this->hasBudgetInformation = true; + } + + return $this; + } + + /** + * @inheritDoc + */ + public function excludeBudgets(Collection $budgets): GroupCollectorInterface + { + if ($budgets->count() > 0) { + $this->withBudgetInformation(); + $this->query->where(static function (EloquentBuilder $q1) use ($budgets) { + $q1->whereNotIn('budgets.id', $budgets->pluck('id')->toArray()); + $q1->orWhereNull('budgets.id'); + }); + } + + return $this; + } + + /** + * @inheritDoc + */ + public function excludeCategories(Collection $categories): GroupCollectorInterface + { + if ($categories->count() > 0) { + $this->withCategoryInformation(); + $this->query->where(static function (EloquentBuilder $q1) use ($categories) { + $q1->whereNotIn('categories.id', $categories->pluck('id')->toArray()); + $q1->orWhereNull('categories.id'); + }); + } + + return $this; + } + + /** + * Will include category ID + name, if any. + * + * @return GroupCollectorInterface + */ + public function withCategoryInformation(): GroupCollectorInterface + { + if (false === $this->hasCatInformation) { + // join link table + $this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); + // join cat table + $this->query->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id'); + // add fields + $this->fields[] = 'categories.id as category_id'; + $this->fields[] = 'categories.name as category_name'; + $this->hasCatInformation = true; + } + + return $this; + } + + /** + * Exclude a specific category. + * + * @param Category $category + * + * @return GroupCollectorInterface + */ + public function excludeCategory(Category $category): GroupCollectorInterface + { + $this->withCategoryInformation(); + + $this->query->where(static function (EloquentBuilder $q2) use ($category) { + $q2->where('categories.id', '!=', $category->id); + $q2->orWhereNull('categories.id'); + }); + + return $this; + } + + /** + * @inheritDoc + */ + public function excludeExternalId(string $externalId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'external_id'); + $this->query->where('journal_meta.data', '!=', sprintf('%s', json_encode($externalId))); + + return $this; + } + + /** + * @inheritDoc + */ + public function excludeExternalUrl(string $url): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'external_url'); + $this->query->where('journal_meta.data', '!=', json_encode($url)); + + return $this; + } + + /** + * @inheritDoc + */ + public function excludeInternalReference(string $internalReference): GroupCollectorInterface + { + $this->joinMetaDataTables(); + + $this->query->where('journal_meta.name', '=', 'internal_reference'); + $this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s%%', $internalReference)); + + return $this; + } + + /** + * @inheritDoc + */ + public function excludeRecurrenceId(string $recurringId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'recurrence_id'); + $this->query->where('journal_meta.data', '!=', sprintf('%s', json_encode($recurringId))); + + return $this; + } + /** * @inheritDoc */ @@ -63,6 +258,42 @@ trait MetaCollection } } + /** + * @inheritDoc + */ + public function externalIdDoesNotContain(string $externalId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'external_id'); + $this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s%%', $externalId)); + + return $this; + } + + /** + * @inheritDoc + */ + public function externalIdDoesNotEnd(string $externalId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'external_id'); + $this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s"', $externalId)); + + return $this; + } + + /** + * @inheritDoc + */ + public function externalIdDoesNotStart(string $externalId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'external_id'); + $this->query->where('journal_meta.data', 'LIKE', sprintf('"%s%%', $externalId)); + + return $this; + } + /** * @inheritDoc */ @@ -88,7 +319,7 @@ trait MetaCollection } /** - * @param string $url + * @param string $url * @return GroupCollectorInterface */ public function externalUrlContains(string $url): GroupCollectorInterface @@ -103,7 +334,54 @@ trait MetaCollection } /** - * @param string $url + * @param string $url + * @return GroupCollectorInterface + */ + public function externalUrlDoesNotContain(string $url): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $url = json_encode($url); + $url = str_replace('\\', '\\\\', trim($url, '"')); + $this->query->where('journal_meta.name', '=', 'external_url'); + $this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s%%', $url)); + + return $this; + } + + /** + * @param string $url + * @return GroupCollectorInterface + */ + public function externalUrlDoesNotEnd(string $url): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $url = json_encode($url); + $url = str_replace('\\', '\\\\', ltrim($url, '"')); + $this->query->where('journal_meta.name', '=', 'external_url'); + $this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s', $url)); + + return $this; + } + + /** + * @param string $url + * @return GroupCollectorInterface + */ + public function externalUrlDoesNotStart(string $url): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $url = json_encode($url); + $url = str_replace('\\', '\\\\', rtrim($url, '"')); + //var_dump($url); + + $this->query->where('journal_meta.name', '=', 'external_url'); + $this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%s%%', $url)); + + return $this; + } + + /** + * @param string $url * @return GroupCollectorInterface */ public function externalUrlEnds(string $url): GroupCollectorInterface @@ -118,7 +396,7 @@ trait MetaCollection } /** - * @param string $url + * @param string $url * @return GroupCollectorInterface */ public function externalUrlStarts(string $url): GroupCollectorInterface @@ -190,6 +468,42 @@ trait MetaCollection return $this; } + /** + * @inheritDoc + */ + public function internalReferenceDoesNotContain(string $externalId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'internal_reference'); + $this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s%%', $externalId)); + + return $this; + } + + /** + * @inheritDoc + */ + public function internalReferenceDoesNotEnd(string $externalId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'internal_reference'); + $this->query->where('journal_meta.data', 'NOT LIKE', sprintf('%%%s"', $externalId)); + + return $this; + } + + /** + * @inheritDoc + */ + public function internalReferenceDoesNotStart(string $externalId): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'internal_reference'); + $this->query->where('journal_meta.data', 'LIKE', sprintf('"%s%%', $externalId)); + + return $this; + } + /** * @inheritDoc */ @@ -215,7 +529,7 @@ trait MetaCollection } /** - * @param string $value + * @param string $value * * @return GroupCollectorInterface */ @@ -251,7 +565,55 @@ trait MetaCollection } /** - * @param string $value + * @param string $value + * + * @return GroupCollectorInterface + */ + public function notesDoNotContain(string $value): GroupCollectorInterface + { + $this->withNotes(); + $this->query->where(static function (Builder $q) use ($value) { + $q->whereNull('notes.text'); + $q->orWhere('notes.text', 'NOT LIKE', sprintf('%%%s%%', $value)); + }); + + return $this; + } + + /** + * @param string $value + * + * @return GroupCollectorInterface + */ + public function notesDontEndWith(string $value): GroupCollectorInterface + { + $this->withNotes(); + $this->query->where(static function (Builder $q) use ($value) { + $q->whereNull('notes.text'); + $q->orWhere('notes.text', 'NOT LIKE', sprintf('%%%s', $value)); + }); + + return $this; + } + + /** + * @param string $value + * + * @return GroupCollectorInterface + */ + public function notesDontStartWith(string $value): GroupCollectorInterface + { + $this->withNotes(); + $this->query->where(static function (Builder $q) use ($value) { + $q->whereNull('notes.text'); + $q->orWhere('notes.text', 'NOT LIKE', sprintf('%s%%', $value)); + }); + + return $this; + } + + /** + * @param string $value * * @return GroupCollectorInterface */ @@ -264,7 +626,7 @@ trait MetaCollection } /** - * @param string $value + * @param string $value * * @return GroupCollectorInterface */ @@ -277,7 +639,23 @@ trait MetaCollection } /** - * @param string $value + * @param string $value + * + * @return GroupCollectorInterface + */ + public function notesExactlyNot(string $value): GroupCollectorInterface + { + $this->withNotes(); + $this->query->where(static function (Builder $q) use ($value) { + $q->whereNull('notes.text'); + $q->orWhere('notes.text', '!=', sprintf('%s', $value)); + }); + + return $this; + } + + /** + * @param string $value * * @return GroupCollectorInterface */ @@ -292,7 +670,7 @@ trait MetaCollection /** * Limit the search to a specific bill. * - * @param Bill $bill + * @param Bill $bill * * @return GroupCollectorInterface */ @@ -304,29 +682,10 @@ trait MetaCollection return $this; } - /** - * Will include bill name + ID, if any. - * - * @return GroupCollectorInterface - */ - public function withBillInformation(): GroupCollectorInterface - { - if (false === $this->hasBillInformation) { - // join bill table - $this->query->leftJoin('bills', 'bills.id', '=', 'transaction_journals.bill_id'); - // add fields - $this->fields[] = 'bills.id as bill_id'; - $this->fields[] = 'bills.name as bill_name'; - $this->hasBillInformation = true; - } - - return $this; - } - /** * Limit the search to a specific set of bills. * - * @param Collection $bills + * @param Collection $bills * * @return GroupCollectorInterface */ @@ -341,7 +700,7 @@ trait MetaCollection /** * Limit the search to a specific budget. * - * @param Budget $budget + * @param Budget $budget * * @return GroupCollectorInterface */ @@ -353,31 +712,10 @@ trait MetaCollection return $this; } - /** - * Will include budget ID + name, if any. - * - * @return GroupCollectorInterface - */ - public function withBudgetInformation(): GroupCollectorInterface - { - if (false === $this->hasBudgetInformation) { - // join link table - $this->query->leftJoin('budget_transaction_journal', 'budget_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); - // join cat table - $this->query->leftJoin('budgets', 'budget_transaction_journal.budget_id', '=', 'budgets.id'); - // add fields - $this->fields[] = 'budgets.id as budget_id'; - $this->fields[] = 'budgets.name as budget_name'; - $this->hasBudgetInformation = true; - } - - return $this; - } - /** * Limit the search to a specific set of budgets. * - * @param Collection $budgets + * @param Collection $budgets * * @return GroupCollectorInterface */ @@ -394,7 +732,7 @@ trait MetaCollection /** * Limit the search to a specific bunch of categories. * - * @param Collection $categories + * @param Collection $categories * * @return GroupCollectorInterface */ @@ -408,31 +746,10 @@ trait MetaCollection return $this; } - /** - * Will include category ID + name, if any. - * - * @return GroupCollectorInterface - */ - public function withCategoryInformation(): GroupCollectorInterface - { - if (false === $this->hasCatInformation) { - // join link table - $this->query->leftJoin('category_transaction_journal', 'category_transaction_journal.transaction_journal_id', '=', 'transaction_journals.id'); - // join cat table - $this->query->leftJoin('categories', 'category_transaction_journal.category_id', '=', 'categories.id'); - // add fields - $this->fields[] = 'categories.id as category_id'; - $this->fields[] = 'categories.name as category_name'; - $this->hasCatInformation = true; - } - - return $this; - } - /** * Limit the search to a specific category. * - * @param Category $category + * @param Category $category * * @return GroupCollectorInterface */ @@ -493,10 +810,23 @@ trait MetaCollection return $this; } + /** + * @inheritDoc + */ + public function setSepaCT(string $sepaCT): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'sepa_ct_id'); + $this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($sepaCT))); + $this->query->whereNull('journal_meta.deleted_at'); + + return $this; + } + /** * Limit results to a specific tag. * - * @param Tag $tag + * @param Tag $tag * * @return GroupCollectorInterface */ @@ -511,7 +841,7 @@ trait MetaCollection /** * Limit results to a specific set of tags. * - * @param Collection $tags + * @param Collection $tags * * @return GroupCollectorInterface */ @@ -526,7 +856,7 @@ trait MetaCollection /** * Without tags * - * @param Collection $tags + * @param Collection $tags * * @return GroupCollectorInterface */ @@ -539,7 +869,7 @@ trait MetaCollection $filter = function (int $index, array $object) use ($list): bool { foreach ($object['transactions'] as $transaction) { foreach ($transaction['tags'] as $tag) { - if (in_array($tag['name'], $list)) { + if (in_array($tag['name'], $list, true)) { return false; } } @@ -602,6 +932,18 @@ trait MetaCollection return $this; } + /** + * @inheritDoc + */ + public function withExternalId(): GroupCollectorInterface + { + $this->joinMetaDataTables(); + $this->query->where('journal_meta.name', '=', 'external_id'); + $this->query->whereNotNull('journal_meta.data'); + + return $this; + } + /** * @inheritDoc */ @@ -652,6 +994,27 @@ trait MetaCollection return $this; } + /** + * @inheritDoc + */ + public function withoutExternalId(): GroupCollectorInterface + { + $this->joinMetaDataTables(); + // TODO not sure if this will work properly. + $this->query->where(function (Builder $q1) { + $q1->where(function (Builder $q2) { + $q2->where('journal_meta.name', '=', 'external_id'); + $q2->whereNull('journal_meta.data'); + })->orWhere(function (Builder $q3) { + $q3->where('journal_meta.name', '!=', 'external_id'); + })->orWhere(function (Builder $q4) { + $q4->whereNull('journal_meta.name'); + }); + }); + + return $this; + } + /** * @inheritDoc */ @@ -699,17 +1062,4 @@ trait MetaCollection return $this; } - - /** - * @inheritDoc - */ - public function setSepaCT(string $sepaCT): GroupCollectorInterface - { - $this->joinMetaDataTables(); - $this->query->where('journal_meta.name', '=', 'sepa_ct_id'); - $this->query->where('journal_meta.data', '=', sprintf('%s', json_encode($sepaCT))); - $this->query->whereNull('journal_meta.deleted_at'); - - return $this; - } } diff --git a/app/Helpers/Collector/Extensions/TimeCollection.php b/app/Helpers/Collector/Extensions/TimeCollection.php index cca0a7855d..31bbd13f03 100644 --- a/app/Helpers/Collector/Extensions/TimeCollection.php +++ b/app/Helpers/Collector/Extensions/TimeCollection.php @@ -33,7 +33,7 @@ use FireflyIII\Helpers\Collector\GroupCollectorInterface; trait TimeCollection { /** - * @param string $day + * @param string $day * @return GroupCollectorInterface */ public function dayAfter(string $day): GroupCollectorInterface @@ -43,7 +43,7 @@ trait TimeCollection } /** - * @param string $day + * @param string $day * @return GroupCollectorInterface */ public function dayBefore(string $day): GroupCollectorInterface @@ -53,7 +53,7 @@ trait TimeCollection } /** - * @param string $day + * @param string $day * @return GroupCollectorInterface */ public function dayIs(string $day): GroupCollectorInterface @@ -63,22 +63,39 @@ trait TimeCollection } /** - * @param string $day - * @param string $field + * @param string $day * @return GroupCollectorInterface */ - public function metaDayAfter(string $day, string $field): GroupCollectorInterface + public function dayIsNot(string $day): GroupCollectorInterface { + $this->query->whereDay('transaction_journals.date', '!=', $day); + return $this; + } + + /** + * @param Carbon $start + * @param Carbon $end + * @param string $field + * @return GroupCollectorInterface + */ + public function excludeMetaDateRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface + { + if ($end < $start) { + [$start, $end] = [$end, $start]; + } + $end = clone $end; // this is so weird, but it works if $end and $start secretly point to the same object. + $end->endOfDay(); + $start->startOfDay(); $this->withMetaDate($field); - $filter = function (int $index, array $object) use ($field, $day): bool { + + $filter = function (int $index, array $object) use ($field, $start, $end): bool { foreach ($object['transactions'] as $transaction) { - if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon - ) { - return $transaction[$field]->day >= (int) $day; + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon) { + return $transaction[$field]->lt($start) || $transaction[$field]->gt($end); } } - return true; + return false; }; $this->postFilters[] = $filter; @@ -98,8 +115,67 @@ trait TimeCollection } /** - * @param string $day - * @param string $field + * @param Carbon $start + * @param Carbon $end + * @param string $field + * @return GroupCollectorInterface + */ + public function excludeObjectRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface + { + $after = $start->format('Y-m-d 00:00:00'); + $before = $end->format('Y-m-d 23:59:59'); + + $this->query->where(sprintf('transaction_journals.%s', $field), '<', $after); + $this->query->orWhere(sprintf('transaction_journals.%s', $field), '>', $before); + + return $this; + } + + /** + * @param Carbon $start + * @param Carbon $end + * @return GroupCollectorInterface + */ + public function excludeRange(Carbon $start, Carbon $end): GroupCollectorInterface + { + if ($end < $start) { + [$start, $end] = [$end, $start]; + } + $startStr = $start->format('Y-m-d 00:00:00'); + $endStr = $end->format('Y-m-d 23:59:59'); + + $this->query->where('transaction_journals.date', '<', $startStr); + $this->query->orWhere('transaction_journals.date', '>', $endStr); + + return $this; + } + + /** + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayAfter(string $day, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $day): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $transaction[$field]->day >= (int)$day; + } + } + + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function metaDayBefore(string $day, string $field): GroupCollectorInterface @@ -109,7 +185,7 @@ trait TimeCollection foreach ($object['transactions'] as $transaction) { if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return $transaction[$field]->day <= (int) $day; + return $transaction[$field]->day <= (int)$day; } } @@ -121,8 +197,8 @@ trait TimeCollection } /** - * @param string $day - * @param string $field + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function metaDayIs(string $day, string $field): GroupCollectorInterface @@ -132,7 +208,7 @@ trait TimeCollection foreach ($object['transactions'] as $transaction) { if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return (int) $day === $transaction[$field]->day; + return (int)$day === $transaction[$field]->day; } } @@ -143,8 +219,30 @@ trait TimeCollection } /** - * @param string $month - * @param string $field + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayIsNot(string $day, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $day): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return (int)$day !== $transaction[$field]->day; + } + } + + return false; + }; + $this->postFilters[] = $filter; + return $this; + } + + /** + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function metaMonthAfter(string $month, string $field): GroupCollectorInterface @@ -154,7 +252,7 @@ trait TimeCollection foreach ($object['transactions'] as $transaction) { if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return $transaction[$field]->month >= (int) $month; + return $transaction[$field]->month >= (int)$month; } } @@ -166,8 +264,8 @@ trait TimeCollection } /** - * @param string $month - * @param string $field + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function metaMonthBefore(string $month, string $field): GroupCollectorInterface @@ -177,7 +275,7 @@ trait TimeCollection foreach ($object['transactions'] as $transaction) { if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return $transaction[$field]->month <= (int) $month; + return $transaction[$field]->month <= (int)$month; } } @@ -189,8 +287,8 @@ trait TimeCollection } /** - * @param string $month - * @param string $field + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function metaMonthIs(string $month, string $field): GroupCollectorInterface @@ -200,7 +298,7 @@ trait TimeCollection foreach ($object['transactions'] as $transaction) { if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return (int) $month === $transaction[$field]->month; + return (int)$month === $transaction[$field]->month; } } @@ -211,8 +309,30 @@ trait TimeCollection } /** - * @param string $year - * @param string $field + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function metaMonthIsNot(string $month, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $month): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return (int)$month !== $transaction[$field]->month; + } + } + + return false; + }; + $this->postFilters[] = $filter; + return $this; + } + + /** + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function metaYearAfter(string $year, string $field): GroupCollectorInterface @@ -222,7 +342,7 @@ trait TimeCollection foreach ($object['transactions'] as $transaction) { if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return $transaction[$field]->year >= (int) $year; + return $transaction[$field]->year >= (int)$year; } } @@ -234,8 +354,8 @@ trait TimeCollection } /** - * @param string $year - * @param string $field + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function metaYearBefore(string $year, string $field): GroupCollectorInterface @@ -245,7 +365,7 @@ trait TimeCollection foreach ($object['transactions'] as $transaction) { if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return $transaction[$field]->year <= (int) $year; + return $transaction[$field]->year <= (int)$year; } } @@ -257,8 +377,8 @@ trait TimeCollection } /** - * @param string $year - * @param string $field + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function metaYearIs(string $year, string $field): GroupCollectorInterface @@ -268,7 +388,7 @@ trait TimeCollection foreach ($object['transactions'] as $transaction) { if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon ) { - return $year === (string) $transaction[$field]->year; + return $year === (string)$transaction[$field]->year; } } @@ -280,29 +400,49 @@ trait TimeCollection } /** - * @param string $month + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function metaYearIsNot(string $year, string $field): GroupCollectorInterface + { + $this->withMetaDate($field); + $filter = function (int $index, array $object) use ($field, $year): bool { + foreach ($object['transactions'] as $transaction) { + if (array_key_exists($field, $transaction) && $transaction[$field] instanceof Carbon + ) { + return $year !== (string)$transaction[$field]->year; + } + } + return true; + }; + $this->postFilters[] = $filter; + + return $this; + } + + /** + * @param string $month * @return GroupCollectorInterface */ public function monthAfter(string $month): GroupCollectorInterface { $this->query->whereMonth('transaction_journals.date', '>=', $month); return $this; - } /** - * @param string $month + * @param string $month * @return GroupCollectorInterface */ public function monthBefore(string $month): GroupCollectorInterface { $this->query->whereMonth('transaction_journals.date', '<=', $month); return $this; - } /** - * @param string $month + * @param string $month * @return GroupCollectorInterface */ public function monthIs(string $month): GroupCollectorInterface @@ -312,8 +452,18 @@ trait TimeCollection } /** - * @param string $day - * @param string $field + * @param string $month + * @return GroupCollectorInterface + */ + public function monthIsNot(string $month): GroupCollectorInterface + { + $this->query->whereMonth('transaction_journals.date', '!=', $month); + return $this; + } + + /** + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function objectDayAfter(string $day, string $field): GroupCollectorInterface @@ -323,8 +473,8 @@ trait TimeCollection } /** - * @param string $day - * @param string $field + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function objectDayBefore(string $day, string $field): GroupCollectorInterface @@ -334,8 +484,8 @@ trait TimeCollection } /** - * @param string $day - * @param string $field + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function objectDayIs(string $day, string $field): GroupCollectorInterface @@ -345,8 +495,19 @@ trait TimeCollection } /** - * @param string $month - * @param string $field + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function objectDayIsNot(string $day, string $field): GroupCollectorInterface + { + $this->query->whereDay(sprintf('transaction_journals.%s', $field), '!=', $day); + return $this; + } + + /** + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function objectMonthAfter(string $month, string $field): GroupCollectorInterface @@ -356,8 +517,8 @@ trait TimeCollection } /** - * @param string $month - * @param string $field + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function objectMonthBefore(string $month, string $field): GroupCollectorInterface @@ -367,8 +528,8 @@ trait TimeCollection } /** - * @param string $month - * @param string $field + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function objectMonthIs(string $month, string $field): GroupCollectorInterface @@ -378,8 +539,19 @@ trait TimeCollection } /** - * @param string $year - * @param string $field + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function objectMonthIsNot(string $month, string $field): GroupCollectorInterface + { + $this->query->whereMonth(sprintf('transaction_journals.%s', $field), '!=', $month); + return $this; + } + + /** + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function objectYearAfter(string $year, string $field): GroupCollectorInterface @@ -389,8 +561,8 @@ trait TimeCollection } /** - * @param string $year - * @param string $field + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function objectYearBefore(string $year, string $field): GroupCollectorInterface @@ -400,8 +572,8 @@ trait TimeCollection } /** - * @param string $year - * @param string $field + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function objectYearIs(string $year, string $field): GroupCollectorInterface @@ -410,10 +582,21 @@ trait TimeCollection return $this; } + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function objectYearIsNot(string $year, string $field): GroupCollectorInterface + { + $this->query->whereYear(sprintf('transaction_journals.%s', $field), '!=', $year); + return $this; + } + /** * Collect transactions after a specific date. * - * @param Carbon $date + * @param Carbon $date * * @return GroupCollectorInterface */ @@ -428,7 +611,7 @@ trait TimeCollection /** * Collect transactions before a specific date. * - * @param Carbon $date + * @param Carbon $date * * @return GroupCollectorInterface */ @@ -443,7 +626,7 @@ trait TimeCollection /** * Collect transactions created on a specific date. * - * @param Carbon $date + * @param Carbon $date * * @return GroupCollectorInterface */ @@ -458,8 +641,8 @@ trait TimeCollection } /** - * @param Carbon $date - * @param string $field + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ public function setMetaAfter(Carbon $date, string $field): GroupCollectorInterface @@ -482,8 +665,8 @@ trait TimeCollection } /** - * @param Carbon $date - * @param string $field + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ public function setMetaBefore(Carbon $date, string $field): GroupCollectorInterface @@ -505,9 +688,9 @@ trait TimeCollection } /** - * @param Carbon $start - * @param Carbon $end - * @param string $field + * @param Carbon $start + * @param Carbon $end + * @param string $field * @return GroupCollectorInterface */ public function setMetaDateRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface @@ -532,12 +715,11 @@ trait TimeCollection }; $this->postFilters[] = $filter; return $this; - } /** - * @param Carbon $date - * @param string $field + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ public function setObjectAfter(Carbon $date, string $field): GroupCollectorInterface @@ -549,8 +731,8 @@ trait TimeCollection } /** - * @param Carbon $date - * @param string $field + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ public function setObjectBefore(Carbon $date, string $field): GroupCollectorInterface @@ -561,9 +743,9 @@ trait TimeCollection } /** - * @param Carbon $start - * @param Carbon $end - * @param string $field + * @param Carbon $start + * @param Carbon $end + * @param string $field * @return GroupCollectorInterface */ public function setObjectRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface @@ -579,8 +761,8 @@ trait TimeCollection /** * Set the start and end time of the results to return. * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return GroupCollectorInterface */ @@ -602,7 +784,7 @@ trait TimeCollection /** * Collect transactions updated on a specific date. * - * @param Carbon $date + * @param Carbon $date * * @return GroupCollectorInterface */ @@ -616,22 +798,43 @@ trait TimeCollection return $this; } + /** + * @param string $year + * @return GroupCollectorInterface + */ public function yearAfter(string $year): GroupCollectorInterface { $this->query->whereYear('transaction_journals.date', '>=', $year); return $this; } + /** + * @param string $year + * @return GroupCollectorInterface + */ public function yearBefore(string $year): GroupCollectorInterface { $this->query->whereYear('transaction_journals.date', '<=', $year); return $this; } + /** + * @param string $year + * @return GroupCollectorInterface + */ public function yearIs(string $year): GroupCollectorInterface { $this->query->whereYear('transaction_journals.date', '=', $year); return $this; } + /** + * @param string $year + * @return GroupCollectorInterface + */ + public function yearIsNot(string $year): GroupCollectorInterface + { + $this->query->whereYear('transaction_journals.date', '!=', $year); + return $this; + } } diff --git a/app/Helpers/Collector/GroupCollector.php b/app/Helpers/Collector/GroupCollector.php index 85480f4bcd..a4fcb71568 100644 --- a/app/Helpers/Collector/GroupCollector.php +++ b/app/Helpers/Collector/GroupCollector.php @@ -25,8 +25,10 @@ namespace FireflyIII\Helpers\Collector; use Carbon\Carbon; use Carbon\Exceptions\InvalidDateException; +use Carbon\Exceptions\InvalidFormatException; use Closure; use Exception; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\Extensions\AccountCollection; use FireflyIII\Helpers\Collector\Extensions\AmountCollection; use FireflyIII\Helpers\Collector\Extensions\AttachmentCollection; @@ -50,7 +52,12 @@ use Log; */ class GroupCollector implements GroupCollectorInterface { - use CollectorProperties, AccountCollection, AmountCollection, TimeCollection, MetaCollection, AttachmentCollection; + use CollectorProperties; + use AccountCollection; + use AmountCollection; + use TimeCollection; + use MetaCollection; + use AttachmentCollection; /** * Group collector constructor. @@ -133,6 +140,66 @@ class GroupCollector implements GroupCollectorInterface ]; } + /** + * @inheritDoc + */ + public function descriptionDoesNotEnd(array $array): GroupCollectorInterface + { + $this->query->where( + static function (EloquentBuilder $q) use ($array) { + $q->where( + static function (EloquentBuilder $q1) use ($array) { + foreach ($array as $word) { + $keyword = sprintf('%%%s', $word); + $q1->where('transaction_journals.description', 'NOT LIKE', $keyword); + } + } + ); + $q->where( + static function (EloquentBuilder $q2) use ($array) { + foreach ($array as $word) { + $keyword = sprintf('%%%s', $word); + $q2->where('transaction_groups.title', 'NOT LIKE', $keyword); + $q2->orWhereNull('transaction_groups.title'); + } + } + ); + } + ); + + return $this; + } + + /** + * @inheritDoc + */ + public function descriptionDoesNotStart(array $array): GroupCollectorInterface + { + $this->query->where( + static function (EloquentBuilder $q) use ($array) { + $q->where( + static function (EloquentBuilder $q1) use ($array) { + foreach ($array as $word) { + $keyword = sprintf('%s%%', $word); + $q1->where('transaction_journals.description', 'NOT LIKE', $keyword); + } + } + ); + $q->where( + static function (EloquentBuilder $q2) use ($array) { + foreach ($array as $word) { + $keyword = sprintf('%s%%', $word); + $q2->where('transaction_groups.title', 'NOT LIKE', $keyword); + $q2->orWhereNull('transaction_groups.title'); + } + } + ); + } + ); + + return $this; + } + /** * @inheritDoc */ @@ -177,6 +244,26 @@ class GroupCollector implements GroupCollectorInterface return $this; } + /** + * @inheritDoc + */ + public function descriptionIsNot(string $value): GroupCollectorInterface + { + $this->query->where( + static function (EloquentBuilder $q) use ($value) { + $q->where('transaction_journals.description', '!=', $value); + $q->where( + static function (EloquentBuilder $q2) use ($value) { + $q2->where('transaction_groups.title', '!=', $value); + $q2->orWhereNull('transaction_groups.title'); + } + ); + } + ); + + return $this; + } + /** * @inheritDoc */ @@ -226,6 +313,133 @@ class GroupCollector implements GroupCollectorInterface Log::debug('Bindings', $this->query->getBindings()); } + /** + * Limit results to NOT a specific currency, either foreign or normal one. + * + * @param TransactionCurrency $currency + * + * @return GroupCollectorInterface + */ + public function excludeCurrency(TransactionCurrency $currency): GroupCollectorInterface + { + $this->query->where( + static function (EloquentBuilder $q) use ($currency) { + $q->where('source.transaction_currency_id', '!=', $currency->id); + $q->where( + static function (EloquentBuilder $q2) use ($currency) { + $q2->where('source.foreign_currency_id', '!=', $currency->id); + $q2->orWhereNull('source.foreign_currency_id'); + } + ); + } + ); + + return $this; + } + + /** + * @inheritDoc + */ + public function excludeForeignCurrency(TransactionCurrency $currency): GroupCollectorInterface + { + $this->query->where(static function (EloquentBuilder $q2) use ($currency) { + $q2->where('source.foreign_currency_id', '!=', $currency->id); + $q2->orWhereNull('source.foreign_currency_id'); + }); + + return $this; + } + + /** + * Limit the result to NOT a set of specific transaction groups. + * + * @param array $groupIds + * + * @return GroupCollectorInterface + */ + public function excludeIds(array $groupIds): GroupCollectorInterface + { + $this->query->whereNotIn('transaction_groups.id', $groupIds); + + return $this; + } + + /** + * Limit the result to NOT a set of specific journals. + * + * @param array $journalIds + * + * @return GroupCollectorInterface + */ + public function excludeJournalIds(array $journalIds): GroupCollectorInterface + { + if (0 !== count($journalIds)) { + // make all integers. + $integerIDs = array_map('intval', $journalIds); + + + $this->query->whereNotIn('transaction_journals.id', $integerIDs); + } + + return $this; + } + + /** + * Search for words in descriptions. + * + * @param array $array + * + * @return GroupCollectorInterface + */ + public function excludeSearchWords(array $array): GroupCollectorInterface + { + if (0 === count($array)) { + return $this; + } + $this->query->where( + static function (EloquentBuilder $q) use ($array) { + $q->where( + static function (EloquentBuilder $q1) use ($array) { + foreach ($array as $word) { + $keyword = sprintf('%%%s%%', $word); + $q1->where('transaction_journals.description', 'NOT LIKE', $keyword); + } + } + ); + $q->where( + static function (EloquentBuilder $q2) use ($array) { + foreach ($array as $word) { + $keyword = sprintf('%%%s%%', $word); + $q2->where('transaction_groups.title', 'NOT LIKE', $keyword); + $q2->orWhereNull('transaction_groups.title'); + } + } + ); + } + ); + + return $this; + } + + /** + * @inheritDoc + */ + public function excludeTypes(array $types): GroupCollectorInterface + { + $this->query->whereNotIn('transaction_types.type', $types); + + return $this; + } + + /** + * @inheritDoc + */ + public function exists(): GroupCollectorInterface + { + $this->query->whereNull('transaction_groups.deleted_at'); + return $this; + } + /** * @inheritDoc */ @@ -287,7 +501,7 @@ class GroupCollector implements GroupCollectorInterface } /** - * @param Collection $collection + * @param Collection $collection * * @return Collection */ @@ -302,21 +516,24 @@ class GroupCollector implements GroupCollectorInterface // make new array $parsedGroup = $this->parseAugmentedJournal($augumentedJournal); $groupArray = [ - 'id' => (int) $augumentedJournal->transaction_group_id, - 'user_id' => (int) $augumentedJournal->user_id, - 'title' => $augumentedJournal->transaction_group_title, + 'id' => (int)$augumentedJournal->transaction_group_id, + 'user_id' => (int)$augumentedJournal->user_id, + // Field transaction_group_title was added by the query. + 'title' => $augumentedJournal->transaction_group_title, // @phpstan-ignore-line 'transaction_type' => $parsedGroup['transaction_type_type'], 'count' => 1, 'sums' => [], 'transactions' => [], ]; - $journalId = (int) $augumentedJournal->transaction_journal_id; + // Field transaction_journal_id was added by the query. + $journalId = (int)$augumentedJournal->transaction_journal_id; // @phpstan-ignore-line $groupArray['transactions'][$journalId] = $parsedGroup; $groups[$groupId] = $groupArray; continue; } // or parse the rest. - $journalId = (int) $augumentedJournal->transaction_journal_id; + // Field transaction_journal_id was added by the query. + $journalId = (int)$augumentedJournal->transaction_journal_id; // @phpstan-ignore-line if (array_key_exists($journalId, $groups[$groupId]['transactions'])) { // append data to existing group + journal (for multiple tags or multiple attachments) $groups[$groupId]['transactions'][$journalId] = $this->mergeTags($groups[$groupId]['transactions'][$journalId], $augumentedJournal); @@ -336,7 +553,7 @@ class GroupCollector implements GroupCollectorInterface } /** - * @param TransactionJournal $augumentedJournal + * @param TransactionJournal $augumentedJournal * * @return array */ @@ -360,15 +577,16 @@ class GroupCollector implements GroupCollectorInterface $result['date']->setTimezone(config('app.timezone')); $result['created_at']->setTimezone(config('app.timezone')); $result['updated_at']->setTimezone(config('app.timezone')); - } catch (Exception $e) { // @phpstan-ignore-line + } catch (Exception $e) { // intentional generic exception Log::error($e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } // try to process meta date value (if present) $dates = ['interest_date', 'payment_date', 'invoice_date', 'book_date', 'due_date', 'process_date']; if (array_key_exists('meta_name', $result) && in_array($result['meta_name'], $dates, true)) { $name = $result['meta_name']; - if (array_key_exists('meta_data', $result) && '' !== (string) $result['meta_data']) { + if (array_key_exists('meta_data', $result) && '' !== (string)$result['meta_data']) { $result[$name] = Carbon::createFromFormat('!Y-m-d', substr(json_decode($result['meta_data']), 0, 10)); } } @@ -379,18 +597,18 @@ class GroupCollector implements GroupCollectorInterface // convert back to strings because SQLite is dumb like that. $result = $this->convertToStrings($result); - $result['reconciled'] = 1 === (int) $result['reconciled']; + $result['reconciled'] = 1 === (int)$result['reconciled']; if (array_key_exists('tag_id', $result) && null !== $result['tag_id']) { // assume the other fields are present as well. - $tagId = (int) $augumentedJournal['tag_id']; + $tagId = (int)$augumentedJournal['tag_id']; $tagDate = null; try { $tagDate = Carbon::parse($augumentedJournal['tag_date']); - } catch (InvalidDateException $e) { + } catch (InvalidFormatException $e) { Log::debug(sprintf('Could not parse date: %s', $e->getMessage())); } $result['tags'][$tagId] = [ - 'id' => (int) $result['tag_id'], + 'id' => (int)$result['tag_id'], 'name' => $result['tag_name'], 'date' => $tagDate, 'description' => $result['tag_description'], @@ -399,8 +617,8 @@ class GroupCollector implements GroupCollectorInterface // also merge attachments: if (array_key_exists('attachment_id', $result)) { - $uploaded = 1 === (int) $result['attachment_uploaded']; - $attachmentId = (int) $augumentedJournal['attachment_id']; + $uploaded = 1 === (int)$result['attachment_uploaded']; + $attachmentId = (int)$augumentedJournal['attachment_id']; if (0 !== $attachmentId && $uploaded) { $result['attachments'][$attachmentId] = [ 'id' => $attachmentId, @@ -410,7 +628,8 @@ class GroupCollector implements GroupCollectorInterface } } // unset various fields: - unset($result['tag_id'], $result['meta_data'], $result['meta_name'], + unset( + $result['tag_id'], $result['meta_data'], $result['meta_name'], $result['tag_name'], $result['tag_date'], $result['tag_description'], $result['tag_latitude'], $result['tag_longitude'], $result['tag_zoom_level'], $result['attachment_filename'], $result['attachment_id'] @@ -423,22 +642,35 @@ class GroupCollector implements GroupCollectorInterface /** * Convert a selected set of fields to arrays. * - * @param array $array + * @param array $array * * @return array */ private function convertToInteger(array $array): array { foreach ($this->integerFields as $field) { - $array[$field] = array_key_exists($field, $array) ? (int) $array[$field] : null; + $array[$field] = array_key_exists($field, $array) ? (int)$array[$field] : null; } return $array; } /** - * @param array $existingJournal - * @param TransactionJournal $newJournal + * @param array $array + * @return array + */ + private function convertToStrings(array $array): array + { + foreach ($this->stringFields as $field) { + $array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string)$array[$field] : null; + } + + return $array; + } + + /** + * @param array $existingJournal + * @param TransactionJournal $newJournal * * @return array */ @@ -446,17 +678,17 @@ class GroupCollector implements GroupCollectorInterface { $newArray = $newJournal->toArray(); if (array_key_exists('tag_id', $newArray)) { // assume the other fields are present as well. - $tagId = (int) $newJournal['tag_id']; + $tagId = (int)$newJournal['tag_id']; $tagDate = null; try { $tagDate = Carbon::parse($newArray['tag_date']); - } catch (InvalidDateException $e) { + } catch (InvalidFormatException $e) { Log::debug(sprintf('Could not parse date: %s', $e->getMessage())); } $existingJournal['tags'][$tagId] = [ - 'id' => (int) $newArray['tag_id'], + 'id' => (int)$newArray['tag_id'], 'name' => $newArray['tag_name'], 'date' => $tagDate, 'description' => $newArray['tag_description'], @@ -467,8 +699,8 @@ class GroupCollector implements GroupCollectorInterface } /** - * @param array $existingJournal - * @param TransactionJournal $newJournal + * @param array $existingJournal + * @param TransactionJournal $newJournal * * @return array */ @@ -476,7 +708,7 @@ class GroupCollector implements GroupCollectorInterface { $newArray = $newJournal->toArray(); if (array_key_exists('attachment_id', $newArray)) { - $attachmentId = (int) $newJournal['attachment_id']; + $attachmentId = (int)$newJournal['attachment_id']; $existingJournal['attachments'][$attachmentId] = [ 'id' => $attachmentId, @@ -487,20 +719,20 @@ class GroupCollector implements GroupCollectorInterface } /** - * @param array $groups + * @param array $groups * * @return array */ private function parseSums(array $groups): array { /** - * @var int $groudId + * @var int $groudId * @var array $group */ foreach ($groups as $groudId => $group) { /** @var array $transaction */ foreach ($group['transactions'] as $transaction) { - $currencyId = (int) $transaction['currency_id']; + $currencyId = (int)$transaction['currency_id']; // set default: if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) { @@ -513,7 +745,7 @@ class GroupCollector implements GroupCollectorInterface $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['amount']); if (null !== $transaction['foreign_amount'] && null !== $transaction['foreign_currency_id']) { - $currencyId = (int) $transaction['foreign_currency_id']; + $currencyId = (int)$transaction['foreign_currency_id']; // set default: if (!array_key_exists($currencyId, $groups[$groudId]['sums'])) { @@ -523,10 +755,7 @@ class GroupCollector implements GroupCollectorInterface $groups[$groudId]['sums'][$currencyId]['currency_decimal_places'] = $transaction['foreign_currency_decimal_places']; $groups[$groudId]['sums'][$currencyId]['amount'] = '0'; } - $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd( - $groups[$groudId]['sums'][$currencyId]['amount'], - $transaction['foreign_amount'] ?? '0' - ); + $groups[$groudId]['sums'][$currencyId]['amount'] = bcadd($groups[$groudId]['sums'][$currencyId]['amount'], $transaction['foreign_amount']); } } } @@ -535,24 +764,22 @@ class GroupCollector implements GroupCollectorInterface } /** - * @param Collection $collection + * @param Collection $collection * @return Collection */ private function postFilterCollection(Collection $collection): Collection { $currentCollection = $collection; /** - * @var int $i * @var Closure $function */ foreach ($this->postFilters as $function) { - - $nextCollection = new Collection; + $nextCollection = new Collection(); // loop everything in the current collection // and save it (or not) in the new collection. // that new collection is the next current collection /** - * @var int $index + * @var int $ii * @var array $item */ foreach ($currentCollection as $ii => $item) { @@ -586,7 +813,7 @@ class GroupCollector implements GroupCollectorInterface /** * Limit the number of returned entries. * - * @param int $limit + * @param int $limit * * @return GroupCollectorInterface */ @@ -598,11 +825,28 @@ class GroupCollector implements GroupCollectorInterface return $this; } + /** + * @inheritDoc + */ + public function isNotReconciled(): GroupCollectorInterface + { + $this->query->where('source.reconciled', 0)->where('destination.reconciled', 0); + return $this; + } + + /** + * @inheritDoc + */ + public function isReconciled(): GroupCollectorInterface + { + $this->query->where('source.reconciled', 1)->where('destination.reconciled', 1); + return $this; + } /** * Limit results to a specific currency, either foreign or normal one. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return GroupCollectorInterface */ @@ -631,13 +875,12 @@ class GroupCollector implements GroupCollectorInterface /** * Limit the result to a set of specific transaction groups. * - * @param array $groupIds + * @param array $groupIds * * @return GroupCollectorInterface */ public function setIds(array $groupIds): GroupCollectorInterface { - $this->query->whereIn('transaction_groups.id', $groupIds); return $this; @@ -646,13 +889,13 @@ class GroupCollector implements GroupCollectorInterface /** * Limit the result to a set of specific journals. * - * @param array $journalIds + * @param array $journalIds * * @return GroupCollectorInterface */ public function setJournalIds(array $journalIds): GroupCollectorInterface { - if (!empty($journalIds)) { + if (0 !== count($journalIds)) { // make all integers. $integerIDs = array_map('intval', $journalIds); @@ -666,7 +909,7 @@ class GroupCollector implements GroupCollectorInterface /** * Set the page to get. * - * @param int $page + * @param int $page * * @return GroupCollectorInterface */ @@ -682,12 +925,15 @@ class GroupCollector implements GroupCollectorInterface /** * Search for words in descriptions. * - * @param array $array + * @param array $array * * @return GroupCollectorInterface */ public function setSearchWords(array $array): GroupCollectorInterface { + if (0 === count($array)) { + return $this; + } $this->query->where( static function (EloquentBuilder $q) use ($array) { $q->where( @@ -715,7 +961,7 @@ class GroupCollector implements GroupCollectorInterface /** * Limit the search to one specific transaction group. * - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return GroupCollectorInterface */ @@ -729,7 +975,7 @@ class GroupCollector implements GroupCollectorInterface /** * Limit the included transaction types. * - * @param array $types + * @param array $types * * @return GroupCollectorInterface */ @@ -743,7 +989,7 @@ class GroupCollector implements GroupCollectorInterface /** * Set the user object and start the query. * - * @param User $user + * @param User $user * * @return GroupCollectorInterface */ @@ -752,7 +998,6 @@ class GroupCollector implements GroupCollectorInterface if (null === $this->user) { $this->user = $user; $this->startQuery(); - } return $this; @@ -819,17 +1064,4 @@ class GroupCollector implements GroupCollectorInterface return $this; } - - /** - * @param array $array - * @return array - */ - private function convertToStrings(array $array): array - { - foreach ($this->stringFields as $field) { - $array[$field] = array_key_exists($field, $array) && null !== $array[$field] ? (string) $array[$field] : null; - } - - return $array; - } } diff --git a/app/Helpers/Collector/GroupCollectorInterface.php b/app/Helpers/Collector/GroupCollectorInterface.php index b950f12f1f..e8409de225 100644 --- a/app/Helpers/Collector/GroupCollectorInterface.php +++ b/app/Helpers/Collector/GroupCollectorInterface.php @@ -42,16 +42,23 @@ interface GroupCollectorInterface /** * Get transactions with a specific amount. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ public function amountIs(string $amount): GroupCollectorInterface; + /** + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function amountIsNot(string $amount): GroupCollectorInterface; + /** * Get transactions where the amount is less than. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ @@ -60,82 +67,154 @@ interface GroupCollectorInterface /** * Get transactions where the foreign amount is more than. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ public function amountMore(string $amount): GroupCollectorInterface; /** - * @param string $name + * @param string $name * @return GroupCollectorInterface */ public function attachmentNameContains(string $name): GroupCollectorInterface; /** - * @param string $name + * @param string $name + * @return GroupCollectorInterface + */ + public function attachmentNameDoesNotContain(string $name): GroupCollectorInterface; + + /** + * @param string $name + * @return GroupCollectorInterface + */ + public function attachmentNameDoesNotEnd(string $name): GroupCollectorInterface; + + /** + * @param string $name + * @return GroupCollectorInterface + */ + public function attachmentNameDoesNotStart(string $name): GroupCollectorInterface; + + /** + * @param string $name * @return GroupCollectorInterface */ public function attachmentNameEnds(string $name): GroupCollectorInterface; /** - * @param string $name + * @param string $name * @return GroupCollectorInterface */ public function attachmentNameIs(string $name): GroupCollectorInterface; /** - * @param string $name + * @param string $name + * @return GroupCollectorInterface + */ + public function attachmentNameIsNot(string $name): GroupCollectorInterface; + + /** + * @param string $name * @return GroupCollectorInterface */ public function attachmentNameStarts(string $name): GroupCollectorInterface; /** - * @param string $value + * @param string $value * @return GroupCollectorInterface */ public function attachmentNotesAre(string $value): GroupCollectorInterface; /** - * @param string $value + * @param string $value + * @return GroupCollectorInterface + */ + public function attachmentNotesAreNot(string $value): GroupCollectorInterface; + + /** + * @param string $value * @return GroupCollectorInterface */ public function attachmentNotesContains(string $value): GroupCollectorInterface; /** - * @param string $value + * @param string $value + * @return GroupCollectorInterface + */ + public function attachmentNotesDoNotContain(string $value): GroupCollectorInterface; + + /** + * @param string $value + * @return GroupCollectorInterface + */ + public function attachmentNotesDoNotEnd(string $value): GroupCollectorInterface; + + /** + * @param string $value + * @return GroupCollectorInterface + */ + public function attachmentNotesDoNotStart(string $value): GroupCollectorInterface; + + /** + * @param string $value * @return GroupCollectorInterface */ public function attachmentNotesEnds(string $value): GroupCollectorInterface; /** - * @param string $value + * @param string $value * @return GroupCollectorInterface */ public function attachmentNotesStarts(string $value): GroupCollectorInterface; /** - * @param string $day + * @param string $day * @return GroupCollectorInterface */ public function dayAfter(string $day): GroupCollectorInterface; /** - * @param string $day + * @param string $day * @return GroupCollectorInterface */ public function dayBefore(string $day): GroupCollectorInterface; /** - * @param string $day + * @param string $day * @return GroupCollectorInterface */ public function dayIs(string $day): GroupCollectorInterface; + /** + * @param string $day + * @return GroupCollectorInterface + */ + public function dayIsNot(string $day): GroupCollectorInterface; + + /** + * End of the description must not match: + * + * @param array $array + * + * @return GroupCollectorInterface + */ + public function descriptionDoesNotEnd(array $array): GroupCollectorInterface; + + /** + * Beginning of the description must not start with: + * + * @param array $array + * + * @return GroupCollectorInterface + */ + public function descriptionDoesNotStart(array $array): GroupCollectorInterface; + /** * End of the description must match: * - * @param array $array + * @param array $array * * @return GroupCollectorInterface */ @@ -144,71 +223,282 @@ interface GroupCollectorInterface /** * Description must be: * - * @param string $value + * @param string $value * * @return GroupCollectorInterface */ public function descriptionIs(string $value): GroupCollectorInterface; + /** + * Description must not be: + * + * @param string $value + * + * @return GroupCollectorInterface + */ + public function descriptionIsNot(string $value): GroupCollectorInterface; + /** * Beginning of the description must match: * - * @param array $array + * @param array $array * * @return GroupCollectorInterface */ public function descriptionStarts(array $array): GroupCollectorInterface; + /** + * These accounts must not be accounts. + * + * @param Collection $accounts + * + * @return GroupCollectorInterface + */ + public function excludeAccounts(Collection $accounts): GroupCollectorInterface; + + /** + * Exclude a specific set of bills + * + * @param Collection $bills + * + * @return GroupCollectorInterface + */ + public function excludeBills(Collection $bills): GroupCollectorInterface; + + /** + * Exclude a budget + * + * @param Budget $budget + * + * @return GroupCollectorInterface + */ + public function excludeBudget(Budget $budget): GroupCollectorInterface; + + /** + * Exclude a budget. + * + * @param Collection $budgets + * + * @return GroupCollectorInterface + */ + public function excludeBudgets(Collection $budgets): GroupCollectorInterface; + + /** + * Exclude a set of categories. + * + * @param Collection $categories + * @return GroupCollectorInterface + */ + public function excludeCategories(Collection $categories): GroupCollectorInterface; + + /** + * Exclude a specific category + * + * @param Category $category + * + * @return GroupCollectorInterface + */ + public function excludeCategory(Category $category): GroupCollectorInterface; + + /** + * Limit results to NOT a specific currency, either foreign or normal one. + * + * @param TransactionCurrency $currency + * + * @return GroupCollectorInterface + */ + public function excludeCurrency(TransactionCurrency $currency): GroupCollectorInterface; + /** * Exclude destination accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ public function excludeDestinationAccounts(Collection $accounts): GroupCollectorInterface; + /** + * Look for specific external ID's. + * + * @param string $externalId + * + * @return GroupCollectorInterface + */ + public function excludeExternalId(string $externalId): GroupCollectorInterface; + + /** + * @param string $url + * @return GroupCollectorInterface + */ + public function excludeExternalUrl(string $url): GroupCollectorInterface; + + /** + * Limit results to exclude a specific foreign currency. + * + * @param TransactionCurrency $currency + * + * @return GroupCollectorInterface + */ + public function excludeForeignCurrency(TransactionCurrency $currency): GroupCollectorInterface; + + /** + * Limit the result to NOT a set of specific transaction groups. + * + * @param array $groupIds + * + * @return GroupCollectorInterface + */ + public function excludeIds(array $groupIds): GroupCollectorInterface; + + /** + * Look for specific external ID's. + * + * @param string $externalId + * + * @return GroupCollectorInterface + */ + public function excludeInternalReference(string $externalId): GroupCollectorInterface; + + /** + * Limit the result to NOT a set of specific transaction journals. + * + * @param array $journalIds + * + * @return GroupCollectorInterface + */ + public function excludeJournalIds(array $journalIds): GroupCollectorInterface; + + /** + * @param Carbon $start + * @param Carbon $end + * @param string $field + * @return GroupCollectorInterface + */ + public function excludeMetaDateRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface; + + /** + * @param Carbon $start + * @param Carbon $end + * @param string $field + * @return GroupCollectorInterface + */ + public function excludeObjectRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface; + + /** + * @param Carbon $start + * @param Carbon $end + * @return GroupCollectorInterface + */ + public function excludeRange(Carbon $start, Carbon $end): GroupCollectorInterface; + + /** + * @param string $recurringId + * + * @return GroupCollectorInterface + */ + public function excludeRecurrenceId(string $recurringId): GroupCollectorInterface; + + /** + * Exclude words in descriptions. + * + * @param array $array + * + * @return GroupCollectorInterface + */ + public function excludeSearchWords(array $array): GroupCollectorInterface; + /** * These accounts must not be source accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ public function excludeSourceAccounts(Collection $accounts): GroupCollectorInterface; /** - * @param string $externalId + * Limit the included transaction types. + * + * @param array $types + * + * @return GroupCollectorInterface + */ + public function excludeTypes(array $types): GroupCollectorInterface; + + /** + * @return GroupCollectorInterface + */ + public function exists(): GroupCollectorInterface; + + /** + * @param string $externalId * @return GroupCollectorInterface */ public function externalIdContains(string $externalId): GroupCollectorInterface; /** - * @param string $externalId + * @param string $externalId + * @return GroupCollectorInterface + */ + public function externalIdDoesNotContain(string $externalId): GroupCollectorInterface; + + /** + * @param string $externalId + * @return GroupCollectorInterface + */ + public function externalIdDoesNotEnd(string $externalId): GroupCollectorInterface; + + /** + * @param string $externalId + * @return GroupCollectorInterface + */ + public function externalIdDoesNotStart(string $externalId): GroupCollectorInterface; + + /** + * @param string $externalId * @return GroupCollectorInterface */ public function externalIdEnds(string $externalId): GroupCollectorInterface; /** - * @param string $externalId + * @param string $externalId * @return GroupCollectorInterface */ public function externalIdStarts(string $externalId): GroupCollectorInterface; /** - * @param string $url + * @param string $url * @return GroupCollectorInterface */ public function externalUrlContains(string $url): GroupCollectorInterface; /** - * @param string $url + * @param string $url + * @return GroupCollectorInterface + */ + public function externalUrlDoesNotContain(string $url): GroupCollectorInterface; + + /** + * @param string $url + * @return GroupCollectorInterface + */ + public function externalUrlDoesNotEnd(string $url): GroupCollectorInterface; + + /** + * @param string $url + * @return GroupCollectorInterface + */ + public function externalUrlDoesNotStart(string $url): GroupCollectorInterface; + + /** + * @param string $url * @return GroupCollectorInterface */ public function externalUrlEnds(string $url): GroupCollectorInterface; /** - * @param string $url + * @param string $url * @return GroupCollectorInterface */ public function externalUrlStarts(string $url): GroupCollectorInterface; @@ -223,16 +513,25 @@ interface GroupCollectorInterface /** * Get transactions with a specific foreign amount. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ public function foreignAmountIs(string $amount): GroupCollectorInterface; + /** + * Get transactions with a specific foreign amount. + * + * @param string $amount + * + * @return GroupCollectorInterface + */ + public function foreignAmountIsNot(string $amount): GroupCollectorInterface; + /** * Get transactions where the amount is less than. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ @@ -241,7 +540,7 @@ interface GroupCollectorInterface /** * Get transactions where the foreign amount is more than. * - * @param string $amount + * @param string $amount * * @return GroupCollectorInterface */ @@ -288,199 +587,306 @@ interface GroupCollectorInterface public function hasNoAttachments(): GroupCollectorInterface; /** - * @param string $externalId + * @param string $externalId * @return GroupCollectorInterface */ public function internalReferenceContains(string $externalId): GroupCollectorInterface; /** - * @param string $externalId + * @param string $externalId + * @return GroupCollectorInterface + */ + public function internalReferenceDoesNotContain(string $externalId): GroupCollectorInterface; + + /** + * @param string $externalId + * @return GroupCollectorInterface + */ + public function internalReferenceDoesNotEnd(string $externalId): GroupCollectorInterface; + + /** + * @param string $externalId + * @return GroupCollectorInterface + */ + public function internalReferenceDoesNotStart(string $externalId): GroupCollectorInterface; + + /** + * @param string $externalId * @return GroupCollectorInterface */ public function internalReferenceEnds(string $externalId): GroupCollectorInterface; /** - * @param string $externalId + * @param string $externalId * @return GroupCollectorInterface */ public function internalReferenceStarts(string $externalId): GroupCollectorInterface; /** - * @param string $day - * @param string $field + * Only journals that are reconciled. + * + * @return GroupCollectorInterface + */ + public function isNotReconciled(): GroupCollectorInterface; + + /** + * Only journals that are reconciled. + * + * @return GroupCollectorInterface + */ + public function isReconciled(): GroupCollectorInterface; + + /** + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function metaDayAfter(string $day, string $field): GroupCollectorInterface; /** - * @param string $day - * @param string $field + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function metaDayBefore(string $day, string $field): GroupCollectorInterface; /** - * @param string $day - * @param string $field + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function metaDayIs(string $day, string $field): GroupCollectorInterface; /** - * @param string $month - * @param string $field + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function metaDayIsNot(string $day, string $field): GroupCollectorInterface; + + /** + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function metaMonthAfter(string $month, string $field): GroupCollectorInterface; /** - * @param string $month - * @param string $field + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function metaMonthBefore(string $month, string $field): GroupCollectorInterface; /** - * @param string $month - * @param string $field + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function metaMonthIs(string $month, string $field): GroupCollectorInterface; /** - * @param string $year - * @param string $field + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function metaMonthIsNot(string $month, string $field): GroupCollectorInterface; + + /** + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function metaYearAfter(string $year, string $field): GroupCollectorInterface; /** - * @param string $year - * @param string $field + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function metaYearBefore(string $year, string $field): GroupCollectorInterface; /** - * @param string $year - * @param string $field + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function metaYearIs(string $year, string $field): GroupCollectorInterface; /** - * @param string $month + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function metaYearIsNot(string $year, string $field): GroupCollectorInterface; + + /** + * @param string $month * @return GroupCollectorInterface */ public function monthAfter(string $month): GroupCollectorInterface; /** - * @param string $month + * @param string $month * @return GroupCollectorInterface */ public function monthBefore(string $month): GroupCollectorInterface; /** - * @param string $month + * @param string $month * @return GroupCollectorInterface */ public function monthIs(string $month): GroupCollectorInterface; /** - * @param string $value + * @param string $month + * @return GroupCollectorInterface + */ + public function monthIsNot(string $month): GroupCollectorInterface; + + /** + * @param string $value * * @return GroupCollectorInterface */ public function notesContain(string $value): GroupCollectorInterface; /** - * @param string $value + * @param string $value + * + * @return GroupCollectorInterface + */ + public function notesDoNotContain(string $value): GroupCollectorInterface; + + /** + * @param string $value + * + * @return GroupCollectorInterface + */ + public function notesDontEndWith(string $value): GroupCollectorInterface; + + /** + * @param string $value + * @return GroupCollectorInterface + */ + public function notesDontStartWith(string $value): GroupCollectorInterface; + + /** + * @param string $value * * @return GroupCollectorInterface */ public function notesEndWith(string $value): GroupCollectorInterface; /** - * @param string $value + * @param string $value * * @return GroupCollectorInterface */ public function notesExactly(string $value): GroupCollectorInterface; /** - * @param string $value + * @param string $value + * + * @return GroupCollectorInterface + */ + public function notesExactlyNot(string $value): GroupCollectorInterface; + + /** + * @param string $value * * @return GroupCollectorInterface */ public function notesStartWith(string $value): GroupCollectorInterface; /** - * @param string $day - * @param string $field + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function objectDayAfter(string $day, string $field): GroupCollectorInterface; /** - * @param string $day - * @param string $field + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function objectDayBefore(string $day, string $field): GroupCollectorInterface; /** - * @param string $day - * @param string $field + * @param string $day + * @param string $field * @return GroupCollectorInterface */ public function objectDayIs(string $day, string $field): GroupCollectorInterface; /** - * @param string $month - * @param string $field + * @param string $day + * @param string $field + * @return GroupCollectorInterface + */ + public function objectDayIsNot(string $day, string $field): GroupCollectorInterface; + + /** + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function objectMonthAfter(string $month, string $field): GroupCollectorInterface; /** - * @param string $month - * @param string $field + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function objectMonthBefore(string $month, string $field): GroupCollectorInterface; /** - * @param string $month - * @param string $field + * @param string $month + * @param string $field * @return GroupCollectorInterface */ public function objectMonthIs(string $month, string $field): GroupCollectorInterface; /** - * @param string $year - * @param string $field + * @param string $month + * @param string $field + * @return GroupCollectorInterface + */ + public function objectMonthIsNot(string $month, string $field): GroupCollectorInterface; + + /** + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function objectYearAfter(string $year, string $field): GroupCollectorInterface; /** - * @param string $year - * @param string $field + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function objectYearBefore(string $year, string $field): GroupCollectorInterface; /** - * @param string $year - * @param string $field + * @param string $year + * @param string $field * @return GroupCollectorInterface */ public function objectYearIs(string $year, string $field): GroupCollectorInterface; + /** + * @param string $year + * @param string $field + * @return GroupCollectorInterface + */ + public function objectYearIsNot(string $year, string $field): GroupCollectorInterface; + /** * Define which accounts can be part of the source and destination transactions. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -489,7 +895,7 @@ interface GroupCollectorInterface /** * Collect transactions after a specific date. * - * @param Carbon $date + * @param Carbon $date * * @return GroupCollectorInterface */ @@ -498,7 +904,7 @@ interface GroupCollectorInterface /** * Collect transactions before a specific date. * - * @param Carbon $date + * @param Carbon $date * * @return GroupCollectorInterface */ @@ -507,7 +913,7 @@ interface GroupCollectorInterface /** * Limit the search to a specific bill. * - * @param Bill $bill + * @param Bill $bill * * @return GroupCollectorInterface */ @@ -516,7 +922,7 @@ interface GroupCollectorInterface /** * Limit the search to a specific set of bills. * - * @param Collection $bills + * @param Collection $bills * * @return GroupCollectorInterface */ @@ -525,7 +931,7 @@ interface GroupCollectorInterface /** * Both source AND destination must be in this list of accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -534,7 +940,7 @@ interface GroupCollectorInterface /** * Limit the search to a specific budget. * - * @param Budget $budget + * @param Budget $budget * * @return GroupCollectorInterface */ @@ -543,7 +949,7 @@ interface GroupCollectorInterface /** * Limit the search to a specific set of budgets. * - * @param Collection $budgets + * @param Collection $budgets * * @return GroupCollectorInterface */ @@ -552,7 +958,7 @@ interface GroupCollectorInterface /** * Limit the search to a specific bunch of categories. * - * @param Collection $categories + * @param Collection $categories * * @return GroupCollectorInterface */ @@ -561,7 +967,7 @@ interface GroupCollectorInterface /** * Limit the search to a specific category. * - * @param Category $category + * @param Category $category * * @return GroupCollectorInterface */ @@ -570,7 +976,7 @@ interface GroupCollectorInterface /** * Collect transactions created on a specific date. * - * @param Carbon $date + * @param Carbon $date * * @return GroupCollectorInterface */ @@ -579,7 +985,7 @@ interface GroupCollectorInterface /** * Limit results to a specific currency, either foreign or normal one. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return GroupCollectorInterface */ @@ -588,7 +994,7 @@ interface GroupCollectorInterface /** * Set destination accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -597,14 +1003,14 @@ interface GroupCollectorInterface /** * Look for specific external ID's. * - * @param string $externalId + * @param string $externalId * * @return GroupCollectorInterface */ public function setExternalId(string $externalId): GroupCollectorInterface; /** - * @param string $url + * @param string $url * @return GroupCollectorInterface */ public function setExternalUrl(string $url): GroupCollectorInterface; @@ -612,7 +1018,7 @@ interface GroupCollectorInterface /** * Limit results to a specific foreign currency. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return GroupCollectorInterface */ @@ -621,7 +1027,7 @@ interface GroupCollectorInterface /** * Limit the result to a set of specific transaction groups. * - * @param array $groupIds + * @param array $groupIds * * @return GroupCollectorInterface */ @@ -630,7 +1036,7 @@ interface GroupCollectorInterface /** * Look for specific external ID's. * - * @param string $externalId + * @param string $externalId * * @return GroupCollectorInterface */ @@ -639,7 +1045,7 @@ interface GroupCollectorInterface /** * Limit the result to a set of specific transaction journals. * - * @param array $journalIds + * @param array $journalIds * * @return GroupCollectorInterface */ @@ -648,7 +1054,7 @@ interface GroupCollectorInterface /** * Limit the number of returned entries. * - * @param int $limit + * @param int $limit * * @return GroupCollectorInterface */ @@ -657,8 +1063,8 @@ interface GroupCollectorInterface /** * Collect transactions after a specific date. * - * @param Carbon $date - * @param string $field + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ public function setMetaAfter(Carbon $date, string $field): GroupCollectorInterface; @@ -666,8 +1072,8 @@ interface GroupCollectorInterface /** * Collect transactions before a specific date. * - * @param Carbon $date - * @param string $field + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ public function setMetaBefore(Carbon $date, string $field): GroupCollectorInterface; @@ -675,32 +1081,41 @@ interface GroupCollectorInterface /** * Set the start and end time of the results to return, based on meta data. * - * @param Carbon $start - * @param Carbon $end - * @param string $field + * @param Carbon $start + * @param Carbon $end + * @param string $field * * @return GroupCollectorInterface */ public function setMetaDateRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface; /** - * @param Carbon $date - * @param string $field + * Define which accounts can NOT be part of the source and destination transactions. + * + * @param Collection $accounts + * + * @return GroupCollectorInterface + */ + public function setNotAccounts(Collection $accounts): GroupCollectorInterface; + + /** + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ public function setObjectAfter(Carbon $date, string $field): GroupCollectorInterface; /** - * @param Carbon $date - * @param string $field + * @param Carbon $date + * @param string $field * @return GroupCollectorInterface */ public function setObjectBefore(Carbon $date, string $field): GroupCollectorInterface; /** - * @param Carbon $start - * @param Carbon $end - * @param string $field + * @param Carbon $start + * @param Carbon $end + * @param string $field * @return GroupCollectorInterface */ public function setObjectRange(Carbon $start, Carbon $end, string $field): GroupCollectorInterface; @@ -708,7 +1123,7 @@ interface GroupCollectorInterface /** * Set the page to get. * - * @param int $page + * @param int $page * * @return GroupCollectorInterface */ @@ -717,8 +1132,8 @@ interface GroupCollectorInterface /** * Set the start and end time of the results to return. * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return GroupCollectorInterface */ @@ -727,7 +1142,7 @@ interface GroupCollectorInterface /** * Look for specific recurring ID's. * - * @param string $recurringId + * @param string $recurringId * * @return GroupCollectorInterface */ @@ -736,16 +1151,22 @@ interface GroupCollectorInterface /** * Search for words in descriptions. * - * @param array $array + * @param array $array * * @return GroupCollectorInterface */ public function setSearchWords(array $array): GroupCollectorInterface; + /** + * @param string $sepaCT + * @return GroupCollectorInterface + */ + public function setSepaCT(string $sepaCT): GroupCollectorInterface; + /** * Set source accounts. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -754,7 +1175,7 @@ interface GroupCollectorInterface /** * Limit results to a specific tag. * - * @param Tag $tag + * @param Tag $tag * * @return GroupCollectorInterface */ @@ -763,7 +1184,7 @@ interface GroupCollectorInterface /** * Limit results to a specific set of tags. * - * @param Collection $tags + * @param Collection $tags * * @return GroupCollectorInterface */ @@ -772,7 +1193,7 @@ interface GroupCollectorInterface /** * Limit the search to one specific transaction group. * - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return GroupCollectorInterface */ @@ -781,7 +1202,7 @@ interface GroupCollectorInterface /** * Limit the included transaction types. * - * @param array $types + * @param array $types * * @return GroupCollectorInterface */ @@ -790,7 +1211,7 @@ interface GroupCollectorInterface /** * Collect transactions updated on a specific date. * - * @param Carbon $date + * @param Carbon $date * * @return GroupCollectorInterface */ @@ -799,7 +1220,7 @@ interface GroupCollectorInterface /** * Set the user object and start the query. * - * @param User $user + * @param User $user * * @return GroupCollectorInterface */ @@ -808,7 +1229,7 @@ interface GroupCollectorInterface /** * Only when does not have these tags * - * @param Collection $tags + * @param Collection $tags * * @return GroupCollectorInterface */ @@ -817,7 +1238,7 @@ interface GroupCollectorInterface /** * Either account can be set, but NOT both. This effectively excludes internal transfers. * - * @param Collection $accounts + * @param Collection $accounts * * @return GroupCollectorInterface */ @@ -894,7 +1315,14 @@ interface GroupCollectorInterface public function withCategoryInformation(): GroupCollectorInterface; /** - * Transactions with an external URL + * Transactions with any external ID + * + * @return GroupCollectorInterface + */ + public function withExternalId(): GroupCollectorInterface; + + /** + * Transactions with any external URL * * @return GroupCollectorInterface */ @@ -903,7 +1331,7 @@ interface GroupCollectorInterface /** * Transaction must have meta date field X. * - * @param string $field + * @param string $field * @return GroupCollectorInterface */ public function withMetaDate(string $field): GroupCollectorInterface; @@ -943,6 +1371,13 @@ interface GroupCollectorInterface */ public function withoutCategory(): GroupCollectorInterface; + /** + * Transactions without an external ID + * + * @return GroupCollectorInterface + */ + public function withoutExternalId(): GroupCollectorInterface; + /** * Transactions without an external URL * @@ -961,22 +1396,26 @@ interface GroupCollectorInterface public function withoutTags(): GroupCollectorInterface; /** - * @param string $year + * @param string $year * @return GroupCollectorInterface */ public function yearAfter(string $year): GroupCollectorInterface; /** - * @param string $year + * @param string $year * @return GroupCollectorInterface */ public function yearBefore(string $year): GroupCollectorInterface; /** - * @param string $year + * @param string $year * @return GroupCollectorInterface */ public function yearIs(string $year): GroupCollectorInterface; - + /** + * @param string $year + * @return GroupCollectorInterface + */ + public function yearIsNot(string $year): GroupCollectorInterface; } diff --git a/app/Helpers/Fiscal/FiscalHelper.php b/app/Helpers/Fiscal/FiscalHelper.php index 68af77a004..47fbd76ce6 100644 --- a/app/Helpers/Fiscal/FiscalHelper.php +++ b/app/Helpers/Fiscal/FiscalHelper.php @@ -1,4 +1,5 @@ useCustomFiscalYear = app('preferences')->get('customFiscalYear', false)->data; + $this->useCustomFiscalYear = (bool) app('preferences')->get('customFiscalYear', false)->data; } /** - * @param Carbon $date + * @param Carbon $date * * @return Carbon date object * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function endOfFiscalYear(Carbon $date): Carbon { @@ -68,12 +71,12 @@ class FiscalHelper implements FiscalHelperInterface } /** - * @param Carbon $date + * @param Carbon $date * * @return Carbon date object * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function startOfFiscalYear(Carbon $date): Carbon { @@ -82,7 +85,7 @@ class FiscalHelper implements FiscalHelperInterface if (true === $this->useCustomFiscalYear) { $prefStartStr = app('preferences')->get('fiscalYearStart', '01-01')->data; [$mth, $day] = explode('-', $prefStartStr); - $startDate->day((int) $day)->month((int) $mth); + $startDate->day((int)$day)->month((int)$mth); // if start date is after passed date, sub 1 year. if ($startDate > $date) { diff --git a/app/Helpers/Fiscal/FiscalHelperInterface.php b/app/Helpers/Fiscal/FiscalHelperInterface.php index 4888dce3c5..559f2fe672 100644 --- a/app/Helpers/Fiscal/FiscalHelperInterface.php +++ b/app/Helpers/Fiscal/FiscalHelperInterface.php @@ -1,4 +1,5 @@ addProperty($date); $cache->addProperty('net-worth-by-currency'); $cache->addProperty(implode(',', $accounts->pluck('id')->toArray())); @@ -79,7 +78,7 @@ class NetWorth implements NetWorthInterface $netWorth = []; $result = []; - //Log::debug(sprintf('Now in getNetWorthByCurrency(%s)', $date->format('Y-m-d'))); + Log::debug(sprintf('Now in getNetWorthByCurrency(%s)', $date->format('Y-m-d'))); // get default currency $default = app('amount')->getDefaultCurrencyByUser($this->user); @@ -90,31 +89,31 @@ class NetWorth implements NetWorthInterface // get the preferred currency for this account /** @var Account $account */ foreach ($accounts as $account) { - //Log::debug(sprintf('Now at account #%d: "%s"', $account->id, $account->name)); - $currencyId = (int) $this->accountRepository->getMetaValue($account, 'currency_id'); + Log::debug(sprintf('Now at account #%d: "%s"', $account->id, $account->name)); + $currencyId = (int)$this->accountRepository->getMetaValue($account, 'currency_id'); $currencyId = 0 === $currencyId ? $default->id : $currencyId; - //Log::debug(sprintf('Currency ID is #%d', $currencyId)); + Log::debug(sprintf('Currency ID is #%d', $currencyId)); // balance in array: $balance = $balances[$account->id] ?? '0'; - //Log::debug(sprintf('Balance is %s', $balance)); + Log::debug(sprintf('Balance for %s is %s', $date->format('Y-m-d'), $balance)); // always subtract virtual balance. - $virtualBalance = (string) $account->virtual_balance; + $virtualBalance = (string)$account->virtual_balance; if ('' !== $virtualBalance) { $balance = bcsub($balance, $virtualBalance); } - //Log::debug(sprintf('Balance corrected to %s because of virtual balance (%s)', $balance, $virtualBalance)); + Log::debug(sprintf('Balance corrected to %s because of virtual balance (%s)', $balance, $virtualBalance)); if (!array_key_exists($currencyId, $netWorth)) { $netWorth[$currencyId] = '0'; } $netWorth[$currencyId] = bcadd($balance, $netWorth[$currencyId]); - //Log::debug(sprintf('Total net worth for currency #%d is %s', $currencyId, $netWorth[$currencyId])); + Log::debug(sprintf('Total net worth for currency #%d is %s', $currencyId, $netWorth[$currencyId])); } ksort($netWorth); @@ -131,7 +130,7 @@ class NetWorth implements NetWorthInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { @@ -144,4 +143,55 @@ class NetWorth implements NetWorthInterface $this->currencyRepos = app(CurrencyRepositoryInterface::class); $this->currencyRepos->setUser($this->user); } + + /** + * @inheritDoc + */ + public function sumNetWorthByCurrency(Carbon $date): array + { + /** + * Collect accounts + */ + $accounts = $this->getAccounts(); + $return = []; + $balances = app('steam')->balancesByAccounts($accounts, $date); + foreach ($accounts as $account) { + $currency = $this->accountRepository->getAccountCurrency($account); + $balance = $balances[$account->id] ?? '0'; + + // always subtract virtual balance. + $virtualBalance = (string)$account->virtual_balance; + if ('' !== $virtualBalance) { + $balance = bcsub($balance, $virtualBalance); + } + + $return[$currency->id] = $return[$currency->id] ?? [ + 'id' => (string)$currency->id, + 'name' => $currency->name, + 'symbol' => $currency->symbol, + 'code' => $currency->code, + 'decimal_places' => $currency->decimal_places, + 'sum' => '0', + ]; + $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $balance); + } + + return $return; + } + + /** + * @return Collection + */ + private function getAccounts(): Collection + { + $accounts = $this->accountRepository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT]); + $filtered = new Collection(); + /** @var Account $account */ + foreach ($accounts as $account) { + if (1 === (int)$this->accountRepository->getMetaValue($account, 'include_net_worth')) { + $filtered->push($account); + } + } + return $filtered; + } } diff --git a/app/Helpers/Report/NetWorthInterface.php b/app/Helpers/Report/NetWorthInterface.php index 0cb371b2c5..d263213a4a 100644 --- a/app/Helpers/Report/NetWorthInterface.php +++ b/app/Helpers/Report/NetWorthInterface.php @@ -34,6 +34,8 @@ use Illuminate\Support\Collection; interface NetWorthInterface { /** + * TODO unsure why this is deprecated. + * * Returns the user's net worth in an array with the following layout: * * - @@ -44,16 +46,26 @@ interface NetWorthInterface * This repeats for each currency the user has transactions in. * Result of this method is cached. * - * @param Collection $accounts - * @param Carbon $date - * + * @param Collection $accounts + * @param Carbon $date * @return array + * @deprecated */ public function getNetWorthByCurrency(Collection $accounts, Carbon $date): array; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; + /** + * TODO move to repository + * + * Same as above but cleaner function with less dependencies. + * + * @param Carbon $date + * + * @return array + */ + public function sumNetWorthByCurrency(Carbon $date): array; } diff --git a/app/Helpers/Report/PopupReport.php b/app/Helpers/Report/PopupReport.php index 66bbdd5228..15a2a8ea34 100644 --- a/app/Helpers/Report/PopupReport.php +++ b/app/Helpers/Report/PopupReport.php @@ -1,4 +1,5 @@ find((int) $currencyId); + $currency = $repos->find((int)$currencyId); } /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -99,8 +100,8 @@ class PopupReport implements PopupReportInterface /** * Collect the transactions for a budget. * - * @param Budget $budget - * @param array $attributes + * @param Budget $budget + * @param array $attributes * * @return array */ @@ -112,7 +113,7 @@ class PopupReport implements PopupReportInterface if (null !== $currencyId) { /** @var CurrencyRepositoryInterface $repos */ $repos = app(CurrencyRepositoryInterface::class); - $currency = $repos->find((int) $currencyId); + $currency = $repos->find((int)$currencyId); } /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -139,8 +140,8 @@ class PopupReport implements PopupReportInterface /** * Collect journals by a category. * - * @param Category|null $category - * @param array $attributes + * @param Category|null $category + * @param array $attributes * * @return array */ @@ -152,7 +153,7 @@ class PopupReport implements PopupReportInterface if (null !== $currencyId) { /** @var CurrencyRepositoryInterface $repos */ $repos = app(CurrencyRepositoryInterface::class); - $currency = $repos->find((int) $currencyId); + $currency = $repos->find((int)$currencyId); } /** @var GroupCollectorInterface $collector */ @@ -182,8 +183,8 @@ class PopupReport implements PopupReportInterface /** * Group transactions by expense. * - * @param Account $account - * @param array $attributes + * @param Account $account + * @param array $attributes * * @return array */ @@ -195,7 +196,7 @@ class PopupReport implements PopupReportInterface if (null !== $currencyId) { /** @var CurrencyRepositoryInterface $repos */ $repos = app(CurrencyRepositoryInterface::class); - $currency = $repos->find((int) $currencyId); + $currency = $repos->find((int)$currencyId); } /** @var JournalRepositoryInterface $repository */ @@ -228,8 +229,8 @@ class PopupReport implements PopupReportInterface /** * Collect transactions by income. * - * @param Account $account - * @param array $attributes + * @param Account $account + * @param array $attributes * * @return array */ diff --git a/app/Helpers/Report/PopupReportInterface.php b/app/Helpers/Report/PopupReportInterface.php index 4e46ee3805..2b5c4b821a 100644 --- a/app/Helpers/Report/PopupReportInterface.php +++ b/app/Helpers/Report/PopupReportInterface.php @@ -1,4 +1,5 @@ endOfMonth(); $months[$year]['months'][] = [ - 'formatted' => $start->isoFormat((string) trans('config.month_js')), + 'formatted' => $start->isoFormat((string)trans('config.month_js')), 'start' => $start->format('Y-m-d'), 'end' => $currentEnd->format('Y-m-d'), 'month' => $start->month, diff --git a/app/Helpers/Report/ReportHelperInterface.php b/app/Helpers/Report/ReportHelperInterface.php index e246ee946f..f5eb876bf3 100644 --- a/app/Helpers/Report/ReportHelperInterface.php +++ b/app/Helpers/Report/ReportHelperInterface.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-credit-card'); - app('view')->share('title', (string) trans('firefly.accounts')); + app('view')->share('title', (string)trans('firefly.accounts')); $this->repository = app(AccountRepositoryInterface::class); $this->attachments = app(AttachmentHelperInterface::class); @@ -74,17 +76,16 @@ class CreateController extends Controller /** * Create a new account. * - * @param Request $request - * @param string|null $objectType + * @param Request $request + * @param string $objectType * * @return Factory|View */ - public function create(Request $request, string $objectType = null) + public function create(Request $request, string $objectType) { - $objectType = $objectType ?? 'asset'; $defaultCurrency = app('amount')->getDefaultCurrency(); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); - $subTitle = (string) trans(sprintf('firefly.make_new_%s_account', $objectType)); + $subTitle = (string)trans(sprintf('firefly.make_new_%s_account', $objectType)); $roles = $this->getRoles(); $liabilityTypes = $this->getLiabilityTypes(); $hasOldInput = null !== $request->old('_token'); @@ -103,9 +104,9 @@ class CreateController extends Controller // interest calculation periods: $interestPeriods = [ - 'daily' => (string) trans('firefly.interest_calc_daily'), - 'monthly' => (string) trans('firefly.interest_calc_monthly'), - 'yearly' => (string) trans('firefly.interest_calc_yearly'), + 'daily' => (string)trans('firefly.interest_calc_daily'), + 'monthly' => (string)trans('firefly.interest_calc_monthly'), + 'yearly' => (string)trans('firefly.interest_calc_yearly'), ]; // pre fill some data @@ -113,7 +114,7 @@ class CreateController extends Controller 'preFilled', [ 'currency_id' => $defaultCurrency->id, - 'include_net_worth' => $hasOldInput ? (bool) $request->old('include_net_worth') : true, + 'include_net_worth' => $hasOldInput ? (bool)$request->old('include_net_worth') : true, ] ); @@ -133,18 +134,18 @@ class CreateController extends Controller /** * Store the new account. * - * @param AccountFormRequest $request + * @param AccountFormRequest $request * * @return RedirectResponse|Redirector * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function store(AccountFormRequest $request) { $data = $request->getAccountData(); $account = $this->repository->store($data); - $request->session()->flash('success', (string) trans('firefly.stored_new_account', ['name' => $account->name])); + $request->session()->flash('success', (string)trans('firefly.stored_new_account', ['name' => $account->name])); app('preferences')->mark(); Log::channel('audit')->info('Stored new account.', $data); @@ -163,7 +164,7 @@ class CreateController extends Controller $this->attachments->saveAttachmentsForModel($account, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { @@ -172,7 +173,7 @@ class CreateController extends Controller // redirect to previous URL. $redirect = redirect($this->getPreviousUrl('accounts.create.url')); - if (1 === (int) $request->get('create_another')) { + if (1 === (int)$request->get('create_another')) { // set value so create routine will not overwrite URL: $request->session()->put('accounts.create.fromStore', true); diff --git a/app/Http/Controllers/Account/DeleteController.php b/app/Http/Controllers/Account/DeleteController.php index 35901e59b7..51776f196a 100644 --- a/app/Http/Controllers/Account/DeleteController.php +++ b/app/Http/Controllers/Account/DeleteController.php @@ -53,7 +53,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-credit-card'); - app('view')->share('title', (string) trans('firefly.accounts')); + app('view')->share('title', (string)trans('firefly.accounts')); $this->repository = app(AccountRepositoryInterface::class); @@ -65,7 +65,7 @@ class DeleteController extends Controller /** * Delete account screen. * - * @param Account $account + * @param Account $account * * @return Factory|RedirectResponse|Redirector|View */ @@ -76,7 +76,7 @@ class DeleteController extends Controller } $typeName = config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type)); - $subTitle = (string) trans(sprintf('firefly.delete_%s_account', $typeName), ['name' => $account->name]); + $subTitle = (string)trans(sprintf('firefly.delete_%s_account', $typeName), ['name' => $account->name]); $accountList = app('expandedform')->makeSelectListWithEmpty($this->repository->getAccountsByType([$account->accountType->type])); $objectType = $typeName; unset($accountList[$account->id]); @@ -90,8 +90,8 @@ class DeleteController extends Controller /** * Delete the account. * - * @param Request $request - * @param Account $account + * @param Request $request + * @param Account $account * * @return RedirectResponse|Redirector */ @@ -104,14 +104,13 @@ class DeleteController extends Controller $type = $account->accountType->type; $typeName = config(sprintf('firefly.shortNamesByFullName.%s', $type)); $name = $account->name; - $moveTo = $this->repository->find((int) $request->get('move_account_before_delete')); + $moveTo = $this->repository->find((int)$request->get('move_account_before_delete')); $this->repository->destroy($account, $moveTo); - $request->session()->flash('success', (string) trans(sprintf('firefly.%s_deleted', $typeName), ['name' => $name])); + $request->session()->flash('success', (string)trans(sprintf('firefly.%s_deleted', $typeName), ['name' => $name])); app('preferences')->mark(); return redirect($this->getPreviousUrl('accounts.delete.url')); } - } diff --git a/app/Http/Controllers/Account/EditController.php b/app/Http/Controllers/Account/EditController.php index 363896bfe8..d2a71fb09e 100644 --- a/app/Http/Controllers/Account/EditController.php +++ b/app/Http/Controllers/Account/EditController.php @@ -28,7 +28,6 @@ use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\AccountFormRequest; use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Http\Controllers\ModelInformation; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; @@ -44,9 +43,8 @@ class EditController extends Controller { use ModelInformation; - private AttachmentHelperInterface $attachments; - private CurrencyRepositoryInterface $currencyRepos; - private AccountRepositoryInterface $repository; + private AttachmentHelperInterface $attachments; + private AccountRepositoryInterface $repository; /** * EditController constructor. @@ -59,11 +57,10 @@ class EditController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-credit-card'); - app('view')->share('title', (string) trans('firefly.accounts')); + app('view')->share('title', (string)trans('firefly.accounts')); - $this->repository = app(AccountRepositoryInterface::class); - $this->currencyRepos = app(CurrencyRepositoryInterface::class); - $this->attachments = app(AttachmentHelperInterface::class); + $this->repository = app(AccountRepositoryInterface::class); + $this->attachments = app(AttachmentHelperInterface::class); return $next($request); } @@ -73,9 +70,9 @@ class EditController extends Controller /** * Edit account overview. * - * @param Request $request - * @param Account $account - * @param AccountRepositoryInterface $repository + * @param Request $request + * @param Account $account + * @param AccountRepositoryInterface $repository * * @return Factory|RedirectResponse|Redirector|View */ @@ -86,7 +83,7 @@ class EditController extends Controller } $objectType = config('firefly.shortNamesByFullName')[$account->accountType->type]; - $subTitle = (string) trans(sprintf('firefly.edit_%s_account', $objectType), ['name' => $account->name]); + $subTitle = (string)trans(sprintf('firefly.edit_%s_account', $objectType), ['name' => $account->name]); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); $roles = $this->getRoles(); $liabilityTypes = $this->getLiabilityTypes(); @@ -111,9 +108,9 @@ class EditController extends Controller // interest calculation periods: $interestPeriods = [ - 'daily' => (string) trans('firefly.interest_calc_daily'), - 'monthly' => (string) trans('firefly.interest_calc_monthly'), - 'yearly' => (string) trans('firefly.interest_calc_yearly'), + 'daily' => (string)trans('firefly.interest_calc_daily'), + 'monthly' => (string)trans('firefly.interest_calc_monthly'), + 'yearly' => (string)trans('firefly.interest_calc_yearly'), ]; // put previous url in session if not redirect from store (not "return_to_edit"). @@ -122,7 +119,7 @@ class EditController extends Controller } $request->session()->forget('accounts.edit.fromUpdate'); - $openingBalanceAmount = (string) $repository->getOpeningBalanceAmount($account); + $openingBalanceAmount = (string)$repository->getOpeningBalanceAmount($account); if ('0' === $openingBalanceAmount) { $openingBalanceAmount = ''; } @@ -134,9 +131,9 @@ class EditController extends Controller $includeNetWorth = null === $includeNetWorth ? true : '1' === $includeNetWorth; // code to handle active-checkboxes - $hasOldInput = null !== $request->old('_token'); + $hasOldInput = null !== $request->old('_token'); $virtualBalance = null === $account->virtual_balance ? '0' : $account->virtual_balance; - $preFilled = [ + $preFilled = [ 'account_number' => $repository->getMetaValue($account, 'account_number'), 'account_role' => $repository->getMetaValue($account, 'account_role'), 'cc_type' => $repository->getMetaValue($account, 'cc_type'), @@ -152,7 +149,7 @@ class EditController extends Controller 'interest' => $repository->getMetaValue($account, 'interest'), 'interest_period' => $repository->getMetaValue($account, 'interest_period'), 'notes' => $this->repository->getNoteText($account), - 'active' => $hasOldInput ? (bool) $request->old('active') : $account->active, + 'active' => $hasOldInput ? (bool)$request->old('active') : $account->active, ]; if ('' === $openingBalanceAmount) { $preFilled['opening_balance'] = ''; @@ -181,8 +178,8 @@ class EditController extends Controller /** * Update the account. * - * @param AccountFormRequest $request - * @param Account $account + * @param AccountFormRequest $request + * @param Account $account * * @return $this|RedirectResponse|Redirector */ @@ -195,7 +192,7 @@ class EditController extends Controller $data = $request->getAccountData(); $this->repository->update($account, $data); - $request->session()->flash('success', (string) trans('firefly.updated_account', ['name' => $account->name])); + $request->session()->flash('success', (string)trans('firefly.updated_account', ['name' => $account->name])); // store new attachment(s): @@ -204,7 +201,7 @@ class EditController extends Controller $this->attachments->saveAttachmentsForModel($account, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { @@ -213,7 +210,7 @@ class EditController extends Controller // redirect $redirect = redirect($this->getPreviousUrl('accounts.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { + if (1 === (int)$request->get('return_to_edit')) { // set value so edit routine will not overwrite URL: $request->session()->put('accounts.edit.fromUpdate', true); diff --git a/app/Http/Controllers/Account/IndexController.php b/app/Http/Controllers/Account/IndexController.php index 31cbad77ac..b19d6c5558 100644 --- a/app/Http/Controllers/Account/IndexController.php +++ b/app/Http/Controllers/Account/IndexController.php @@ -1,4 +1,5 @@ . */ -/** @noinspection CallableParameterUseCaseInTypeContextInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; use Carbon\Carbon; -use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; @@ -34,7 +33,10 @@ use Illuminate\Contracts\View\Factory; use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\View\View; +use JsonException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * @@ -59,7 +61,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-credit-card'); - app('view')->share('title', (string) trans('firefly.accounts')); + app('view')->share('title', (string)trans('firefly.accounts')); $this->repository = app(AccountRepositoryInterface::class); @@ -69,26 +71,25 @@ class IndexController extends Controller } /** - * @param Request $request - * @param string $objectType + * @param Request $request + * @param string $objectType * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function inactive(Request $request, string $objectType) { - $objectType = $objectType ?? 'asset'; $inactivePage = true; - $subTitle = (string) trans(sprintf('firefly.%s_accounts_inactive', $objectType)); + $subTitle = (string)trans(sprintf('firefly.%s_accounts_inactive', $objectType)); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); $types = config(sprintf('firefly.accountTypesByIdentifier.%s', $objectType)); $collection = $this->repository->getInactiveAccountsByType($types); $total = $collection->count(); - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $accounts = $collection->slice(($page - 1) * $pageSize, $pageSize); unset($collection); /** @var Carbon $start */ @@ -109,10 +110,10 @@ class IndexController extends Controller $account->endBalance = $this->isInArray($endBalances, $account->id); $account->difference = bcsub($account->endBalance, $account->startBalance); $account->interest = app('steam')->bcround($this->repository->getMetaValue($account, 'interest'), 4); - $account->interestPeriod = (string) trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period'))); - $account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type)); + $account->interestPeriod = (string)trans(sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period'))); + $account->accountTypeString = (string)trans(sprintf('firefly.account_type_%s', $account->accountType->type)); $account->current_debt = '0'; - $account->iban = implode(' ', str_split((string) $account->iban, 4)); + $account->iban = implode(' ', str_split((string)$account->iban, 4)); } ); @@ -121,26 +122,24 @@ class IndexController extends Controller $accounts->setPath(route('accounts.inactive.index', [$objectType])); return view('accounts.index', compact('objectType', 'inactivePage', 'subTitleIcon', 'subTitle', 'page', 'accounts')); - } /** * Show list of accounts. * - * @param Request $request - * @param string $objectType + * @param Request $request + * @param string $objectType * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index(Request $request, string $objectType) { Log::debug(sprintf('Now at %s', __METHOD__)); - $objectType = $objectType ?? 'asset'; - $subTitle = (string) trans(sprintf('firefly.%s_accounts', $objectType)); + $subTitle = (string)trans(sprintf('firefly.%s_accounts', $objectType)); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $objectType)); $types = config(sprintf('firefly.accountTypesByIdentifier.%s', $objectType)); @@ -148,8 +147,8 @@ class IndexController extends Controller $collection = $this->repository->getActiveAccountsByType($types); $total = $collection->count(); - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $accounts = $collection->slice(($page - 1) * $pageSize, $pageSize); $inactiveCount = $this->repository->getInactiveAccountsByType($types)->count(); @@ -170,7 +169,6 @@ class IndexController extends Controller $accounts->each( function (Account $account) use ($activities, $startBalances, $endBalances) { - $interest = (string)$this->repository->getMetaValue($account, 'interest'); $interest = '' === $interest ? '0' : $interest; @@ -180,14 +178,14 @@ class IndexController extends Controller $account->endBalance = $this->isInArray($endBalances, $account->id); $account->difference = bcsub($account->endBalance, $account->startBalance); $account->interest = app('steam')->bcround($interest, 4); - $account->interestPeriod = (string) trans( + $account->interestPeriod = (string)trans( sprintf('firefly.interest_calc_%s', $this->repository->getMetaValue($account, 'interest_period')) ); - $account->accountTypeString = (string) trans(sprintf('firefly.account_type_%s', $account->accountType->type)); + $account->accountTypeString = (string)trans(sprintf('firefly.account_type_%s', $account->accountType->type)); $account->location = $this->repository->getLocation($account); $account->liability_direction = $this->repository->getMetaValue($account, 'liability_direction'); $account->current_debt = $this->repository->getMetaValue($account, 'current_debt') ?? '-'; - $account->iban = implode(' ', str_split((string) $account->iban, 4)); + $account->iban = implode(' ', str_split((string)$account->iban, 4)); } ); // make paginator: diff --git a/app/Http/Controllers/Account/ReconcileController.php b/app/Http/Controllers/Account/ReconcileController.php index cde88cbd16..d3ba54baae 100644 --- a/app/Http/Controllers/Account/ReconcileController.php +++ b/app/Http/Controllers/Account/ReconcileController.php @@ -1,4 +1,5 @@ . */ -/** @noinspection CallableParameterUseCaseInTypeContextInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; use Carbon\Carbon; -use Exception; use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\TransactionGroupFactory; @@ -34,26 +33,24 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\User; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; use Illuminate\Routing\Redirector; use Illuminate\View\View; +use JsonException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class ReconcileController. */ class ReconcileController extends Controller { - /** @var AccountRepositoryInterface The account repository */ - private $accountRepos; - /** @var CurrencyRepositoryInterface The currency repository */ - private $currencyRepos; - /** @var JournalRepositoryInterface Journals and transactions overview */ - private $repository; + private AccountRepositoryInterface $accountRepos; + private JournalRepositoryInterface $repository; /** * ReconcileController constructor. @@ -68,10 +65,9 @@ class ReconcileController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-credit-card'); - app('view')->share('title', (string) trans('firefly.accounts')); - $this->repository = app(JournalRepositoryInterface::class); - $this->accountRepos = app(AccountRepositoryInterface::class); - $this->currencyRepos = app(CurrencyRepositoryInterface::class); + app('view')->share('title', (string)trans('firefly.accounts')); + $this->repository = app(JournalRepositoryInterface::class); + $this->accountRepos = app(AccountRepositoryInterface::class); return $next($request); } @@ -81,15 +77,15 @@ class ReconcileController extends Controller /** * Reconciliation overview. * - * @param Account $account - * @param Carbon|null $start - * @param Carbon|null $end + * @param Account $account + * @param Carbon|null $start + * @param Carbon|null $end * * @return Factory|RedirectResponse|Redirector|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function reconcile(Account $account, Carbon $start = null, Carbon $end = null) { @@ -97,11 +93,9 @@ class ReconcileController extends Controller return $this->redirectAccountToAccount($account); } if (AccountType::ASSET !== $account->accountType->type) { - - session()->flash('error', (string) trans('firefly.must_be_asset_account')); + session()->flash('error', (string)trans('firefly.must_be_asset_account')); return redirect(route('accounts.index', [config(sprintf('firefly.shortNamesByFullName.%s', $account->accountType->type))])); - } $currency = $this->accountRepos->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); @@ -111,11 +105,10 @@ class ReconcileController extends Controller // get start and end if (null === $start && null === $end) { - /** @var Carbon $start */ - $start = clone session('start', app('navigation')->startOfPeriod(new Carbon, $range)); + $start = clone session('start', app('navigation')->startOfPeriod(new Carbon(), $range)); /** @var Carbon $end */ - $end = clone session('end', app('navigation')->endOfPeriod(new Carbon, $range)); + $end = clone session('end', app('navigation')->endOfPeriod(new Carbon(), $range)); } if (null === $end) { /** @var Carbon $end */ @@ -129,9 +122,9 @@ class ReconcileController extends Controller $startDate = clone $start; $startDate->subDay(); $startBalance = app('steam')->bcround(app('steam')->balance($account, $startDate), $currency->decimal_places); - $endBalance = app('steam')->bcround( app('steam')->balance($account, $end), $currency->decimal_places); + $endBalance = app('steam')->bcround(app('steam')->balance($account, $end), $currency->decimal_places); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); - $subTitle = (string) trans('firefly.reconcile_account', ['account' => $account->name]); + $subTitle = (string)trans('firefly.reconcile_account', ['account' => $account->name]); // various links $transactionsUrl = route('accounts.reconcile.transactions', [$account->id, '%start%', '%end%']); @@ -161,10 +154,10 @@ class ReconcileController extends Controller /** * Submit a new reconciliation. * - * @param ReconciliationStoreRequest $request - * @param Account $account - * @param Carbon $start - * @param Carbon $end + * @param ReconciliationStoreRequest $request + * @param Account $account + * @param Carbon $start + * @param Carbon $end * * @return RedirectResponse|Redirector * @throws DuplicateTransactionException @@ -180,7 +173,7 @@ class ReconcileController extends Controller /** @var string $journalId */ foreach ($data['journals'] as $journalId) { - $this->repository->reconcileById((int) $journalId); + $this->repository->reconcileById((int)$journalId); } Log::debug('Reconciled all transactions.'); @@ -197,10 +190,10 @@ class ReconcileController extends Controller Log::debug('End of routine.'); app('preferences')->mark(); if ('' === $result) { - session()->flash('success', (string) trans('firefly.reconciliation_stored')); + session()->flash('success', (string)trans('firefly.reconciliation_stored')); } if ('' !== $result) { - session()->flash('error', (string) trans('firefly.reconciliation_error', ['error' => $result])); + session()->flash('error', (string)trans('firefly.reconciliation_error', ['error' => $result])); } return redirect(route('accounts.show', [$account->id])); @@ -209,10 +202,10 @@ class ReconcileController extends Controller /** * Creates a reconciliation group. * - * @param Account $account - * @param Carbon $start - * @param Carbon $end - * @param string $difference + * @param Account $account + * @param Carbon $start + * @param Carbon $end + * @param string $difference * * @return RedirectResponse|Redirector|string * @throws DuplicateTransactionException @@ -240,8 +233,10 @@ class ReconcileController extends Controller // title: $description = trans( 'firefly.reconciliation_transaction_title', - ['from' => $start->isoFormat($this->monthAndDayFormat), - 'to' => $end->isoFormat($this->monthAndDayFormat)] + [ + 'from' => $start->isoFormat($this->monthAndDayFormat), + 'to' => $end->isoFormat($this->monthAndDayFormat), + ] ); $submission = [ 'user' => auth()->user()->id, diff --git a/app/Http/Controllers/Account/ShowController.php b/app/Http/Controllers/Account/ShowController.php index 4083d4100d..d7c182df7b 100644 --- a/app/Http/Controllers/Account/ShowController.php +++ b/app/Http/Controllers/Account/ShowController.php @@ -24,12 +24,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Account; use Carbon\Carbon; -use Exception; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; use FireflyIII\Repositories\Account\AccountRepositoryInterface; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Http\Controllers\PeriodOverview; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; @@ -37,6 +36,9 @@ use Illuminate\Http\Request; use Illuminate\Routing\Redirector; use Illuminate\Support\Collection; use Illuminate\View\View; +use JsonException; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class ShowController @@ -46,8 +48,7 @@ class ShowController extends Controller { use PeriodOverview; - private CurrencyRepositoryInterface $currencyRepos; - private AccountRepositoryInterface $repository; + private AccountRepositoryInterface $repository; /** * ShowController constructor. @@ -64,10 +65,9 @@ class ShowController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-credit-card'); - app('view')->share('title', (string) trans('firefly.accounts')); + app('view')->share('title', (string)trans('firefly.accounts')); - $this->repository = app(AccountRepositoryInterface::class); - $this->currencyRepos = app(CurrencyRepositoryInterface::class); + $this->repository = app(AccountRepositoryInterface::class); return $next($request); } @@ -77,16 +77,16 @@ class ShowController extends Controller /** * Show an account. * - * @param Request $request - * @param Account $account - * @param Carbon|null $start - * @param Carbon|null $end + * @param Request $request + * @param Account $account + * @param Carbon|null $start + * @param Carbon|null $end * * @return RedirectResponse|Redirector|Factory|View - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws FireflyException + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function show(Request $request, Account $account, Carbon $start = null, Carbon $end = null) { @@ -108,19 +108,19 @@ class ShowController extends Controller $attachments = $this->repository->getAttachments($account); $today = today(config('app.timezone')); $subTitleIcon = config(sprintf('firefly.subIconsByIdentifier.%s', $account->accountType->type)); - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $currency = $this->repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); $fStart = $start->isoFormat($this->monthAndDayFormat); $fEnd = $end->isoFormat($this->monthAndDayFormat); - $subTitle = (string) trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]); + $subTitle = (string)trans('firefly.journals_in_period_for_account', ['name' => $account->name, 'start' => $fStart, 'end' => $fEnd]); $chartUrl = route('chart.account.period', [$account->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); $firstTransaction = $this->repository->oldestJournalDate($account) ?? $start; $periods = $this->getAccountPeriodOverview($account, $firstTransaction, $end); // if layout = v2, overrule the page title. if ('v1' !== config('firefly.layout')) { - $subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]); + $subTitle = (string)trans('firefly.all_journals_for_account', ['name' => $account->name]); } @@ -162,14 +162,14 @@ class ShowController extends Controller /** * Show an account. * - * @param Request $request - * @param Account $account + * @param Request $request + * @param Account $account * * @return RedirectResponse|Redirector|Factory|View - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws FireflyException + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function showAll(Request $request, Account $account) { @@ -183,12 +183,12 @@ class ShowController extends Controller $end = today(config('app.timezone')); $today = today(config('app.timezone')); $start = $this->repository->oldestJournalDate($account) ?? Carbon::now()->startOfMonth(); - $subTitleIcon = config('firefly.subIconsByIdentifier.' . $account->accountType->type); - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $subTitleIcon = config('firefly.subIconsByIdentifier.'.$account->accountType->type); + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $currency = $this->repository->getAccountCurrency($account) ?? app('amount')->getDefaultCurrency(); - $subTitle = (string) trans('firefly.all_journals_for_account', ['name' => $account->name]); - $periods = new Collection; + $subTitle = (string)trans('firefly.all_journals_for_account', ['name' => $account->name]); + $periods = new Collection(); /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setAccounts(new Collection([$account]))->setLimit($pageSize)->setPage($page)->withAccountInformation()->withCategoryInformation(); diff --git a/app/Http/Controllers/Admin/ConfigurationController.php b/app/Http/Controllers/Admin/ConfigurationController.php index 0b15f2247b..1fbcfd7fa3 100644 --- a/app/Http/Controllers/Admin/ConfigurationController.php +++ b/app/Http/Controllers/Admin/ConfigurationController.php @@ -1,4 +1,5 @@ middleware( static function ($request, $next) { - app('view')->share('title', (string) trans('firefly.administration')); + app('view')->share('title', (string)trans('firefly.administration')); app('view')->share('mainTitleIcon', 'fa-hand-spock-o'); return $next($request); @@ -61,12 +64,12 @@ class ConfigurationController extends Controller * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index() { - $subTitle = (string) trans('firefly.instance_configuration'); + $subTitle = (string)trans('firefly.instance_configuration'); $subTitleIcon = 'fa-wrench'; Log::channel('audit')->info('User visits admin config index.'); @@ -86,7 +89,7 @@ class ConfigurationController extends Controller /** * Store new configuration values. * - * @param ConfigurationRequest $request + * @param ConfigurationRequest $request * * @return RedirectResponse */ @@ -102,7 +105,7 @@ class ConfigurationController extends Controller app('fireflyconfig')->set('is_demo_site', $data['is_demo_site']); // flash message - session()->flash('success', (string) trans('firefly.configuration_updated')); + session()->flash('success', (string)trans('firefly.configuration_updated')); app('preferences')->mark(); return redirect()->route('admin.configuration.index'); diff --git a/app/Http/Controllers/Admin/HomeController.php b/app/Http/Controllers/Admin/HomeController.php index c6527c210b..55f945d397 100644 --- a/app/Http/Controllers/Admin/HomeController.php +++ b/app/Http/Controllers/Admin/HomeController.php @@ -1,4 +1,5 @@ info('User visits admin index.'); - $title = (string) trans('firefly.administration'); + $title = (string)trans('firefly.administration'); $mainTitleIcon = 'fa-hand-spock-o'; $email = auth()->user()->email; $pref = app('preferences')->get('remote_guard_alt_email'); if (null !== $pref && is_string($pref->data)) { $email = $pref->data; } - Log::debug('Email is ', [$email]); - return view('admin.index', compact('title', 'mainTitleIcon', 'email')); + // admin notification settings: + $notifications = []; + foreach (config('firefly.admin_notifications') as $item) { + $notifications[$item] = FireflyConfig::get(sprintf('notification_%s', $item), true)->data; + } + $slackUrl = FireflyConfig::get('slack_webhook_url', '')->data; + + return view('admin.index', compact('title', 'mainTitleIcon', 'email', 'notifications', 'slackUrl')); + } + + public function notifications(Request $request): RedirectResponse + { + foreach (config('firefly.admin_notifications') as $item) { + $value = false; + if ($request->has(sprintf('notification_%s', $item))) { + $value = true; + } + FireflyConfig::set(sprintf('notification_%s', $item), $value); + } + $url = (string)$request->get('slackUrl'); + if ('' === $url) { + FireflyConfig::delete('slack_webhook_url'); + } + if (str_starts_with($url, 'https://hooks.slack.com/services/')) { + FireflyConfig::set('slack_webhook_url', $url); + } + + session()->flash('success', (string)trans('firefly.notification_settings_saved')); + return redirect(route('admin.index')); } /** * Send a test message to the admin. * - * @param Request $request + * @param Request $request * * @return RedirectResponse|Redirector */ @@ -87,7 +118,7 @@ class HomeController extends Controller $user = auth()->user(); Log::debug('Now in testMessage() controller.'); event(new AdminRequestedTestMessage($user)); - session()->flash('info', (string) trans('firefly.send_test_triggered')); + 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 5cda12b263..7adf4717fe 100644 --- a/app/Http/Controllers/Admin/LinkController.php +++ b/app/Http/Controllers/Admin/LinkController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.administration')); + app('view')->share('title', (string)trans('firefly.administration')); app('view')->share('mainTitleIcon', 'fa-hand-spock-o'); $this->repository = app(LinkTypeRepositoryInterface::class); @@ -71,7 +72,7 @@ class LinkController extends Controller { Log::channel('audit')->info('User visits link index.'); - $subTitle = (string) trans('firefly.create_new_link_type'); + $subTitle = (string)trans('firefly.create_new_link_type'); $subTitleIcon = 'fa-link'; // put previous url in session if not redirect from store (not "create another"). @@ -85,25 +86,25 @@ class LinkController extends Controller /** * Delete a link form. * - * @param Request $request - * @param LinkType $linkType + * @param Request $request + * @param LinkType $linkType * * @return Factory|RedirectResponse|Redirector|View */ public function delete(Request $request, LinkType $linkType) { if (!$linkType->editable) { - $request->session()->flash('error', (string) trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)])); + $request->session()->flash('error', (string)trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)])); return redirect(route('admin.links.index')); } Log::channel('audit')->info(sprintf('User wants to delete link type #%d', $linkType->id)); - $subTitle = (string) trans('firefly.delete_link_type', ['name' => $linkType->name]); + $subTitle = (string)trans('firefly.delete_link_type', ['name' => $linkType->name]); $otherTypes = $this->repository->get(); $count = $this->repository->countJournals($linkType); $moveTo = []; - $moveTo[0] = (string) trans('firefly.do_not_save_connection'); + $moveTo[0] = (string)trans('firefly.do_not_save_connection'); /** @var LinkType $otherType */ foreach ($otherTypes as $otherType) { @@ -121,8 +122,8 @@ class LinkController extends Controller /** * Actually destroy the link. * - * @param Request $request - * @param LinkType $linkType + * @param Request $request + * @param LinkType $linkType * * @return RedirectResponse|Redirector */ @@ -130,10 +131,10 @@ class LinkController extends Controller { Log::channel('audit')->info(sprintf('User destroyed link type #%d', $linkType->id)); $name = $linkType->name; - $moveTo = $this->repository->find((int) $request->get('move_link_type_before_delete')); + $moveTo = $this->repository->find((int)$request->get('move_link_type_before_delete')); $this->repository->destroy($linkType, $moveTo); - $request->session()->flash('success', (string) trans('firefly.deleted_link_type', ['name' => $name])); + $request->session()->flash('success', (string)trans('firefly.deleted_link_type', ['name' => $name])); app('preferences')->mark(); return redirect($this->getPreviousUrl('link-types.delete.url')); @@ -142,19 +143,19 @@ class LinkController extends Controller /** * Edit a link form. * - * @param Request $request - * @param LinkType $linkType + * @param Request $request + * @param LinkType $linkType * * @return Factory|RedirectResponse|Redirector|View */ public function edit(Request $request, LinkType $linkType) { if (!$linkType->editable) { - $request->session()->flash('error', (string) trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)])); + $request->session()->flash('error', (string)trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)])); return redirect(route('admin.links.index')); } - $subTitle = (string) trans('firefly.edit_link_type', ['name' => $linkType->name]); + $subTitle = (string)trans('firefly.edit_link_type', ['name' => $linkType->name]); $subTitleIcon = 'fa-link'; Log::channel('audit')->info(sprintf('User wants to edit link type #%d', $linkType->id)); @@ -175,7 +176,7 @@ class LinkController extends Controller */ public function index() { - $subTitle = (string) trans('firefly.journal_link_configuration'); + $subTitle = (string)trans('firefly.journal_link_configuration'); $subTitleIcon = 'fa-link'; $linkTypes = $this->repository->get(); @@ -192,13 +193,13 @@ class LinkController extends Controller /** * Show a single link. * - * @param LinkType $linkType + * @param LinkType $linkType * * @return Factory|View */ public function show(LinkType $linkType) { - $subTitle = (string) trans('firefly.overview_for_link', ['name' => $linkType->name]); + $subTitle = (string)trans('firefly.overview_for_link', ['name' => $linkType->name]); $subTitleIcon = 'fa-link'; $links = $this->repository->getJournalLinks($linkType); @@ -210,7 +211,7 @@ class LinkController extends Controller /** * Store the new link. * - * @param LinkTypeFormRequest $request + * @param LinkTypeFormRequest $request * * @return $this|RedirectResponse|Redirector */ @@ -225,9 +226,9 @@ class LinkController extends Controller Log::channel('audit')->info('User stored new link type.', $linkType->toArray()); - $request->session()->flash('success', (string) trans('firefly.stored_new_link_type', ['name' => $linkType->name])); + $request->session()->flash('success', (string)trans('firefly.stored_new_link_type', ['name' => $linkType->name])); $redirect = redirect($this->getPreviousUrl('link-types.create.url')); - if (1 === (int) $request->get('create_another')) { + if (1 === (int)$request->get('create_another')) { // set value so create routine will not overwrite URL: $request->session()->put('link-types.create.fromStore', true); @@ -241,15 +242,15 @@ class LinkController extends Controller /** * Update an existing link. * - * @param LinkTypeFormRequest $request - * @param LinkType $linkType + * @param LinkTypeFormRequest $request + * @param LinkType $linkType * * @return $this|RedirectResponse|Redirector */ public function update(LinkTypeFormRequest $request, LinkType $linkType) { if (!$linkType->editable) { - $request->session()->flash('error', (string) trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)])); + $request->session()->flash('error', (string)trans('firefly.cannot_edit_link_type', ['name' => e($linkType->name)])); return redirect(route('admin.links.index')); } @@ -263,10 +264,10 @@ class LinkController extends Controller Log::channel('audit')->info(sprintf('User update link type #%d.', $linkType->id), $data); - $request->session()->flash('success', (string) trans('firefly.updated_link_type', ['name' => $linkType->name])); + $request->session()->flash('success', (string)trans('firefly.updated_link_type', ['name' => $linkType->name])); app('preferences')->mark(); $redirect = redirect($this->getPreviousUrl('link-types.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { + 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); diff --git a/app/Http/Controllers/Admin/UpdateController.php b/app/Http/Controllers/Admin/UpdateController.php index e5444ba97d..5334f27843 100644 --- a/app/Http/Controllers/Admin/UpdateController.php +++ b/app/Http/Controllers/Admin/UpdateController.php @@ -1,4 +1,5 @@ middleware( static function ($request, $next) { - app('view')->share('title', (string) trans('firefly.administration')); + app('view')->share('title', (string)trans('firefly.administration')); app('view')->share('mainTitleIcon', 'fa-hand-spock-o'); return $next($request); @@ -61,27 +64,27 @@ class UpdateController extends Controller * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index() { - $subTitle = (string) trans('firefly.update_check_title'); + $subTitle = (string)trans('firefly.update_check_title'); $subTitleIcon = 'fa-star'; $permission = app('fireflyconfig')->get('permission_update_check', -1); $channel = app('fireflyconfig')->get('update_channel', 'stable'); $selected = $permission->data; $channelSelected = $channel->data; $options = [ - -1 => (string) trans('firefly.updates_ask_me_later'), - 0 => (string) trans('firefly.updates_do_not_check'), - 1 => (string) trans('firefly.updates_enable_check'), + -1 => (string)trans('firefly.updates_ask_me_later'), + 0 => (string)trans('firefly.updates_do_not_check'), + 1 => (string)trans('firefly.updates_enable_check'), ]; $channelOptions = [ - 'stable' => (string) trans('firefly.update_channel_stable'), - 'beta' => (string) trans('firefly.update_channel_beta'), - 'alpha' => (string) trans('firefly.update_channel_alpha'), + 'stable' => (string)trans('firefly.update_channel_stable'), + 'beta' => (string)trans('firefly.update_channel_beta'), + 'alpha' => (string)trans('firefly.update_channel_alpha'), ]; return view('admin.update.index', compact('subTitle', 'subTitleIcon', 'selected', 'options', 'channelSelected', 'channelOptions')); @@ -90,20 +93,20 @@ class UpdateController extends Controller /** * Post new settings. * - * @param Request $request + * @param Request $request * * @return RedirectResponse|Redirector */ public function post(Request $request) { - $checkForUpdates = (int) $request->get('check_for_updates'); + $checkForUpdates = (int)$request->get('check_for_updates'); $channel = $request->get('update_channel'); $channel = in_array($channel, ['stable', 'beta', 'alpha'], true) ? $channel : 'stable'; app('fireflyconfig')->set('permission_update_check', $checkForUpdates); app('fireflyconfig')->set('last_update_check', time()); app('fireflyconfig')->set('update_channel', $channel); - session()->flash('success', (string) trans('firefly.configuration_updated')); + session()->flash('success', (string)trans('firefly.configuration_updated')); return redirect(route('admin.update-check')); } diff --git a/app/Http/Controllers/Admin/UserController.php b/app/Http/Controllers/Admin/UserController.php index cde875d4d7..b5107d4d28 100644 --- a/app/Http/Controllers/Admin/UserController.php +++ b/app/Http/Controllers/Admin/UserController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.administration')); + app('view')->share('title', (string)trans('firefly.administration')); app('view')->share('mainTitleIcon', 'fa-hand-spock-o'); $this->repository = app(UserRepositoryInterface::class); @@ -65,7 +68,7 @@ class UserController extends Controller } /** - * @param User $user + * @param User $user * * @return Application|Factory|RedirectResponse|Redirector|View */ @@ -77,7 +80,7 @@ class UserController extends Controller return redirect(route('admin.users')); } - $subTitle = (string) trans('firefly.delete_user', ['email' => $user->email]); + $subTitle = (string)trans('firefly.delete_user', ['email' => $user->email]); return view('admin.users.delete', compact('user', 'subTitle')); } @@ -85,7 +88,7 @@ class UserController extends Controller /** * Destroy a user. * - * @param User $user + * @param User $user * * @return RedirectResponse|Redirector */ @@ -97,7 +100,7 @@ class UserController extends Controller return redirect(route('admin.users')); } $this->repository->destroy($user); - session()->flash('success', (string) trans('firefly.user_deleted')); + session()->flash('success', (string)trans('firefly.user_deleted')); return redirect(route('admin.users')); } @@ -105,7 +108,7 @@ class UserController extends Controller /** * Edit user form. * - * @param User $user + * @param User $user * * @return Factory|View */ @@ -121,15 +124,15 @@ class UserController extends Controller } session()->forget('users.edit.fromUpdate'); - $subTitle = (string) trans('firefly.edit_user', ['email' => $user->email]); + $subTitle = (string)trans('firefly.edit_user', ['email' => $user->email]); $subTitleIcon = 'fa-user-o'; $currentUser = auth()->user(); $isAdmin = $this->repository->hasRole($user, 'owner'); $codes = [ - '' => (string) trans('firefly.no_block_code'), - 'bounced' => (string) trans('firefly.block_code_bounced'), - 'expired' => (string) trans('firefly.block_code_expired'), - 'email_changed' => (string) trans('firefly.block_code_email_changed'), + '' => (string)trans('firefly.no_block_code'), + 'bounced' => (string)trans('firefly.block_code_bounced'), + 'expired' => (string)trans('firefly.block_code_expired'), + 'email_changed' => (string)trans('firefly.block_code_email_changed'), ]; return view('admin.users.edit', compact('user', 'canEditDetails', 'subTitle', 'subTitleIcon', 'codes', 'currentUser', 'isAdmin')); @@ -142,9 +145,17 @@ class UserController extends Controller */ public function index() { - $subTitle = (string) trans('firefly.user_administration'); - $subTitleIcon = 'fa-users'; - $users = $this->repository->all(); + $subTitle = (string)trans('firefly.user_administration'); + $subTitleIcon = 'fa-users'; + $users = $this->repository->all(); + $singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data; + $allowInvites = false; + if (!$this->externalIdentity && $singleUserMode) { + // also registration enabled. + $allowInvites = true; + } + + $invitedUsers = $this->repository->getInvitedUsers(); // add meta stuff. $users->each( @@ -154,21 +165,37 @@ class UserController extends Controller } ); - return view('admin.users.index', compact('subTitle', 'subTitleIcon', 'users')); + return view('admin.users.index', compact('subTitle', 'subTitleIcon', 'users', 'allowInvites', 'invitedUsers')); + } + + /** + * @param InviteUserFormRequest $request + * @return RedirectResponse + */ + public function invite(InviteUserFormRequest $request): RedirectResponse + { + $address = (string)$request->get('invited_user'); + $invitee = $this->repository->inviteUser(auth()->user(), $address); + session()->flash('info', trans('firefly.user_is_invited', ['address' => $address])); + + // event! + event(new InvitationCreated($invitee)); + + return redirect(route('admin.users')); } /** * Show single user. * - * @param User $user + * @param User $user * * @return Factory|View */ public function show(User $user) { - $title = (string) trans('firefly.administration'); + $title = (string)trans('firefly.administration'); $mainTitleIcon = 'fa-hand-spock-o'; - $subTitle = (string) trans('firefly.single_user_administration', ['email' => $user->email]); + $subTitle = (string)trans('firefly.single_user_administration', ['email' => $user->email]); $subTitleIcon = 'fa-user'; $information = $this->repository->getUserData($user); @@ -188,8 +215,8 @@ class UserController extends Controller /** * Update single user. * - * @param UserFormRequest $request - * @param User $user + * @param UserFormRequest $request + * @param User $user * * @return $this|RedirectResponse|Redirector */ @@ -215,15 +242,13 @@ class UserController extends Controller $this->repository->changeStatus($user, $data['blocked'], $data['blocked_code']); $this->repository->updateEmail($user, $data['email']); - session()->flash('success', (string) trans('firefly.updated_user', ['email' => $user->email])); + session()->flash('success', (string)trans('firefly.updated_user', ['email' => $user->email])); app('preferences')->mark(); $redirect = redirect($this->getPreviousUrl('users.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { session()->put('users.edit.fromUpdate', true); $redirect = redirect(route('admin.users.edit', [$user->id]))->withInput(['return_to_edit' => 1]); - } // redirect to previous URL. diff --git a/app/Http/Controllers/AttachmentController.php b/app/Http/Controllers/AttachmentController.php index 2fe07a7d0f..db72125f8a 100644 --- a/app/Http/Controllers/AttachmentController.php +++ b/app/Http/Controllers/AttachmentController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-paperclip'); - app('view')->share('title', (string) trans('firefly.attachments')); + app('view')->share('title', (string)trans('firefly.attachments')); $this->repository = app(AttachmentRepositoryInterface::class); return $next($request); @@ -68,13 +68,13 @@ class AttachmentController extends Controller /** * Form to delete an attachment. * - * @param Attachment $attachment + * @param Attachment $attachment * * @return Factory|View */ public function delete(Attachment $attachment) { - $subTitle = (string) trans('firefly.delete_attachment', ['name' => $attachment->filename]); + $subTitle = (string)trans('firefly.delete_attachment', ['name' => $attachment->filename]); // put previous url in session $this->rememberPreviousUrl('attachments.delete.url'); @@ -85,8 +85,8 @@ class AttachmentController extends Controller /** * Destroy attachment. * - * @param Request $request - * @param Attachment $attachment + * @param Request $request + * @param Attachment $attachment * * @return RedirectResponse|Redirector */ @@ -96,7 +96,7 @@ class AttachmentController extends Controller $this->repository->destroy($attachment); - $request->session()->flash('success', (string) trans('firefly.attachment_deleted', ['name' => $name])); + $request->session()->flash('success', (string)trans('firefly.attachment_deleted', ['name' => $name])); app('preferences')->mark(); return redirect($this->getPreviousUrl('attachments.delete.url')); @@ -105,7 +105,7 @@ class AttachmentController extends Controller /** * Download attachment to PC. * - * @param Attachment $attachment + * @param Attachment $attachment * * @return LaravelResponse * @@ -122,7 +122,7 @@ class AttachmentController extends Controller $response ->header('Content-Description', 'File Transfer') ->header('Content-Type', 'application/octet-stream') - ->header('Content-Disposition', 'attachment; filename=' . $quoted) + ->header('Content-Disposition', 'attachment; filename='.$quoted) ->header('Content-Transfer-Encoding', 'binary') ->header('Connection', 'Keep-Alive') ->header('Expires', '0') @@ -138,15 +138,15 @@ class AttachmentController extends Controller /** * Edit an attachment. * - * @param Request $request - * @param Attachment $attachment + * @param Request $request + * @param Attachment $attachment * * @return Factory|View */ public function edit(Request $request, Attachment $attachment) { $subTitleIcon = 'fa-pencil'; - $subTitle = (string) trans('firefly.edit_attachment', ['name' => $attachment->filename]); + $subTitle = (string)trans('firefly.edit_attachment', ['name' => $attachment->filename]); // put previous url in session if not redirect from store (not "return_to_edit"). if (true !== session('attachments.edit.fromUpdate')) { @@ -183,8 +183,8 @@ class AttachmentController extends Controller /** * Update attachment. * - * @param AttachmentFormRequest $request - * @param Attachment $attachment + * @param AttachmentFormRequest $request + * @param Attachment $attachment * * @return RedirectResponse */ @@ -193,16 +193,14 @@ class AttachmentController extends Controller $data = $request->getAttachmentData(); $this->repository->update($attachment, $data); - $request->session()->flash('success', (string) trans('firefly.attachment_updated', ['name' => $attachment->filename])); + $request->session()->flash('success', (string)trans('firefly.attachment_updated', ['name' => $attachment->filename])); app('preferences')->mark(); $redirect = redirect($this->getPreviousUrl('attachments.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { $request->session()->put('attachments.edit.fromUpdate', true); $redirect = redirect(route('attachments.edit', [$attachment->id]))->withInput(['return_to_edit' => 1]); - } // redirect to previous URL. @@ -212,8 +210,8 @@ class AttachmentController extends Controller /** * View attachment in browser. * - * @param Request $request - * @param Attachment $attachment + * @param Request $request + * @param Attachment $attachment * * @return LaravelResponse * @throws FireflyException @@ -243,7 +241,7 @@ class AttachmentController extends Controller [ 'Content-Security-Policy' => implode('; ', $csp), 'Content-Type' => $attachment->mime, - 'Content-Disposition' => 'inline; filename="' . $attachment->filename . '"', + 'Content-Disposition' => 'inline; filename="'.$attachment->filename.'"', ] ); } diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index dbdd2d7af3..bd0004d992 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -1,4 +1,5 @@ get('email'))->first(); if (null !== $user && $repository->hasRole($user, 'demo')) { - return back()->withErrors(['email' => (string) trans('firefly.cannot_reset_demo_user')]); + return back()->withErrors(['email' => (string)trans('firefly.cannot_reset_demo_user')]); } // We will send the password reset link to this user. Once we have attempted @@ -110,8 +113,8 @@ class ForgotPasswordController extends Controller * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function showLinkRequestForm() { @@ -126,7 +129,7 @@ class ForgotPasswordController extends Controller $singleUserMode = app('fireflyconfig')->get('single_user_mode', config('firefly.configuration.single_user_mode'))->data; $userCount = User::count(); $allowRegistration = true; - $pageTitle = (string) trans('firefly.forgot_pw_page_title'); + $pageTitle = (string)trans('firefly.forgot_pw_page_title'); if (true === $singleUserMode && $userCount > 0) { $allowRegistration = false; } diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php index 80dfe094d1..1c6f2ae1d5 100644 --- a/app/Http/Controllers/Auth/LoginController.php +++ b/app/Http/Controllers/Auth/LoginController.php @@ -1,4 +1,5 @@ sendLoginResponse($request); } - Log::warning('Login attempt failed.'); + app('log')->warning('Login attempt failed.'); /** Copied directly from AuthenticatesUsers, but with logging added: */ // If the login attempt was unsuccessful we will increment the number of attempts @@ -141,7 +142,7 @@ class LoginController extends Controller /** * Get the failed login response instance. * - * @param Request $request + * @param Request $request * * @return void * @@ -162,9 +163,9 @@ class LoginController extends Controller /** * Log the user out of the application. * - * @param Request $request + * @param Request $request * - * @return Response + * @return RedirectResponse|Redirector|Response */ public function logout(Request $request) { @@ -199,12 +200,12 @@ class LoginController extends Controller /** * Show the application's login form. * - * @param Request $request + * @param Request $request * * @return Factory|Application|View|Redirector|RedirectResponse * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function showLoginForm(Request $request) { @@ -212,7 +213,7 @@ class LoginController extends Controller $count = DB::table('users')->count(); $guard = config('auth.defaults.guard'); - $title = (string) trans('firefly.login_page_title'); + $title = (string)trans('firefly.login_page_title'); if (0 === $count && 'web' === $guard) { return redirect(route('register')); diff --git a/app/Http/Controllers/Auth/RegisterController.php b/app/Http/Controllers/Auth/RegisterController.php index e21fa46e75..e82f23449e 100644 --- a/app/Http/Controllers/Auth/RegisterController.php +++ b/app/Http/Controllers/Auth/RegisterController.php @@ -1,4 +1,5 @@ allowedToRegister(); + $inviteCode = (string)$request->get('invite_code'); + $repository = app(UserRepositoryInterface::class); + $validCode = $repository->validateInviteCode($inviteCode); - if (false === $allowRegistration) { + if (false === $allowRegistration && false === $validCode) { throw new FireflyException('Registration is currently not available :('); } + $this->validator($request->all())->validate(); $user = $this->createUser($request->all()); Log::info(sprintf('Registered new user %s', $user->email)); @@ -100,10 +106,14 @@ class RegisterController extends Controller $this->guard()->login($user); - session()->flash('success', (string) trans('firefly.registered')); + session()->flash('success', (string)trans('firefly.registered')); $this->registered($request, $user); + if ($validCode) { + $repository->redeemCode($inviteCode); + } + return redirect($this->redirectPath()); } @@ -131,10 +141,45 @@ class RegisterController extends Controller return $allowRegistration; } + /** + * Show the application registration form if the invitation code is valid. + * + * @param Request $request + * + * @return Factory|View + * @throws ContainerExceptionInterface + * @throws FireflyException + * @throws NotFoundExceptionInterface + */ + public function showInviteForm(Request $request, string $code) + { + $isDemoSite = app('fireflyconfig')->get('is_demo_site', config('firefly.configuration.is_demo_site'))->data; + $pageTitle = (string)trans('firefly.register_page_title'); + $repository = app(UserRepositoryInterface::class); + $allowRegistration = $this->allowedToRegister(); + $inviteCode = $code; + $validCode = $repository->validateInviteCode($inviteCode); + + if (true === $allowRegistration) { + $message = 'You do not need an invite code on this installation.'; + + return view('error', compact('message')); + } + if (false === $validCode) { + $message = 'Invalid code.'; + + return view('error', compact('message')); + } + + $email = $request->old('email'); + + return view('auth.register', compact('isDemoSite', 'email', 'pageTitle', 'inviteCode')); + } + /** * Show the application registration form. * - * @param Request $request + * @param Request $request * * @return Factory|View * @throws ContainerExceptionInterface @@ -144,7 +189,7 @@ class RegisterController extends Controller public function showRegistrationForm(Request $request) { $isDemoSite = app('fireflyconfig')->get('is_demo_site', config('firefly.configuration.is_demo_site'))->data; - $pageTitle = (string) trans('firefly.register_page_title'); + $pageTitle = (string)trans('firefly.register_page_title'); $allowRegistration = $this->allowedToRegister(); if (false === $allowRegistration) { diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 7b28f677c2..a81b36a5e3 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -1,4 +1,5 @@ get('single_user_mode', config('firefly.configuration.single_user_mode'))->data; $userCount = User::count(); $allowRegistration = true; - $pageTitle = (string) trans('firefly.reset_pw_page_title'); + $pageTitle = (string)trans('firefly.reset_pw_page_title'); if (true === $singleUserMode && $userCount > 0) { $allowRegistration = false; } - /** @noinspection PhpUndefinedFieldInspection */ return view('auth.passwords.reset')->with( ['token' => $token, 'email' => $request->email, 'allowRegistration' => $allowRegistration, 'pageTitle' => $pageTitle] ); diff --git a/app/Http/Controllers/Auth/TwoFactorController.php b/app/Http/Controllers/Auth/TwoFactorController.php index bec3852b4a..c50ec7051a 100644 --- a/app/Http/Controllers/Auth/TwoFactorController.php +++ b/app/Http/Controllers/Auth/TwoFactorController.php @@ -1,4 +1,5 @@ user(); $siteOwner = config('firefly.site_owner'); - $title = (string) trans('firefly.two_factor_forgot_title'); + $title = (string)trans('firefly.two_factor_forgot_title'); return view('auth.lost-two-factor', compact('user', 'siteOwner', 'title')); } /** - * @param Request $request + * @param Request $request * * @return RedirectResponse|Redirector */ @@ -61,7 +62,7 @@ class TwoFactorController extends Controller { /** @var array $mfaHistory */ $mfaHistory = Preferences::get('mfa_history', [])->data; - $mfaCode = (string) $request->get('one_time_password'); + $mfaCode = (string)$request->get('one_time_password'); // is in history? then refuse to use it. if ($this->inMFAHistory($mfaCode, $mfaHistory)) { @@ -101,8 +102,8 @@ class TwoFactorController extends Controller * Each MFA history has a timestamp and a code, saving the MFA entries for 5 minutes. So if the * submitted MFA code has been submitted in the last 5 minutes, it won't work despite being valid. * - * @param string $mfaCode - * @param array $mfaHistory + * @param string $mfaCode + * @param array $mfaHistory * * @return bool */ @@ -143,7 +144,7 @@ class TwoFactorController extends Controller } /** - * @param string $mfaCode + * @param string $mfaCode */ private function addToMFAHistory(string $mfaCode): void { @@ -162,7 +163,7 @@ class TwoFactorController extends Controller /** * Checks if code is in users backup codes. * - * @param string $mfaCode + * @param string $mfaCode * * @return bool */ @@ -179,7 +180,7 @@ class TwoFactorController extends Controller /** * Remove the used code from the list of backup codes. * - * @param string $mfaCode + * @param string $mfaCode */ private function removeFromBackupCodes(string $mfaCode): void { diff --git a/app/Http/Controllers/Bill/CreateController.php b/app/Http/Controllers/Bill/CreateController.php index 4520d73561..0035275412 100644 --- a/app/Http/Controllers/Bill/CreateController.php +++ b/app/Http/Controllers/Bill/CreateController.php @@ -54,7 +54,7 @@ class CreateController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.bills')); + app('view')->share('title', (string)trans('firefly.bills')); app('view')->share('mainTitleIcon', 'fa-calendar-o'); $this->attachments = app(AttachmentHelperInterface::class); $this->repository = app(BillRepositoryInterface::class); @@ -67,7 +67,7 @@ class CreateController extends Controller /** * Create a new bill. * - * @param Request $request + * @param Request $request * * @return Factory|View */ @@ -77,9 +77,9 @@ class CreateController extends Controller /** @var array $billPeriods */ $billPeriods = config('firefly.bill_periods'); foreach ($billPeriods as $current) { - $periods[$current] = (string) trans('firefly.repeat_freq_' . $current); + $periods[$current] = (string)trans('firefly.repeat_freq_'.$current); } - $subTitle = (string) trans('firefly.create_new_bill'); + $subTitle = (string)trans('firefly.create_new_bill'); $defaultCurrency = app('amount')->getDefaultCurrency(); // put previous url in session if not redirect from store (not "create another"). @@ -94,7 +94,7 @@ class CreateController extends Controller /** * Store a new bill. * - * @param BillStoreRequest $request + * @param BillStoreRequest $request * * @return RedirectResponse * @@ -108,11 +108,11 @@ class CreateController extends Controller $bill = $this->repository->store($billData); } catch (FireflyException $e) { Log::error($e->getMessage()); - $request->session()->flash('error', (string) trans('firefly.bill_store_error')); + $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])); + $request->session()->flash('success', (string)trans('firefly.stored_new_bill', ['name' => $bill->name])); app('preferences')->mark(); /** @var array $files */ @@ -121,7 +121,7 @@ class CreateController extends Controller $this->attachments->saveAttachmentsForModel($bill, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { diff --git a/app/Http/Controllers/Bill/DeleteController.php b/app/Http/Controllers/Bill/DeleteController.php index ada888dec3..7b812f28ac 100644 --- a/app/Http/Controllers/Bill/DeleteController.php +++ b/app/Http/Controllers/Bill/DeleteController.php @@ -53,7 +53,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.bills')); + app('view')->share('title', (string)trans('firefly.bills')); app('view')->share('mainTitleIcon', 'fa-calendar-o'); $this->repository = app(BillRepositoryInterface::class); @@ -65,7 +65,7 @@ class DeleteController extends Controller /** * Delete a bill. * - * @param Bill $bill + * @param Bill $bill * * @return Factory|View */ @@ -73,7 +73,7 @@ class DeleteController extends Controller { // put previous url in session $this->rememberPreviousUrl('bills.delete.url'); - $subTitle = (string) trans('firefly.delete_bill', ['name' => $bill->name]); + $subTitle = (string)trans('firefly.delete_bill', ['name' => $bill->name]); return view('bills.delete', compact('bill', 'subTitle')); } @@ -81,8 +81,8 @@ class DeleteController extends Controller /** * Destroy a bill. * - * @param Request $request - * @param Bill $bill + * @param Request $request + * @param Bill $bill * * @return RedirectResponse|Redirector */ @@ -91,7 +91,7 @@ class DeleteController extends Controller $name = $bill->name; $this->repository->destroy($bill); - $request->session()->flash('success', (string) trans('firefly.deleted_bill', ['name' => $name])); + $request->session()->flash('success', (string)trans('firefly.deleted_bill', ['name' => $name])); app('preferences')->mark(); return redirect($this->getPreviousUrl('bills.delete.url')); diff --git a/app/Http/Controllers/Bill/EditController.php b/app/Http/Controllers/Bill/EditController.php index 31adf6a27b..4c9c716b90 100644 --- a/app/Http/Controllers/Bill/EditController.php +++ b/app/Http/Controllers/Bill/EditController.php @@ -53,7 +53,7 @@ class EditController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.bills')); + app('view')->share('title', (string)trans('firefly.bills')); app('view')->share('mainTitleIcon', 'fa-calendar-o'); $this->attachments = app(AttachmentHelperInterface::class); $this->repository = app(BillRepositoryInterface::class); @@ -66,8 +66,8 @@ class EditController extends Controller /** * Edit a bill. * - * @param Request $request - * @param Bill $bill + * @param Request $request + * @param Bill $bill * * @return Factory|View */ @@ -78,10 +78,10 @@ class EditController extends Controller $billPeriods = config('firefly.bill_periods'); foreach ($billPeriods as $current) { - $periods[$current] = (string) trans('firefly.' . $current); + $periods[$current] = (string)trans('firefly.'.$current); } - $subTitle = (string) trans('firefly.edit_bill', ['name' => $bill->name]); + $subTitle = (string)trans('firefly.edit_bill', ['name' => $bill->name]); // put previous url in session if not redirect from store (not "return_to_edit"). if (true !== session('bills.edit.fromUpdate')) { @@ -102,7 +102,7 @@ class EditController extends Controller 'extension_date' => $bill->extension_date, 'notes' => $this->repository->getNoteText($bill), 'transaction_currency_id' => $bill->transaction_currency_id, - 'active' => $hasOldInput ? (bool) $request->old('active') : $bill->active, + 'active' => $hasOldInput ? (bool)$request->old('active') : $bill->active, 'object_group' => $bill->objectGroups->first() ? $bill->objectGroups->first()->title : '', ]; @@ -115,8 +115,8 @@ class EditController extends Controller /** * Update a bill. * - * @param BillUpdateRequest $request - * @param Bill $bill + * @param BillUpdateRequest $request + * @param Bill $bill * * @return RedirectResponse */ @@ -125,7 +125,7 @@ class EditController extends Controller $billData = $request->getBillData(); $bill = $this->repository->update($bill, $billData); - $request->session()->flash('success', (string) trans('firefly.updated_bill', ['name' => $bill->name])); + $request->session()->flash('success', (string)trans('firefly.updated_bill', ['name' => $bill->name])); app('preferences')->mark(); /** @var array $files */ @@ -134,7 +134,7 @@ class EditController extends Controller $this->attachments->saveAttachmentsForModel($bill, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } // flash messages @@ -143,12 +143,10 @@ class EditController extends Controller } $redirect = redirect($this->getPreviousUrl('bills.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { $request->session()->put('bills.edit.fromUpdate', true); $redirect = redirect(route('bills.edit', [$bill->id]))->withInput(['return_to_edit' => 1]); - } return $redirect; diff --git a/app/Http/Controllers/Bill/IndexController.php b/app/Http/Controllers/Bill/IndexController.php index 5fd72fa205..f40768057a 100644 --- a/app/Http/Controllers/Bill/IndexController.php +++ b/app/Http/Controllers/Bill/IndexController.php @@ -33,6 +33,8 @@ use FireflyIII\Transformers\BillTransformer; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; use Symfony\Component\HttpFoundation\ParameterBag; /** @@ -55,7 +57,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.bills')); + app('view')->share('title', (string)trans('firefly.bills')); app('view')->share('mainTitleIcon', 'fa-calendar-o'); $this->repository = app(BillRepositoryInterface::class); @@ -77,7 +79,7 @@ class IndexController extends Controller $total = $collection->count(); $defaultCurrency = app('amount')->getDefaultCurrency(); - $parameters = new ParameterBag; + $parameters = new ParameterBag(); $parameters->set('start', $start); $parameters->set('end', $end); @@ -92,20 +94,20 @@ class IndexController extends Controller $bills = [ 0 => [ // the index is the order, not the ID. 'object_group_id' => 0, - 'object_group_title' => (string) trans('firefly.default_group_title_name'), + 'object_group_title' => (string)trans('firefly.default_group_title_name'), 'bills' => [], ], ]; /** @var Bill $bill */ foreach ($collection as $bill) { $array = $transformer->transform($bill); - $groupOrder = (int) $array['object_group_order']; + $groupOrder = (int)$array['object_group_order']; // make group array if necessary: $bills[$groupOrder] = $bills[$groupOrder] ?? [ - 'object_group_id' => $array['object_group_id'], - 'object_group_title' => $array['object_group_title'], - 'bills' => [], - ]; + 'object_group_id' => $array['object_group_id'], + 'object_group_title' => $array['object_group_title'], + 'bills' => [], + ]; // var_dump($array);exit; // // expected today? default: // $array['next_expected_match_diff'] = trans('firefly.not_expected_period'); @@ -142,12 +144,12 @@ class IndexController extends Controller } /** - * @param array $bills + * @param array $bills * * @return array * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function getSums(array $bills): array { @@ -164,19 +166,19 @@ class IndexController extends Controller $currencyId = $bill['currency_id']; $sums[$groupOrder][$currencyId] = $sums[$groupOrder][$currencyId] ?? [ - 'currency_id' => $currencyId, - 'currency_code' => $bill['currency_code'], - 'currency_name' => $bill['currency_name'], - 'currency_symbol' => $bill['currency_symbol'], - 'currency_decimal_places' => $bill['currency_decimal_places'], - 'avg' => '0', - 'period' => $range, - 'per_period' => '0', - ]; + 'currency_id' => $currencyId, + 'currency_code' => $bill['currency_code'], + 'currency_name' => $bill['currency_name'], + 'currency_symbol' => $bill['currency_symbol'], + 'currency_decimal_places' => $bill['currency_decimal_places'], + 'avg' => '0', + 'period' => $range, + 'per_period' => '0', + ]; // only fill in avg when bill is active. if (count($bill['pay_dates']) > 0) { - $avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2'); - $avg = bcmul($avg, (string) count($bill['pay_dates'])); + $avg = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2'); + $avg = bcmul($avg, (string)count($bill['pay_dates'])); $sums[$groupOrder][$currencyId]['avg'] = bcadd($sums[$groupOrder][$currencyId]['avg'], $avg); } // fill in per period regardless: @@ -188,14 +190,14 @@ class IndexController extends Controller } /** - * @param array $bill - * @param string $range + * @param array $bill + * @param string $range * * @return string */ private function amountPerPeriod(array $bill, string $range): string { - $avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2'); + $avg = bcdiv(bcadd((string)$bill['amount_min'], (string)$bill['amount_max']), '2'); Log::debug(sprintf('Amount per period for bill #%d "%s"', $bill['id'], $bill['name'])); Log::debug(sprintf('Average is %s', $avg)); @@ -208,8 +210,8 @@ class IndexController extends Controller 'weekly' => '52.17', 'daily' => '365.24', ]; - $yearAmount = bcmul($avg, bcdiv($multiplies[$bill['repeat_freq']], (string) ($bill['skip'] + 1))); - Log::debug(sprintf('Amount per year is %s (%s * %s / %s)', $yearAmount, $avg, $multiplies[$bill['repeat_freq']], (string) ($bill['skip'] + 1))); + $yearAmount = bcmul($avg, bcdiv($multiplies[$bill['repeat_freq']], (string)($bill['skip'] + 1))); + Log::debug(sprintf('Amount per year is %s (%s * %s / %s)', $yearAmount, $avg, $multiplies[$bill['repeat_freq']], (string)($bill['skip'] + 1))); // per period: $division = [ @@ -228,7 +230,7 @@ class IndexController extends Controller } /** - * @param array $sums + * @param array $sums * * @return array */ @@ -243,20 +245,20 @@ class IndexController extends Controller */ foreach ($sums as $array) { /** - * @var int $currencyId + * @var int $currencyId * @var array $entry */ foreach ($array as $currencyId => $entry) { $totals[$currencyId] = $totals[$currencyId] ?? [ - 'currency_id' => $currencyId, - 'currency_code' => $entry['currency_code'], - 'currency_name' => $entry['currency_name'], - 'currency_symbol' => $entry['currency_symbol'], - 'currency_decimal_places' => $entry['currency_decimal_places'], - 'avg' => '0', - 'period' => $entry['period'], - 'per_period' => '0', - ]; + 'currency_id' => $currencyId, + 'currency_code' => $entry['currency_code'], + 'currency_name' => $entry['currency_name'], + 'currency_symbol' => $entry['currency_symbol'], + 'currency_decimal_places' => $entry['currency_decimal_places'], + 'avg' => '0', + 'period' => $entry['period'], + 'per_period' => '0', + ]; $totals[$currencyId]['avg'] = bcadd($totals[$currencyId]['avg'], $entry['avg']); $totals[$currencyId]['per_period'] = bcadd($totals[$currencyId]['per_period'], $entry['per_period']); } @@ -268,15 +270,15 @@ class IndexController extends Controller /** * Set the order of a bill. * - * @param Request $request - * @param Bill $bill + * @param Request $request + * @param Bill $bill * * @return JsonResponse */ public function setOrder(Request $request, Bill $bill): JsonResponse { - $objectGroupTitle = (string) $request->get('objectGroupTitle'); - $newOrder = (int) $request->get('order'); + $objectGroupTitle = (string)$request->get('objectGroupTitle'); + $newOrder = (int)$request->get('order'); $this->repository->setOrder($bill, $newOrder); if ('' !== $objectGroupTitle) { $this->repository->setObjectGroup($bill, $objectGroupTitle); diff --git a/app/Http/Controllers/Bill/ShowController.php b/app/Http/Controllers/Bill/ShowController.php index dbcfb83502..5abc4d9fe3 100644 --- a/app/Http/Controllers/Bill/ShowController.php +++ b/app/Http/Controllers/Bill/ShowController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Bill; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Attachment; @@ -41,6 +42,8 @@ use Illuminate\View\View; use League\Fractal\Manager; use League\Fractal\Resource\Item; use League\Fractal\Serializer\DataArraySerializer; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; use Symfony\Component\HttpFoundation\ParameterBag; /** @@ -63,7 +66,7 @@ class ShowController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.bills')); + app('view')->share('title', (string)trans('firefly.bills')); app('view')->share('mainTitleIcon', 'fa-calendar-o'); $this->repository = app(BillRepositoryInterface::class); @@ -75,8 +78,8 @@ class ShowController extends Controller /** * Rescan bills for transactions. * - * @param Request $request - * @param Bill $bill + * @param Request $request + * @param Bill $bill * * @return RedirectResponse|Redirector */ @@ -84,17 +87,17 @@ class ShowController extends Controller { $total = 0; if (false === $bill->active) { - $request->session()->flash('warning', (string) trans('firefly.cannot_scan_inactive_bill')); + $request->session()->flash('warning', (string)trans('firefly.cannot_scan_inactive_bill')); return redirect(route('bills.show', [$bill->id])); } - $set = new Collection; + $set = new Collection(); if (true === $bill->active) { $set = $this->repository->getRulesForBill($bill); $total = 0; } if (0 === $set->count()) { - $request->session()->flash('error', (string) trans('firefly.no_rules_for_bill')); + $request->session()->flash('error', (string)trans('firefly.no_rules_for_bill')); return redirect(route('bills.show', [$bill->id])); } @@ -110,7 +113,7 @@ class ShowController extends Controller // file the rule(s) $ruleEngine->fire(); - $request->session()->flash('success', (string) trans_choice('firefly.rescanned_bill', $total)); + $request->session()->flash('success', (string)trans_choice('firefly.rescanned_bill', $total)); app('preferences')->mark(); return redirect(route('bills.show', [$bill->id])); @@ -119,13 +122,13 @@ class ShowController extends Controller /** * Show a bill. * - * @param Request $request - * @param Bill $bill + * @param Request $request + * @param Bill $bill * * @return Factory|View - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws FireflyException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function show(Request $request, Bill $bill) { @@ -137,8 +140,8 @@ class ShowController extends Controller /** @var Carbon $end */ $end = session('end'); $year = $start->year; - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $yearAverage = $this->repository->getYearAverage($bill, $start); $overallAverage = $this->repository->getOverallAverage($bill); $manager = new Manager(); @@ -167,7 +170,7 @@ class ShowController extends Controller // transform any attachments as well. $collection = $this->repository->getAttachments($bill); - $attachments = new Collection; + $attachments = new Collection(); if ($collection->count() > 0) { @@ -183,5 +186,4 @@ class ShowController extends Controller return view('bills.show', compact('attachments', 'groups', 'rules', 'yearAverage', 'overallAverage', 'year', 'object', 'bill', 'subTitle')); } - } diff --git a/app/Http/Controllers/Budget/AvailableBudgetController.php b/app/Http/Controllers/Budget/AvailableBudgetController.php deleted file mode 100644 index 0fd7961b52..0000000000 --- a/app/Http/Controllers/Budget/AvailableBudgetController.php +++ /dev/null @@ -1,267 +0,0 @@ -. - */ - -declare(strict_types=1); - -namespace FireflyIII\Http\Controllers\Budget; - -use Carbon\Carbon; -use Carbon\Exceptions\InvalidDateException; -use FireflyIII\Http\Controllers\Controller; -use FireflyIII\Models\AvailableBudget; -use FireflyIII\Models\TransactionCurrency; -use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; -use Illuminate\Contracts\View\Factory; -use Illuminate\Http\RedirectResponse; -use Illuminate\Http\Request; -use Illuminate\Routing\Redirector; -use Illuminate\View\View; -use Log; -use ValueError; - -/** - * - * Class AvailableBudgetController - */ -class AvailableBudgetController extends Controller -{ - - /** @var AvailableBudgetRepositoryInterface */ - private $abRepository; - /** @var CurrencyRepositoryInterface */ - private $currencyRepos; - - /** - * AmountController constructor. - */ - public function __construct() - { - parent::__construct(); - - $this->middleware( - function ($request, $next) { - app('view')->share('title', (string) trans('firefly.budgets')); - app('view')->share('mainTitleIcon', 'fa-pie-chart'); - $this->abRepository = app(AvailableBudgetRepositoryInterface::class); - $this->currencyRepos = app(CurrencyRepositoryInterface::class); - - return $next($request); - } - ); - } - - /** - * Create will always assume the user's default currency, if it's not set. - * - * This method will check if there is no AB, and refuse to continue if it exists. - * - * @param Request $request - * @param Carbon $start - * @param Carbon $end - * @param TransactionCurrency|null $currency - * - * @return Factory|RedirectResponse|Redirector|View - */ - public function create(Request $request, Carbon $start, Carbon $end, ?TransactionCurrency $currency = null) - { - $currency = $currency ?? app('amount')->getDefaultCurrency(); - $collection = $this->abRepository->get($start, $end); - $filtered = $collection->filter( - static function (AvailableBudget $budget) use ($currency) { - return $currency->id === $budget->transaction_currency_id; - } - ); - if ($filtered->count() > 0) { - /** @var AvailableBudget $first */ - $first = $filtered->first(); - - return redirect(route('available-budgets.edit', [$first->id])); - } - $page = (int) ($request->get('page') ?? 1); - - return view('budgets.available-budgets.create', compact('start', 'end', 'page', 'currency')); - } - - /** - * createAlternative will show a list of enabled currencies so the user can pick one. - * - * @param Request $request - * @param Carbon $start - * @param Carbon $end - * - * @return Factory|View - */ - public function createAlternative(Request $request, Carbon $start, Carbon $end) - { - $currencies = $this->currencyRepos->get(); - $availableBudgets = $this->abRepository->get($start, $end); - - // remove already budgeted currencies: - $currencies = $currencies->filter( - static function (TransactionCurrency $currency) use ($availableBudgets) { - /** @var AvailableBudget $budget */ - foreach ($availableBudgets as $budget) { - if ($budget->transaction_currency_id === $currency->id) { - return false; - } - } - - return true; - } - ); - $page = (int) ($request->get('page') ?? 1); - - return view('budgets.available-budgets.create-alternative', compact('start', 'end', 'page', 'currencies')); - } - - /** - * @param Request $request - * - * @return RedirectResponse|Redirector - */ - public function delete(Request $request) - { - $id = (int) $request->get('id'); - if (0 !== $id) { - $availableBudget = $this->abRepository->findById($id); - if (null !== $availableBudget) { - $this->abRepository->destroyAvailableBudget($availableBudget); - session()->flash('success', trans('firefly.deleted_ab')); - } - } - - return redirect(route('budgets.index')); - } - - /** - * @param AvailableBudget $availableBudget - * - * @param Carbon $start - * @param Carbon $end - * - * @return Factory|View - */ - public function edit(AvailableBudget $availableBudget, Carbon $start, Carbon $end) - { - $availableBudget->amount = app('steam')->bcround($availableBudget->amount, $availableBudget->transactionCurrency->decimal_places); - - return view('budgets.available-budgets.edit', compact('availableBudget', 'start', 'end')); - } - - /** - * @param Request $request - * - * @return RedirectResponse|Redirector - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface - */ - public function store(Request $request) - { - // make dates. - try { - $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); - $end = Carbon::createFromFormat('Y-m-d', $request->get('end')); - } catch (InvalidDateException $e) { - $start = session()->get('start'); - $end = session()->get('end'); - Log::info($e->getMessage()); - } - - // validate amount - $amount = (string) $request->get('amount'); - if ('' === $amount) { - session()->flash('error', trans('firefly.invalid_amount')); - - return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); - } - if (bccomp($amount, '0') <= 0) { - session()->flash('error', trans('firefly.invalid_amount')); - - return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); - } - - // find currency - $currency = $this->currencyRepos->find((int) $request->get('currency_id')); - if (null === $currency) { - session()->flash('error', trans('firefly.invalid_currency')); - - return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); - } - $start->startOfDay(); - $end->endOfDay(); - // find existing AB - $existing = $this->abRepository->find($currency, $start, $end); - if (null === $existing) { - $this->abRepository->store( - [ - 'amount' => $amount, - 'currency_id' => $currency->id, - 'start' => $start, - 'end' => $end, - ] - ); - } - if (null !== $existing) { - // update amount: - $this->abRepository->update($existing, ['amount' => $amount]); - } - session()->flash('success', trans('firefly.set_ab')); - - return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); - } - - /** - * @param Request $request - * @param AvailableBudget $availableBudget - * - * @param Carbon $start - * @param Carbon $end - * - * @return RedirectResponse|Redirector - */ - public function update(Request $request, AvailableBudget $availableBudget, Carbon $start, Carbon $end) - { - // validate amount - $amount = (string) $request->get('amount'); - if ('' === $amount) { - session()->flash('error', trans('firefly.invalid_amount')); - - return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); - } - try { - if (bccomp($amount, '0') <= 0) { - session()->flash('error', trans('firefly.invalid_amount')); - - return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); - } - } catch (ValueError $e) { - Log::error(sprintf('Value "%s" is not a number: %s', $amount, $e->getMessage())); - session()->flash('error', trans('firefly.invalid_amount')); - - return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); - } - $this->abRepository->update($availableBudget, ['amount' => $amount]); - session()->flash('success', trans('firefly.updated_ab')); - - return redirect(route('budgets.index', [$start->format('Y-m-d'), $end->format('Y-m-d')])); - } -} diff --git a/app/Http/Controllers/Budget/BudgetLimitController.php b/app/Http/Controllers/Budget/BudgetLimitController.php index 6e2e4cbd89..67df3abb32 100644 --- a/app/Http/Controllers/Budget/BudgetLimitController.php +++ b/app/Http/Controllers/Budget/BudgetLimitController.php @@ -121,12 +121,13 @@ class BudgetLimitController extends Controller } /** + * TODO why redirect AND json response? * @param Request $request * - * @return JsonResponse + * @return RedirectResponse|JsonResponse * @throws FireflyException */ - public function store(Request $request) + public function store(Request $request): RedirectResponse|JsonResponse { Log::debug('Going to store new budget-limit.', $request->all()); // first search for existing one and update it if necessary. diff --git a/app/Http/Controllers/Budget/CreateController.php b/app/Http/Controllers/Budget/CreateController.php index 03bda94126..ad97bd998a 100644 --- a/app/Http/Controllers/Budget/CreateController.php +++ b/app/Http/Controllers/Budget/CreateController.php @@ -52,7 +52,7 @@ class CreateController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.budgets')); + app('view')->share('title', (string)trans('firefly.budgets')); app('view')->share('mainTitleIcon', 'fa-pie-chart'); $this->repository = app(BudgetRepositoryInterface::class); $this->attachments = app(AttachmentHelperInterface::class); @@ -65,7 +65,7 @@ class CreateController extends Controller /** * Form to create a budget. * - * @param Request $request + * @param Request $request * * @return Factory|View */ @@ -75,23 +75,23 @@ class CreateController extends Controller // auto budget types $autoBudgetTypes = [ - 0 => (string) trans('firefly.auto_budget_none'), - AutoBudget::AUTO_BUDGET_RESET => (string) trans('firefly.auto_budget_reset'), - AutoBudget::AUTO_BUDGET_ROLLOVER => (string) trans('firefly.auto_budget_rollover'), + 0 => (string)trans('firefly.auto_budget_none'), + AutoBudget::AUTO_BUDGET_RESET => (string)trans('firefly.auto_budget_reset'), + AutoBudget::AUTO_BUDGET_ROLLOVER => (string)trans('firefly.auto_budget_rollover'), ]; $autoBudgetPeriods = [ - 'daily' => (string) trans('firefly.auto_budget_period_daily'), - 'weekly' => (string) trans('firefly.auto_budget_period_weekly'), - 'monthly' => (string) trans('firefly.auto_budget_period_monthly'), - 'quarterly' => (string) trans('firefly.auto_budget_period_quarterly'), - 'half_year' => (string) trans('firefly.auto_budget_period_half_year'), - 'yearly' => (string) trans('firefly.auto_budget_period_yearly'), + 'daily' => (string)trans('firefly.auto_budget_period_daily'), + 'weekly' => (string)trans('firefly.auto_budget_period_weekly'), + 'monthly' => (string)trans('firefly.auto_budget_period_monthly'), + 'quarterly' => (string)trans('firefly.auto_budget_period_quarterly'), + 'half_year' => (string)trans('firefly.auto_budget_period_half_year'), + 'yearly' => (string)trans('firefly.auto_budget_period_yearly'), ]; $currency = app('amount')->getDefaultCurrency(); $preFilled = [ - 'auto_budget_period' => $hasOldInput ? (bool) $request->old('auto_budget_period') : 'monthly', - 'auto_budget_currency_id' => $hasOldInput ? (int) $request->old('auto_budget_currency_id') : $currency->id, + 'auto_budget_period' => $hasOldInput ? (bool)$request->old('auto_budget_period') : 'monthly', + 'auto_budget_currency_id' => $hasOldInput ? (int)$request->old('auto_budget_currency_id') : $currency->id, ]; $request->session()->flash('preFilled', $preFilled); @@ -101,7 +101,7 @@ class CreateController extends Controller $this->rememberPreviousUrl('budgets.create.url'); } $request->session()->forget('budgets.create.fromStore'); - $subTitle = (string) trans('firefly.create_new_budget'); + $subTitle = (string)trans('firefly.create_new_budget'); return view('budgets.create', compact('subTitle', 'autoBudgetTypes', 'autoBudgetPeriods')); } @@ -109,7 +109,7 @@ class CreateController extends Controller /** * Stores a budget. * - * @param BudgetFormStoreRequest $request + * @param BudgetFormStoreRequest $request * * @return RedirectResponse * @throws FireflyException @@ -120,7 +120,7 @@ class CreateController extends Controller $budget = $this->repository->store($data); $this->repository->cleanupBudgets(); - $request->session()->flash('success', (string) trans('firefly.stored_new_budget', ['name' => $budget->name])); + $request->session()->flash('success', (string)trans('firefly.stored_new_budget', ['name' => $budget->name])); app('preferences')->mark(); // store attachment(s): @@ -129,7 +129,7 @@ class CreateController extends Controller $this->attachments->saveAttachmentsForModel($budget, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { @@ -138,12 +138,10 @@ class CreateController extends Controller $redirect = redirect($this->getPreviousUrl('budgets.create.url')); - if (1 === (int) $request->get('create_another')) { - + if (1 === (int)$request->get('create_another')) { $request->session()->put('budgets.create.fromStore', true); $redirect = redirect(route('budgets.create'))->withInput(); - } return $redirect; diff --git a/app/Http/Controllers/Budget/DeleteController.php b/app/Http/Controllers/Budget/DeleteController.php index 11deeaa906..de6394536b 100644 --- a/app/Http/Controllers/Budget/DeleteController.php +++ b/app/Http/Controllers/Budget/DeleteController.php @@ -52,7 +52,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.budgets')); + app('view')->share('title', (string)trans('firefly.budgets')); app('view')->share('mainTitleIcon', 'fa-pie-chart'); $this->repository = app(BudgetRepositoryInterface::class); @@ -64,13 +64,13 @@ class DeleteController extends Controller /** * Deletes a budget. * - * @param Budget $budget + * @param Budget $budget * * @return Factory|View */ public function delete(Budget $budget) { - $subTitle = (string) trans('firefly.delete_budget', ['name' => $budget->name]); + $subTitle = (string)trans('firefly.delete_budget', ['name' => $budget->name]); // put previous url in session $this->rememberPreviousUrl('budgets.delete.url'); @@ -81,8 +81,8 @@ class DeleteController extends Controller /** * Destroys a budget. * - * @param Request $request - * @param Budget $budget + * @param Request $request + * @param Budget $budget * * @return RedirectResponse|Redirector */ @@ -90,10 +90,9 @@ class DeleteController extends Controller { $name = $budget->name; $this->repository->destroy($budget); - $request->session()->flash('success', (string) trans('firefly.deleted_budget', ['name' => $name])); + $request->session()->flash('success', (string)trans('firefly.deleted_budget', ['name' => $name])); app('preferences')->mark(); return redirect($this->getPreviousUrl('budgets.delete.url')); } - } diff --git a/app/Http/Controllers/Budget/IndexController.php b/app/Http/Controllers/Budget/IndexController.php index ee24285984..7f06d75ced 100644 --- a/app/Http/Controllers/Budget/IndexController.php +++ b/app/Http/Controllers/Budget/IndexController.php @@ -41,7 +41,10 @@ use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\Support\Collection; use Illuminate\View\View; +use JsonException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * @@ -68,7 +71,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.budgets')); + app('view')->share('title', (string)trans('firefly.budgets')); app('view')->share('mainTitleIcon', 'fa-pie-chart'); $this->repository = app(BudgetRepositoryInterface::class); $this->opsRepository = app(OperationsRepositoryInterface::class); @@ -85,23 +88,23 @@ class IndexController extends Controller /** * Show all budgets. * - * @param Request $request + * @param Request $request * - * @param Carbon|null $start - * @param Carbon|null $end + * @param Carbon|null $start + * @param Carbon|null $end * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index(Request $request, Carbon $start = null, Carbon $end = null) { Log::debug('Start of IndexController::index()'); // collect some basic vars: - $range = (string) app('preferences')->get('viewRange', '1M')->data; + $range = (string)app('preferences')->get('viewRange', '1M')->data; $start = $start ?? session('start', Carbon::now()->startOfMonth()); $end = $end ?? app('navigation')->endOfPeriod($start, $range); $defaultCurrency = app('amount')->getDefaultCurrency(); @@ -122,16 +125,13 @@ class IndexController extends Controller $sums = $this->getSums($budgets); // get budgeted for default currency: - if (empty($availableBudgets)) { - $budgeted = $this->blRepository->budgeted($start, $end, $defaultCurrency,); + if (0 === count($availableBudgets)) { + $budgeted = $this->blRepository->budgeted($start, $end, $defaultCurrency, ); $spentArr = $this->opsRepository->sumExpenses($start, $end, null, null, $defaultCurrency); $spent = $spentArr[$defaultCurrency->id]['sum'] ?? '0'; unset($spentArr); } - // count the number of enabled currencies. This determines if we display a "+" button. - $enableAddButton = $currencies->count() > count($availableBudgets); - // number of days for consistent budgeting. $activeDaysPassed = $this->activeDaysPassed($start, $end); // see method description. $activeDaysLeft = $this->activeDaysLeft($start, $end); // see method description. @@ -140,16 +140,31 @@ class IndexController extends Controller $inactive = $this->repository->getInactiveBudgets(); return view( - 'budgets.index', compact( - 'availableBudgets', 'budgeted', 'spent', 'prevLoop', 'nextLoop', 'budgets', 'currencies', 'enableAddButton', 'periodTitle', - 'defaultCurrency', 'activeDaysPassed', 'activeDaysLeft', 'inactive', 'budgets', 'start', 'end', 'sums' - ) + 'budgets.index', + compact( + 'availableBudgets', + 'budgeted', + 'spent', + 'prevLoop', + 'nextLoop', + 'budgets', + 'currencies', + 'periodTitle', + 'defaultCurrency', + 'activeDaysPassed', + 'activeDaysLeft', + 'inactive', + 'budgets', + 'start', + 'end', + 'sums' + ) ); } /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -170,7 +185,7 @@ class IndexController extends Controller $array['spent'] = $spentArr[$entry->transaction_currency_id]['sum'] ?? '0'; // budgeted in period: - $budgeted = $this->blRepository->budgeted($entry->start_date, $entry->end_date, $entry->transactionCurrency,); + $budgeted = $this->blRepository->budgeted($entry->start_date, $entry->end_date, $entry->transactionCurrency, ); $array['budgeted'] = $budgeted; $availableBudgets[] = $array; unset($spentArr); @@ -180,10 +195,10 @@ class IndexController extends Controller } /** - * @param Carbon $start - * @param Carbon $end - * @param Collection $currencies - * @param TransactionCurrency $defaultCurrency + * @param Carbon $start + * @param Carbon $end + * @param Collection $currencies + * @param TransactionCurrency $defaultCurrency * * @return array */ @@ -238,7 +253,7 @@ class IndexController extends Controller } /** - * @param array $budgets + * @param array $budgets * * @return array */ @@ -290,6 +305,10 @@ class IndexController extends Controller } } // final calculation for 'left': + /** + * @var int $currencyId + * @var array $info + */ foreach ($sums['budgeted'] as $currencyId => $info) { $spent = $sums['spent'][$currencyId]['amount'] ?? '0'; $budgeted = $sums['budgeted'][$currencyId]['amount'] ?? '0'; @@ -300,8 +319,8 @@ class IndexController extends Controller } /** - * @param Request $request - * @param BudgetRepositoryInterface $repository + * @param Request $request + * @param BudgetRepositoryInterface $repository * * @return JsonResponse */ @@ -310,7 +329,7 @@ class IndexController extends Controller $budgetIds = $request->get('budgetIds'); foreach ($budgetIds as $index => $budgetId) { - $budgetId = (int) $budgetId; + $budgetId = (int)$budgetId; $budget = $repository->find($budgetId); if (null !== $budget) { Log::debug(sprintf('Set budget #%d ("%s") to position %d', $budget->id, $budget->name, $index + 1)); diff --git a/app/Http/Controllers/Budget/ShowController.php b/app/Http/Controllers/Budget/ShowController.php index a92989f85d..4a206923de 100644 --- a/app/Http/Controllers/Budget/ShowController.php +++ b/app/Http/Controllers/Budget/ShowController.php @@ -37,6 +37,9 @@ use FireflyIII\Support\Http\Controllers\PeriodOverview; use Illuminate\Contracts\View\Factory; use Illuminate\Http\Request; use Illuminate\View\View; +use JsonException; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * @@ -44,7 +47,8 @@ use Illuminate\View\View; */ class ShowController extends Controller { - use PeriodOverview, AugumentData; + use PeriodOverview; + use AugumentData; protected JournalRepositoryInterface $journalRepos; private BudgetRepositoryInterface $repository; @@ -60,7 +64,7 @@ class ShowController extends Controller parent::__construct(); $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.budgets')); + app('view')->share('title', (string)trans('firefly.budgets')); app('view')->share('mainTitleIcon', 'fa-pie-chart'); $this->journalRepos = app(JournalRepositoryInterface::class); $this->repository = app(BudgetRepositoryInterface::class); @@ -73,15 +77,15 @@ class ShowController extends Controller /** * Show transactions without a budget. * - * @param Request $request - * @param Carbon|null $start - * @param Carbon|null $end + * @param Request $request + * @param Carbon|null $start + * @param Carbon|null $end * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function noBudget(Request $request, Carbon $start = null, Carbon $end = null) { @@ -98,8 +102,8 @@ class ShowController extends Controller $first = $this->journalRepos->firstNull(); $firstDate = null !== $first ? $first->date : $start; $periods = $this->getNoBudgetPeriodOverview($firstDate, $end); - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -114,22 +118,21 @@ class ShowController extends Controller /** * Shows ALL transactions without a budget. * - * @param Request $request + * @param Request $request * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function noBudgetAll(Request $request) { - - $subTitle = (string) trans('firefly.all_journals_without_budget'); + $subTitle = (string)trans('firefly.all_journals_without_budget'); $first = $this->journalRepos->firstNull(); - $start = null === $first ? new Carbon : $first->date; + $start = null === $first ? new Carbon() : $first->date; $end = today(config('app.timezone')); - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -144,22 +147,22 @@ class ShowController extends Controller /** * Show a single budget. * - * @param Request $request - * @param Budget $budget + * @param Request $request + * @param Budget $budget * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function show(Request $request, Budget $budget) { /** @var Carbon $allStart */ $allStart = session('first', Carbon::now()->startOfYear()); $allEnd = today(); - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $limits = $this->getLimits($budget, $allStart, $allEnd); $repetition = null; $attachments = $this->repository->getAttachments($budget); @@ -173,7 +176,7 @@ class ShowController extends Controller $groups = $collector->getPaginatedGroups(); $groups->setPath(route('budgets.show', [$budget->id])); - $subTitle = (string) trans('firefly.all_journals_for_budget', ['name' => $budget->name]); + $subTitle = (string)trans('firefly.all_journals_for_budget', ['name' => $budget->name]); return view('budgets.show', compact('limits', 'attachments', 'budget', 'repetition', 'groups', 'subTitle')); } @@ -181,15 +184,15 @@ class ShowController extends Controller /** * Show a single budget by a budget limit. * - * @param Request $request - * @param Budget $budget - * @param BudgetLimit $budgetLimit + * @param Request $request + * @param Budget $budget + * @param BudgetLimit $budgetLimit * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function showByBudgetLimit(Request $request, Budget $budget, BudgetLimit $budgetLimit) { @@ -197,8 +200,8 @@ class ShowController extends Controller throw new FireflyException('This budget limit is not part of this budget.'); } - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $subTitle = trans( 'firefly.budget_in_period', [ diff --git a/app/Http/Controllers/Category/CreateController.php b/app/Http/Controllers/Category/CreateController.php index d29d739735..9643859d73 100644 --- a/app/Http/Controllers/Category/CreateController.php +++ b/app/Http/Controllers/Category/CreateController.php @@ -53,7 +53,7 @@ class CreateController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.categories')); + app('view')->share('title', (string)trans('firefly.categories')); app('view')->share('mainTitleIcon', 'fa-bookmark'); $this->repository = app(CategoryRepositoryInterface::class); $this->attachments = app(AttachmentHelperInterface::class); @@ -66,7 +66,7 @@ class CreateController extends Controller /** * Create category. * - * @param Request $request + * @param Request $request * * @return Factory|View */ @@ -76,7 +76,7 @@ class CreateController extends Controller $this->rememberPreviousUrl('categories.create.url'); } $request->session()->forget('categories.create.fromStore'); - $subTitle = (string) trans('firefly.create_new_category'); + $subTitle = (string)trans('firefly.create_new_category'); return view('categories.create', compact('subTitle')); } @@ -84,7 +84,7 @@ class CreateController extends Controller /** * Store new category. * - * @param CategoryFormRequest $request + * @param CategoryFormRequest $request * * @return $this|RedirectResponse|Redirector * @throws FireflyException @@ -94,7 +94,7 @@ class CreateController extends Controller $data = $request->getCategoryData(); $category = $this->repository->store($data); - $request->session()->flash('success', (string) trans('firefly.stored_category', ['name' => $category->name])); + $request->session()->flash('success', (string)trans('firefly.stored_category', ['name' => $category->name])); app('preferences')->mark(); // store attachment(s): @@ -103,7 +103,7 @@ class CreateController extends Controller $this->attachments->saveAttachmentsForModel($category, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { @@ -111,12 +111,10 @@ class CreateController extends Controller } $redirect = redirect(route('categories.index')); - if (1 === (int) $request->get('create_another')) { - + if (1 === (int)$request->get('create_another')) { $request->session()->put('categories.create.fromStore', true); $redirect = redirect(route('categories.create'))->withInput(); - } return $redirect; diff --git a/app/Http/Controllers/Category/DeleteController.php b/app/Http/Controllers/Category/DeleteController.php index 4f0a44464e..4d8bb058f1 100644 --- a/app/Http/Controllers/Category/DeleteController.php +++ b/app/Http/Controllers/Category/DeleteController.php @@ -51,7 +51,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.categories')); + app('view')->share('title', (string)trans('firefly.categories')); app('view')->share('mainTitleIcon', 'fa-bookmark'); $this->repository = app(CategoryRepositoryInterface::class); @@ -63,13 +63,13 @@ class DeleteController extends Controller /** * Delete a category. * - * @param Category $category + * @param Category $category * * @return Factory|View */ public function delete(Category $category) { - $subTitle = (string) trans('firefly.delete_category', ['name' => $category->name]); + $subTitle = (string)trans('firefly.delete_category', ['name' => $category->name]); // put previous url in session $this->rememberPreviousUrl('categories.delete.url'); @@ -80,8 +80,8 @@ class DeleteController extends Controller /** * Destroy a category. * - * @param Request $request - * @param Category $category + * @param Request $request + * @param Category $category * * @return RedirectResponse|Redirector */ @@ -90,7 +90,7 @@ class DeleteController extends Controller $name = $category->name; $this->repository->destroy($category); - $request->session()->flash('success', (string) trans('firefly.deleted_category', ['name' => $name])); + $request->session()->flash('success', (string)trans('firefly.deleted_category', ['name' => $name])); app('preferences')->mark(); return redirect($this->getPreviousUrl('categories.delete.url')); diff --git a/app/Http/Controllers/Category/EditController.php b/app/Http/Controllers/Category/EditController.php index 0038532d0e..45496408c4 100644 --- a/app/Http/Controllers/Category/EditController.php +++ b/app/Http/Controllers/Category/EditController.php @@ -39,7 +39,6 @@ use Illuminate\View\View; */ class EditController extends Controller { - private AttachmentHelperInterface $attachments; private CategoryRepositoryInterface $repository; @@ -54,7 +53,7 @@ class EditController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.categories')); + app('view')->share('title', (string)trans('firefly.categories')); app('view')->share('mainTitleIcon', 'fa-bookmark'); $this->repository = app(CategoryRepositoryInterface::class); $this->attachments = app(AttachmentHelperInterface::class); @@ -67,14 +66,14 @@ class EditController extends Controller /** * Edit a category. * - * @param Request $request - * @param Category $category + * @param Request $request + * @param Category $category * * @return Factory|View */ public function edit(Request $request, Category $category) { - $subTitle = (string) trans('firefly.edit_category', ['name' => $category->name]); + $subTitle = (string)trans('firefly.edit_category', ['name' => $category->name]); // put previous url in session if not redirect from store (not "return_to_edit"). if (true !== session('categories.edit.fromUpdate')) { @@ -92,8 +91,8 @@ class EditController extends Controller /** * Update category. * - * @param CategoryFormRequest $request - * @param Category $category + * @param CategoryFormRequest $request + * @param Category $category * * @return RedirectResponse|Redirector */ @@ -102,7 +101,7 @@ class EditController extends Controller $data = $request->getCategoryData(); $this->repository->update($category, $data); - $request->session()->flash('success', (string) trans('firefly.updated_category', ['name' => $category->name])); + $request->session()->flash('success', (string)trans('firefly.updated_category', ['name' => $category->name])); app('preferences')->mark(); // store new attachment(s): @@ -111,7 +110,7 @@ class EditController extends Controller $this->attachments->saveAttachmentsForModel($category, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { @@ -119,12 +118,10 @@ class EditController extends Controller } $redirect = redirect($this->getPreviousUrl('categories.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { $request->session()->put('categories.edit.fromUpdate', true); $redirect = redirect(route('categories.edit', [$category->id])); - } return $redirect; diff --git a/app/Http/Controllers/Category/IndexController.php b/app/Http/Controllers/Category/IndexController.php index ee07147caa..768e469b6c 100644 --- a/app/Http/Controllers/Category/IndexController.php +++ b/app/Http/Controllers/Category/IndexController.php @@ -32,6 +32,8 @@ use Illuminate\Http\Request; use Illuminate\Pagination\LengthAwarePaginator; use Illuminate\Support\Collection; use Illuminate\View\View; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class IndexController @@ -52,7 +54,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.categories')); + app('view')->share('title', (string)trans('firefly.categories')); app('view')->share('mainTitleIcon', 'fa-bookmark'); $this->repository = app(CategoryRepositoryInterface::class); @@ -64,24 +66,24 @@ class IndexController extends Controller /** * Show all categories. * - * @param Request $request + * @param Request $request * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index(Request $request) { - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $collection = $this->repository->getCategories(); $total = $collection->count(); $collection = $collection->slice(($page - 1) * $pageSize, $pageSize); $collection->each( function (Category $category) { - $category->lastActivity = $this->repository->lastUseDate($category, new Collection); + $category->lastActivity = $this->repository->lastUseDate($category, new Collection()); } ); @@ -91,5 +93,4 @@ class IndexController extends Controller return view('categories.index', compact('categories')); } - } diff --git a/app/Http/Controllers/Category/NoCategoryController.php b/app/Http/Controllers/Category/NoCategoryController.php index 515bfbb16f..9873883387 100644 --- a/app/Http/Controllers/Category/NoCategoryController.php +++ b/app/Http/Controllers/Category/NoCategoryController.php @@ -34,7 +34,10 @@ use Illuminate\Contracts\View\Factory; use Illuminate\Http\Request; use Illuminate\Support\Collection; use Illuminate\View\View; +use JsonException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * @@ -58,7 +61,7 @@ class NoCategoryController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.categories')); + app('view')->share('title', (string)trans('firefly.categories')); app('view')->share('mainTitleIcon', 'fa-bookmark'); $this->journalRepos = app(JournalRepositoryInterface::class); @@ -70,15 +73,15 @@ class NoCategoryController extends Controller /** * Show transactions without a category. * - * @param Request $request - * @param Carbon|null $start - * @param Carbon|null $end + * @param Request $request + * @param Carbon|null $start + * @param Carbon|null $end * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function show(Request $request, Carbon $start = null, Carbon $end = null) { @@ -87,8 +90,8 @@ class NoCategoryController extends Controller $start = $start ?? session('start'); /** @var Carbon $end */ $end = $end ?? session('end'); - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $subTitle = trans( 'firefly.without_category_between', ['start' => $start->isoFormat($this->monthAndDayFormat), 'end' => $end->isoFormat($this->monthAndDayFormat)] @@ -113,25 +116,25 @@ class NoCategoryController extends Controller /** * Show all transactions without a category. * - * @param Request $request + * @param Request $request * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function showAll(Request $request) { // default values: $start = null; $end = null; - $periods = new Collection; - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $periods = new Collection(); + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; Log::debug('Start of noCategory()'); - $subTitle = (string) trans('firefly.all_journals_without_category'); + $subTitle = (string)trans('firefly.all_journals_without_category'); $first = $this->journalRepos->firstNull(); - $start = null === $first ? new Carbon : $first->date; + $start = null === $first ? new Carbon() : $first->date; $end = today(config('app.timezone')); 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'))); diff --git a/app/Http/Controllers/Category/ShowController.php b/app/Http/Controllers/Category/ShowController.php index a3eb24c391..5e7a02ffe4 100644 --- a/app/Http/Controllers/Category/ShowController.php +++ b/app/Http/Controllers/Category/ShowController.php @@ -34,6 +34,9 @@ use Illuminate\Contracts\View\Factory; use Illuminate\Http\Request; use Illuminate\Support\Collection; use Illuminate\View\View; +use JsonException; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * @@ -59,7 +62,7 @@ class ShowController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.categories')); + app('view')->share('title', (string)trans('firefly.categories')); app('view')->share('mainTitleIcon', 'fa-bookmark'); $this->repository = app(CategoryRepositoryInterface::class); @@ -71,16 +74,16 @@ class ShowController extends Controller /** * Show a single category. * - * @param Request $request - * @param Category $category - * @param Carbon|null $start - * @param Carbon|null $end + * @param Request $request + * @param Category $category + * @param Carbon|null $start + * @param Carbon|null $end * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function show(Request $request, Category $category, Carbon $start = null, Carbon $end = null) { @@ -89,16 +92,19 @@ class ShowController extends Controller /** @var Carbon $end */ $end = $end ?? session('end', Carbon::now()->endOfMonth()); $subTitleIcon = 'fa-bookmark'; - $page = (int) $request->get('page'); + $page = (int)$request->get('page'); $attachments = $this->repository->getAttachments($category); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $oldest = $this->repository->firstUseDate($category) ?? Carbon::now()->startOfYear(); $periods = $this->getCategoryPeriodOverview($category, $oldest, $end); $path = route('categories.show', [$category->id, $start->format('Y-m-d'), $end->format('Y-m-d')]); $subTitle = trans( 'firefly.journals_in_period_for_category', - ['name' => $category->name, 'start' => $start->isoFormat($this->monthAndDayFormat), - 'end' => $end->isoFormat($this->monthAndDayFormat),] + [ + 'name' => $category->name, + 'start' => $start->isoFormat($this->monthAndDayFormat), + 'end' => $end->isoFormat($this->monthAndDayFormat), + ] ); /** @var GroupCollectorInterface $collector */ @@ -116,25 +122,25 @@ class ShowController extends Controller /** * Show all transactions within a category. * - * @param Request $request - * @param Category $category + * @param Request $request + * @param Category $category * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function showAll(Request $request, Category $category) { // default values: $subTitleIcon = 'fa-bookmark'; - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $start = null; $end = null; - $periods = new Collection; + $periods = new Collection(); - $subTitle = (string) trans('firefly.all_journals_for_category', ['name' => $category->name]); + $subTitle = (string)trans('firefly.all_journals_for_category', ['name' => $category->name]); $first = $this->repository->firstUseDate($category); /** @var Carbon $start */ $start = $first ?? today(config('app.timezone')); diff --git a/app/Http/Controllers/Chart/AccountController.php b/app/Http/Controllers/Chart/AccountController.php index a4e60b70a6..6df7bed7bd 100644 --- a/app/Http/Controllers/Chart/AccountController.php +++ b/app/Http/Controllers/Chart/AccountController.php @@ -1,4 +1,5 @@ startOfMonth()); /** @var Carbon $end */ $end = clone session('end', Carbon::now()->endOfMonth()); - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.account.expense-accounts'); @@ -112,14 +117,14 @@ class AccountController extends Controller // loop the end balances. This is an array for each account ($expenses) foreach ($endBalances as $accountId => $expenses) { - $accountId = (int) $accountId; + $accountId = (int)$accountId; // loop each expense entry (each entry can be a different currency). foreach ($expenses as $currencyId => $endAmount) { - $currencyId = (int) $currencyId; + $currencyId = (int)$currencyId; // see if there is an accompanying start amount. // grab the difference and find the currency. - $startAmount = (string) ($startBalances[$accountId][$currencyId] ?? '0'); + $startAmount = (string)($startBalances[$accountId][$currencyId] ?? '0'); $diff = bcsub((string)$endAmount, $startAmount); $currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->find($currencyId); if (0 !== bccomp($diff, '0')) { @@ -127,7 +132,7 @@ class AccountController extends Controller $tempData[] = [ 'name' => $accountNames[$accountId], 'difference' => $diff, - 'diff_float' => (float) $diff, // intentional float + 'diff_float' => (float)$diff, // intentional float 'currency_id' => $currencyId, ]; } @@ -140,13 +145,13 @@ class AccountController extends Controller // loop all found currencies and build the data array for the chart. /** - * @var int $currencyId + * @var int $currencyId * @var TransactionCurrency $currency */ foreach ($currencies as $currencyId => $currency) { $dataSet = [ - 'label' => (string) trans('firefly.spent'), + 'label' => (string)trans('firefly.spent'), 'type' => 'bar', 'currency_symbol' => $currency->symbol, 'currency_code' => $currency->code, @@ -171,8 +176,8 @@ class AccountController extends Controller /** * Expenses per budget for all time, as shown on account overview. * - * @param AccountRepositoryInterface $repository - * @param Account $account + * @param AccountRepositoryInterface $repository + * @param Account $account * * @return JsonResponse * @throws JsonException @@ -188,15 +193,15 @@ class AccountController extends Controller /** * Expenses per budget, as shown on account overview. * - * @param Account $account - * @param Carbon $start - * @param Carbon $end + * @param Account $account + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ public function expenseBudget(Account $account, Carbon $start, Carbon $end): JsonResponse { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($account->id); $cache->addProperty($start); $cache->addProperty($end); @@ -213,7 +218,7 @@ class AccountController extends Controller $budgetIds = []; /** @var array $journal */ foreach ($journals as $journal) { - $budgetId = (int) $journal['budget_id']; + $budgetId = (int)$journal['budget_id']; $key = sprintf('%d-%d', $budgetId, $journal['currency_id']); $budgetIds[] = $budgetId; if (!array_key_exists($key, $result)) { @@ -233,7 +238,7 @@ class AccountController extends Controller foreach ($result as $row) { $budgetId = $row['budget_id']; $name = $names[$budgetId]; - $label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); + $label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); $chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']]; } @@ -246,8 +251,8 @@ class AccountController extends Controller /** * Expenses grouped by category for account. * - * @param AccountRepositoryInterface $repository - * @param Account $account + * @param AccountRepositoryInterface $repository + * @param Account $account * * @return JsonResponse * @throws JsonException @@ -263,15 +268,15 @@ class AccountController extends Controller /** * Expenses per category for one single account. * - * @param Account $account - * @param Carbon $start - * @param Carbon $end + * @param Account $account + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ public function expenseCategory(Account $account, Carbon $start, Carbon $end): JsonResponse { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($account->id); $cache->addProperty($start); $cache->addProperty($end); @@ -293,7 +298,7 @@ class AccountController extends Controller if (!array_key_exists($key, $result)) { $result[$key] = [ 'total' => '0', - 'category_id' => (int) $journal['category_id'], + 'category_id' => (int)$journal['category_id'], 'currency_name' => $journal['currency_name'], 'currency_symbol' => $journal['currency_symbol'], 'currency_code' => $journal['currency_code'], @@ -306,7 +311,7 @@ class AccountController extends Controller foreach ($result as $row) { $categoryId = $row['category_id']; $name = $names[$categoryId] ?? '(unknown)'; - $label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); + $label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); $chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']]; } @@ -319,13 +324,13 @@ class AccountController extends Controller /** * Shows the balances for all the user's frontpage accounts. * - * @param AccountRepositoryInterface $repository + * @param AccountRepositoryInterface $repository * * @return JsonResponse * @throws FireflyException * @throws JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function frontpage(AccountRepositoryInterface $repository): JsonResponse { @@ -335,7 +340,7 @@ class AccountController extends Controller Log::debug('Default set is ', $defaultSet); $frontPage = app('preferences')->get('frontPageAccounts', $defaultSet); Log::debug('Frontpage preference set is ', $frontPage->data); - if (empty($frontPage->data)) { + if (0 === count($frontPage->data)) { app('preferences')->set('frontPageAccounts', $defaultSet); Log::debug('frontpage set is empty!'); } @@ -347,8 +352,8 @@ class AccountController extends Controller /** * Shows the income grouped by category for an account, in all time. * - * @param AccountRepositoryInterface $repository - * @param Account $account + * @param AccountRepositoryInterface $repository + * @param Account $account * * @return JsonResponse * @throws JsonException @@ -364,15 +369,15 @@ class AccountController extends Controller /** * Shows all income per account for each category. * - * @param Account $account - * @param Carbon $start - * @param Carbon $end + * @param Account $account + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ public function incomeCategory(Account $account, Carbon $start, Carbon $end): JsonResponse { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($account->id); $cache->addProperty($start); $cache->addProperty($end); @@ -408,7 +413,7 @@ class AccountController extends Controller foreach ($result as $row) { $categoryId = $row['category_id']; $name = $names[$categoryId] ?? '(unknown)'; - $label = (string) trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); + $label = (string)trans('firefly.name_in_currency', ['name' => $name, 'currency' => $row['currency_name']]); $chartData[$label] = ['amount' => $row['total'], 'currency_symbol' => $row['currency_symbol'], 'currency_code' => $row['currency_code']]; } $data = $this->generator->multiCurrencyPieChart($chartData); @@ -420,10 +425,10 @@ class AccountController extends Controller /** * Shows overview of account during a single period. * - * @param Account $account - * @param Carbon $start + * @param Account $account + * @param Carbon $start * - * @param Carbon $end + * @param Carbon $end * * @return JsonResponse * @throws FireflyException @@ -432,7 +437,7 @@ class AccountController extends Controller public function period(Account $account, Carbon $start, Carbon $end): JsonResponse { $chartData = []; - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('chart.account.period'); $cache->addProperty($start); $cache->addProperty($end); @@ -459,10 +464,10 @@ class AccountController extends Controller } /** - * @param Carbon $start - * @param Carbon $end - * @param Account $account - * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * @param Account $account + * @param TransactionCurrency $currency * * @return array * @throws FireflyException @@ -476,39 +481,30 @@ class AccountController extends Controller 'label' => sprintf('%s (%s)', $account->name, $currency->symbol), 'currency_symbol' => $currency->symbol, 'currency_code' => $currency->code, - 'entries' => [], ]; $entries = []; $current = clone $start; - switch ($step) { - default: - break; - case '1D': - // per day the entire period, balance for every day. - $format = (string) trans('config.month_and_day_js', [], $locale); - $range = app('steam')->balanceInRange($account, $start, $end, $currency); - $previous = array_values($range)[0]; - while ($end >= $current) { - $theDate = $current->format('Y-m-d'); - $balance = $range[$theDate] ?? $previous; - $label = $current->isoFormat($format); - $entries[$label] = $balance; - $previous = $balance; - $current->addDay(); - } - break; - - case '1W': - case '1M': - case '1Y': - while ($end >= $current) { - $balance = app('steam')->balance($account, $current, $currency); - $label = app('navigation')->periodShow($current, $step); - $entries[$label] = $balance; - $current = app('navigation')->addPeriod($current, $step, 0); - } - break; - + if ('1D' === $step) { + // per day the entire period, balance for every day. + $format = (string)trans('config.month_and_day_js', [], $locale); + $range = app('steam')->balanceInRange($account, $start, $end, $currency); + $previous = array_values($range)[0]; + while ($end >= $current) { + $theDate = $current->format('Y-m-d'); + $balance = $range[$theDate] ?? $previous; + $label = $current->isoFormat($format); + $entries[$label] = (float)$balance; + $previous = $balance; + $current->addDay(); + } + } + if ('1W' === $step || '1M' === $step || '1Y' === $step) { + while ($end >= $current) { + $balance = (float)app('steam')->balance($account, $current, $currency); + $label = app('navigation')->periodShow($current, $step); + $entries[$label] = $balance; + $current = app('navigation')->addPeriod($current, $step, 0); + } } $result['entries'] = $entries; @@ -518,12 +514,12 @@ class AccountController extends Controller /** * Shows the balances for a given set of dates and accounts. * - * See reference nr. 55 + * TODO this chart is not multi currency aware. * - * @param Collection $accounts + * @param Collection $accounts * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * @return JsonResponse * @throws FireflyException * @throws JsonException @@ -547,7 +543,7 @@ class AccountController extends Controller $start = clone session('start', Carbon::now()->startOfMonth()); /** @var Carbon $end */ $end = clone session('end', Carbon::now()->endOfMonth()); - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.account.revenue-accounts'); @@ -571,22 +567,22 @@ class AccountController extends Controller // loop the end balances. This is an array for each account ($expenses) foreach ($endBalances as $accountId => $expenses) { - $accountId = (int) $accountId; + $accountId = (int)$accountId; // loop each expense entry (each entry can be a different currency). foreach ($expenses as $currencyId => $endAmount) { - $currencyId = (int) $currencyId; + $currencyId = (int)$currencyId; // see if there is an accompanying start amount. // grab the difference and find the currency. $startAmount = (string)($startBalances[$accountId][$currencyId] ?? '0'); - $diff = bcsub((string) $endAmount, $startAmount); + $diff = bcsub((string)$endAmount, $startAmount); $currencies[$currencyId] = $currencies[$currencyId] ?? $this->currencyRepository->find($currencyId); if (0 !== bccomp($diff, '0')) { // store the values in a temporary array. $tempData[] = [ 'name' => $accountNames[$accountId], 'difference' => $diff, - 'diff_float' => (float) $diff, // intentional float + 'diff_float' => (float)$diff, // intentional float 'currency_id' => $currencyId, ]; } @@ -599,13 +595,13 @@ class AccountController extends Controller // loop all found currencies and build the data array for the chart. /** - * @var int $currencyId + * @var int $currencyId * @var TransactionCurrency $currency */ foreach ($currencies as $currencyId => $currency) { $dataSet = [ - 'label' => (string) trans('firefly.earned'), + 'label' => (string)trans('firefly.earned'), 'type' => 'bar', 'currency_symbol' => $currency->symbol, 'currency_code' => $currency->code, diff --git a/app/Http/Controllers/Chart/BillController.php b/app/Http/Controllers/Chart/BillController.php index ff1782f1b5..807f254289 100644 --- a/app/Http/Controllers/Chart/BillController.php +++ b/app/Http/Controllers/Chart/BillController.php @@ -1,4 +1,5 @@ startOfMonth()); $end = session('end', Carbon::now()->endOfMonth()); - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.bill.frontpage'); @@ -79,15 +81,21 @@ class BillController extends Controller foreach ($paid as $currencyId => $amount) { $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepository->find($currencyId); - $label = (string) trans('firefly.paid_in_currency', ['currency' => $currencies[$currencyId]->name]); - $chartData[$label] = ['amount' => $amount, 'currency_symbol' => $currencies[$currencyId]->symbol, - 'currency_code' => $currencies[$currencyId]->code]; + $label = (string)trans('firefly.paid_in_currency', ['currency' => $currencies[$currencyId]->name]); + $chartData[$label] = [ + 'amount' => $amount, + 'currency_symbol' => $currencies[$currencyId]->symbol, + 'currency_code' => $currencies[$currencyId]->code, + ]; } foreach ($unpaid as $currencyId => $amount) { $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepository->find($currencyId); - $label = (string) trans('firefly.unpaid_in_currency', ['currency' => $currencies[$currencyId]->name]); - $chartData[$label] = ['amount' => $amount, 'currency_symbol' => $currencies[$currencyId]->symbol, - 'currency_code' => $currencies[$currencyId]->code]; + $label = (string)trans('firefly.unpaid_in_currency', ['currency' => $currencies[$currencyId]->name]); + $chartData[$label] = [ + 'amount' => $amount, + 'currency_symbol' => $currencies[$currencyId]->symbol, + 'currency_code' => $currencies[$currencyId]->code, + ]; } $data = $this->generator->multiCurrencyPieChart($chartData); @@ -99,14 +107,14 @@ class BillController extends Controller /** * Shows overview for a single bill. * - * @param Bill $bill + * @param Bill $bill * * @return JsonResponse - * @throws \FireflyIII\Exceptions\FireflyException + * @throws FireflyException */ public function single(Bill $bill): JsonResponse { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('chart.bill.single'); $cache->addProperty($bill->id); if ($cache->has()) { @@ -134,16 +142,31 @@ class BillController extends Controller ); $chartData = [ - ['type' => 'line', 'label' => (string) trans('firefly.min-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol, - 'currency_code' => $bill->transactionCurrency->code, 'entries' => []], - ['type' => 'line', 'label' => (string) trans('firefly.max-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol, - 'currency_code' => $bill->transactionCurrency->code, 'entries' => []], - ['type' => 'bar', 'label' => (string) trans('firefly.journal-amount'), 'currency_symbol' => $bill->transactionCurrency->symbol, - 'currency_code' => $bill->transactionCurrency->code, 'entries' => []], + [ + 'type' => 'line', + 'label' => (string)trans('firefly.min-amount'), + 'currency_symbol' => $bill->transactionCurrency->symbol, + 'currency_code' => $bill->transactionCurrency->code, + 'entries' => [], + ], + [ + 'type' => 'line', + 'label' => (string)trans('firefly.max-amount'), + 'currency_symbol' => $bill->transactionCurrency->symbol, + 'currency_code' => $bill->transactionCurrency->code, + 'entries' => [], + ], + [ + 'type' => 'bar', + 'label' => (string)trans('firefly.journal-amount'), + 'currency_symbol' => $bill->transactionCurrency->symbol, + 'currency_code' => $bill->transactionCurrency->code, + 'entries' => [], + ], ]; - $currencyId = (int) $bill->transaction_currency_id; + $currencyId = (int)$bill->transaction_currency_id; foreach ($journals as $journal) { - $date = $journal['date']->isoFormat((string) trans('config.month_and_day_js', [], $locale)); + $date = $journal['date']->isoFormat((string)trans('config.month_and_day_js', [], $locale)); $chartData[0]['entries'][$date] = $bill->amount_min; // minimum amount of bill $chartData[1]['entries'][$date] = $bill->amount_max; // maximum amount of bill diff --git a/app/Http/Controllers/Chart/BudgetController.php b/app/Http/Controllers/Chart/BudgetController.php index 4857670459..1e01a1d2d6 100644 --- a/app/Http/Controllers/Chart/BudgetController.php +++ b/app/Http/Controllers/Chart/BudgetController.php @@ -1,4 +1,5 @@ opsRepository->sumExpenses($current, $current, null, $budgetCollection, $currency); - $spent = $expenses[(int) $currency->id]['sum'] ?? '0'; + $spent = $expenses[(int)$currency->id]['sum'] ?? '0'; $amount = bcadd($amount, $spent); - $format = $start->isoFormat((string) trans('config.month_and_day_js', [], $locale)); + $format = $start->isoFormat((string)trans('config.month_and_day_js', [], $locale)); $entries[$format] = $amount; $start->addDay(); } - $data = $this->generator->singleSet((string) trans('firefly.left'), $entries); + $data = $this->generator->singleSet((string)trans('firefly.left'), $entries); // add currency symbol from budget limit: $data['datasets'][0]['currency_symbol'] = $budgetLimit->transactionCurrency->symbol; $data['datasets'][0]['currency_code'] = $budgetLimit->transactionCurrency->code; @@ -199,8 +200,8 @@ class BudgetController extends Controller /** * Shows how much is spent per asset account. * - * @param Budget $budget - * @param BudgetLimit|null $budgetLimit + * @param Budget $budget + * @param BudgetLimit|null $budgetLimit * * @return JsonResponse */ @@ -209,7 +210,7 @@ class BudgetController extends Controller /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $budgetLimitId = null === $budgetLimit ? 0 : $budgetLimit->id; - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($budget->id); $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-asset'); @@ -235,20 +236,20 @@ class BudgetController extends Controller // group by asset account ID: foreach ($journals as $journal) { - $key = sprintf('%d-%d', (int) $journal['source_account_id'], $journal['currency_id']); + $key = sprintf('%d-%d', (int)$journal['source_account_id'], $journal['currency_id']); $result[$key] = $result[$key] ?? [ - 'amount' => '0', - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_name' => $journal['currency_name'], - ]; + 'amount' => '0', + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_name' => $journal['currency_name'], + ]; $result[$key]['amount'] = bcadd($journal['amount'], $result[$key]['amount']); } $names = $this->getAccountNames(array_keys($result)); foreach ($result as $combinedId => $info) { $parts = explode('-', $combinedId); - $assetId = (int) $parts[0]; + $assetId = (int)$parts[0]; $title = sprintf('%s (%s)', $names[$assetId] ?? '(empty)', $info['currency_name']); $chartData[$title] = [ @@ -267,8 +268,8 @@ class BudgetController extends Controller /** * Shows how much is spent per category. * - * @param Budget $budget - * @param BudgetLimit|null $budgetLimit + * @param Budget $budget + * @param BudgetLimit|null $budgetLimit * * @return JsonResponse */ @@ -277,7 +278,7 @@ class BudgetController extends Controller /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $budgetLimitId = null === $budgetLimit ? 0 : $budgetLimit->id; - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($budget->id); $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-category'); @@ -302,18 +303,18 @@ class BudgetController extends Controller foreach ($journals as $journal) { $key = sprintf('%d-%d', $journal['category_id'], $journal['currency_id']); $result[$key] = $result[$key] ?? [ - 'amount' => '0', - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_name' => $journal['currency_name'], - ]; + 'amount' => '0', + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_name' => $journal['currency_name'], + ]; $result[$key]['amount'] = bcadd($journal['amount'], $result[$key]['amount']); } $names = $this->getCategoryNames(array_keys($result)); foreach ($result as $combinedId => $info) { $parts = explode('-', $combinedId); - $categoryId = (int) $parts[0]; + $categoryId = (int)$parts[0]; $title = sprintf('%s (%s)', $names[$categoryId] ?? '(empty)', $info['currency_name']); $chartData[$title] = [ 'amount' => $info['amount'], @@ -331,8 +332,8 @@ class BudgetController extends Controller * Shows how much is spent per expense account. * * - * @param Budget $budget - * @param BudgetLimit|null $budgetLimit + * @param Budget $budget + * @param BudgetLimit|null $budgetLimit * * @return JsonResponse */ @@ -341,7 +342,7 @@ class BudgetController extends Controller /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $budgetLimitId = null === $budgetLimit ? 0 : $budgetLimit->id; - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($budget->id); $cache->addProperty($budgetLimitId); $cache->addProperty('chart.budget.expense-expense'); @@ -367,18 +368,18 @@ class BudgetController extends Controller foreach ($journals as $journal) { $key = sprintf('%d-%d', $journal['destination_account_id'], $journal['currency_id']); $result[$key] = $result[$key] ?? [ - 'amount' => '0', - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_name' => $journal['currency_name'], - ]; + 'amount' => '0', + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_name' => $journal['currency_name'], + ]; $result[$key]['amount'] = bcadd($journal['amount'], $result[$key]['amount']); } $names = $this->getAccountNames(array_keys($result)); foreach ($result as $combinedId => $info) { $parts = explode('-', $combinedId); - $opposingId = (int) $parts[0]; + $opposingId = (int)$parts[0]; $name = $names[$opposingId] ?? 'no name'; $title = sprintf('%s (%s)', $name, $info['currency_name']); $chartData[$title] = [ @@ -428,11 +429,11 @@ class BudgetController extends Controller /** * Shows a budget overview chart (spent and budgeted). * - * @param Budget $budget - * @param TransactionCurrency $currency - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Budget $budget + * @param TransactionCurrency $currency + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -453,14 +454,14 @@ class BudgetController extends Controller $preferredRange = app('navigation')->preferredRangeFormat($start, $end); $chartData = [ [ - 'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency->name]), + 'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency->name]), 'type' => 'bar', 'entries' => [], 'currency_symbol' => $currency->symbol, 'currency_code' => $currency->code, ], [ - 'label' => (string) trans('firefly.box_budgeted_in_currency', ['currency' => $currency->name]), + 'label' => (string)trans('firefly.box_budgeted_in_currency', ['currency' => $currency->name]), 'type' => 'bar', 'currency_symbol' => $currency->symbol, 'currency_code' => $currency->code, @@ -504,10 +505,10 @@ class BudgetController extends Controller /** * Shows a chart for transactions without a budget. * - * @param TransactionCurrency $currency - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param TransactionCurrency $currency + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -538,7 +539,7 @@ class BudgetController extends Controller $currentStart = app('navigation')->addPeriod($currentStart, $preferredRange, 0); } - $data = $this->generator->singleSet((string) trans('firefly.spent'), $chartData); + $data = $this->generator->singleSet((string)trans('firefly.spent'), $chartData); $cache->store($data); return response()->json($data); diff --git a/app/Http/Controllers/Chart/BudgetReportController.php b/app/Http/Controllers/Chart/BudgetReportController.php index da0bf7db31..02de0fe349 100644 --- a/app/Http/Controllers/Chart/BudgetReportController.php +++ b/app/Http/Controllers/Chart/BudgetReportController.php @@ -19,7 +19,6 @@ * along with this program. If not, see . */ -/** @noinspection MoreThanThreeArgumentsInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Chart; @@ -42,7 +41,8 @@ use Illuminate\Support\Collection; */ class BudgetReportController extends Controller { - use AugumentData, TransactionCalculation; + use AugumentData; + use TransactionCalculation; /** @var GeneratorInterface Chart generation methods. */ private $generator; @@ -71,10 +71,10 @@ class BudgetReportController extends Controller /** * Chart that groups the expenses by budget. * - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -88,10 +88,10 @@ class BudgetReportController extends Controller foreach ($currency['budgets'] as $budget) { $title = sprintf('%s (%s)', $budget['name'], $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; foreach ($budget['transaction_journals'] as $journal) { $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); @@ -107,10 +107,10 @@ class BudgetReportController extends Controller /** * Chart that groups the expenses by budget. * - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -125,10 +125,10 @@ class BudgetReportController extends Controller $categoryName = $journal['category_name'] ?? trans('firefly.no_category'); $title = sprintf('%s (%s)', $categoryName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); @@ -144,10 +144,10 @@ class BudgetReportController extends Controller /** * Chart that groups expenses by the account. * - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -162,10 +162,10 @@ class BudgetReportController extends Controller foreach ($budget['transaction_journals'] as $journal) { $title = sprintf('%s (%s)', $journal['destination_account_name'], $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); @@ -181,10 +181,10 @@ class BudgetReportController extends Controller /** * Main overview of a budget in the budget report. * - * @param Collection $accounts - * @param Budget $budget - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -199,17 +199,17 @@ class BudgetReportController extends Controller // add things to chart Data for each currency: $spentKey = sprintf('%d-spent', $currency['currency_id']); $chartData[$spentKey] = $chartData[$spentKey] ?? [ - 'label' => sprintf( - '%s (%s)', - (string) trans('firefly.spent_in_specific_budget', ['budget' => $budget->name]), - $currency['currency_name'] - ), - 'type' => 'bar', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_id' => $currency['currency_id'], - 'entries' => $this->makeEntries($start, $end), - ]; + 'label' => sprintf( + '%s (%s)', + (string)trans('firefly.spent_in_specific_budget', ['budget' => $budget->name]), + $currency['currency_name'] + ), + 'type' => 'bar', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_id' => $currency['currency_id'], + 'entries' => $this->makeEntries($start, $end), + ]; foreach ($currency['budgets'] as $currentBudget) { foreach ($currentBudget['transaction_journals'] as $journal) { @@ -227,8 +227,8 @@ class BudgetReportController extends Controller } /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -252,10 +252,10 @@ class BudgetReportController extends Controller /** * Chart that groups expenses by the account. * - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -270,10 +270,10 @@ class BudgetReportController extends Controller foreach ($budget['transaction_journals'] as $journal) { $title = sprintf('%s (%s)', $journal['source_account_name'], $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); diff --git a/app/Http/Controllers/Chart/CategoryController.php b/app/Http/Controllers/Chart/CategoryController.php index ffe0194b98..aadd6e1e2b 100644 --- a/app/Http/Controllers/Chart/CategoryController.php +++ b/app/Http/Controllers/Chart/CategoryController.php @@ -1,4 +1,5 @@ addProperty('chart.category.all'); $cache->addProperty($category->id); if ($cache->has()) { @@ -104,19 +107,12 @@ class CategoryController extends Controller */ private function getDate(): Carbon { - $carbon = null; - try { - $carbon = today(config('app.timezone')); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - - return $carbon; + return today(config('app.timezone')); } /** * Shows the category chart on the front page. - * See reference nr. 60 + * TODO test method for category refactor. * * @return JsonResponse */ @@ -125,7 +121,7 @@ class CategoryController extends Controller $start = session('start', Carbon::now()->startOfMonth()); $end = session('end', Carbon::now()->endOfMonth()); // chart properties for cache: - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.category.frontpage'); @@ -143,18 +139,18 @@ class CategoryController extends Controller /** * Chart report. - * See reference nr. 61 + * TODO test method for category refactor. * - * @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 JsonResponse */ public function reportPeriod(Category $category, Collection $accounts, Carbon $start, Carbon $end): JsonResponse { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.category.period'); @@ -173,10 +169,10 @@ class CategoryController extends Controller /** * Generate report chart for either with or without category. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end - * @param Category|null $category + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * @param Category|null $category * * @return array */ @@ -197,12 +193,11 @@ class CategoryController extends Controller if (null !== $category) { /** @var OperationsRepositoryInterface $opsRepository */ $opsRepository = app(OperationsRepositoryInterface::class); - $categoryId = (int) $category->id; + $categoryId = (int)$category->id; // this gives us all currencies $collection = new Collection([$category]); $expenses = $opsRepository->listExpenses($start, $end, null, $collection); $income = $opsRepository->listIncome($start, $end, null, $collection); - } $currencies = array_unique(array_merge(array_keys($income), array_keys($expenses))); $periods = app('navigation')->listOfPeriods($start, $end); @@ -216,7 +211,7 @@ class CategoryController extends Controller $inKey = sprintf('%d-in', $currencyId); $chartData[$outKey] = [ - 'label' => sprintf('%s (%s)', (string) trans('firefly.spent'), $currencyInfo['currency_name']), + 'label' => sprintf('%s (%s)', (string)trans('firefly.spent'), $currencyInfo['currency_name']), 'entries' => [], 'type' => 'bar', 'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red @@ -224,7 +219,7 @@ class CategoryController extends Controller $chartData[$inKey] = [ - 'label' => sprintf('%s (%s)', (string) trans('firefly.earned'), $currencyInfo['currency_name']), + 'label' => sprintf('%s (%s)', (string)trans('firefly.earned'), $currencyInfo['currency_name']), 'entries' => [], 'type' => 'bar', 'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green @@ -259,17 +254,17 @@ class CategoryController extends Controller /** * Chart for period for transactions without a category. - * See reference nr. 62 + * TODO test me. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ public function reportPeriodNoCategory(Collection $accounts, Carbon $start, Carbon $end): JsonResponse { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.category.period.no-cat'); @@ -286,15 +281,15 @@ class CategoryController extends Controller /** * Chart for a specific period. - * See reference nr. 63 + * TODO test me, for category refactor. * - * @param Category $category - * @param Carbon $date + * @param Category $category + * @param Carbon $date * * @return JsonResponse * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function specificPeriod(Category $category, Carbon $date): JsonResponse { @@ -305,7 +300,7 @@ class CategoryController extends Controller [$end, $start] = [$start, $end]; } - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($category->id); diff --git a/app/Http/Controllers/Chart/CategoryReportController.php b/app/Http/Controllers/Chart/CategoryReportController.php index 84a73c343d..32daf8d3c1 100644 --- a/app/Http/Controllers/Chart/CategoryReportController.php +++ b/app/Http/Controllers/Chart/CategoryReportController.php @@ -1,4 +1,5 @@ '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -101,10 +103,10 @@ class CategoryReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -119,10 +121,10 @@ class CategoryReportController extends Controller foreach ($currency['categories'] as $category) { $title = sprintf('%s (%s)', $category['name'], $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; foreach ($category['transaction_journals'] as $journal) { $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); @@ -136,10 +138,10 @@ class CategoryReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -154,10 +156,10 @@ class CategoryReportController extends Controller foreach ($currency['categories'] as $category) { $title = sprintf('%s (%s)', $category['name'], $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; foreach ($category['transaction_journals'] as $journal) { $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); @@ -171,10 +173,10 @@ class CategoryReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -191,10 +193,10 @@ class CategoryReportController extends Controller $objectName = $journal['destination_account_name'] ?? trans('firefly.empty'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -207,10 +209,10 @@ class CategoryReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -227,10 +229,10 @@ class CategoryReportController extends Controller $objectName = $journal['destination_account_name'] ?? trans('firefly.empty'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -243,10 +245,10 @@ class CategoryReportController extends Controller } /** - * @param Collection $accounts - * @param Category $category - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Category $category + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse * @@ -263,17 +265,17 @@ class CategoryReportController extends Controller // add things to chart Data for each currency: $spentKey = sprintf('%d-spent', $currency['currency_id']); $chartData[$spentKey] = $chartData[$spentKey] ?? [ - 'label' => sprintf( - '%s (%s)', - (string) trans('firefly.spent_in_specific_category', ['category' => $category->name]), - $currency['currency_name'] - ), - 'type' => 'bar', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_id' => $currency['currency_id'], - 'entries' => $this->makeEntries($start, $end), - ]; + 'label' => sprintf( + '%s (%s)', + (string)trans('firefly.spent_in_specific_category', ['category' => $category->name]), + $currency['currency_name'] + ), + 'type' => 'bar', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_id' => $currency['currency_id'], + 'entries' => $this->makeEntries($start, $end), + ]; foreach ($currency['categories'] as $currentCategory) { foreach ($currentCategory['transaction_journals'] as $journal) { @@ -290,17 +292,17 @@ class CategoryReportController extends Controller // add things to chart Data for each currency: $spentKey = sprintf('%d-earned', $currency['currency_id']); $chartData[$spentKey] = $chartData[$spentKey] ?? [ - 'label' => sprintf( - '%s (%s)', - (string) trans('firefly.earned_in_specific_category', ['category' => $category->name]), - $currency['currency_name'] - ), - 'type' => 'bar', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_id' => $currency['currency_id'], - 'entries' => $this->makeEntries($start, $end), - ]; + 'label' => sprintf( + '%s (%s)', + (string)trans('firefly.earned_in_specific_category', ['category' => $category->name]), + $currency['currency_name'] + ), + 'type' => 'bar', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_id' => $currency['currency_id'], + 'entries' => $this->makeEntries($start, $end), + ]; foreach ($currency['categories'] as $currentCategory) { foreach ($currentCategory['transaction_journals'] as $journal) { @@ -318,10 +320,10 @@ class CategoryReportController extends Controller } /** - * See reference nr. 57 + * TODO duplicate function * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -343,10 +345,10 @@ class CategoryReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -363,10 +365,10 @@ class CategoryReportController extends Controller $objectName = $journal['source_account_name'] ?? trans('firefly.empty'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -379,10 +381,10 @@ class CategoryReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -399,10 +401,10 @@ class CategoryReportController extends Controller $objectName = $journal['source_account_name'] ?? trans('firefly.empty'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } diff --git a/app/Http/Controllers/Chart/DoubleReportController.php b/app/Http/Controllers/Chart/DoubleReportController.php index b1f7fa6a08..cd665346c9 100644 --- a/app/Http/Controllers/Chart/DoubleReportController.php +++ b/app/Http/Controllers/Chart/DoubleReportController.php @@ -38,7 +38,6 @@ use Illuminate\Support\Collection; */ class DoubleReportController extends Controller { - /** @var GeneratorInterface Chart generation methods. */ private $generator; /** @var OperationsRepositoryInterface */ @@ -67,10 +66,10 @@ class DoubleReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $others - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $others + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -87,10 +86,10 @@ class DoubleReportController extends Controller $categoryName = $journal['budget_name'] ?? trans('firefly.no_budget'); $title = sprintf('%s (%s)', $categoryName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -102,10 +101,10 @@ class DoubleReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $others - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $others + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -122,10 +121,10 @@ class DoubleReportController extends Controller $categoryName = $journal['category_name'] ?? trans('firefly.no_category'); $title = sprintf('%s (%s)', $categoryName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -137,10 +136,10 @@ class DoubleReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $others - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $others + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -157,10 +156,10 @@ class DoubleReportController extends Controller $categoryName = $journal['category_name'] ?? trans('firefly.no_category'); $title = sprintf('%s (%s)', $categoryName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -172,10 +171,10 @@ class DoubleReportController extends Controller } /** - * @param Collection $accounts - * @param Account $account - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Account $account + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse * @@ -197,17 +196,17 @@ class DoubleReportController extends Controller $name = $this->getCounterpartName($accounts, $account->id, $account->name, $account->iban); $chartData[$spentKey] = $chartData[$spentKey] ?? [ - 'label' => sprintf( - '%s (%s)', - (string) trans('firefly.spent_in_specific_double', ['account' => $name]), - $currency['currency_name'] - ), - 'type' => 'bar', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_id' => $currency['currency_id'], - 'entries' => $this->makeEntries($start, $end), - ]; + 'label' => sprintf( + '%s (%s)', + (string)trans('firefly.spent_in_specific_double', ['account' => $name]), + $currency['currency_name'] + ), + 'type' => 'bar', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_id' => $currency['currency_id'], + 'entries' => $this->makeEntries($start, $end), + ]; foreach ($currency['transaction_journals'] as $journal) { $key = $journal['date']->isoFormat($format); @@ -223,17 +222,17 @@ class DoubleReportController extends Controller $name = $this->getCounterpartName($accounts, $account->id, $account->name, $account->iban); $chartData[$earnedKey] = $chartData[$earnedKey] ?? [ - 'label' => sprintf( - '%s (%s)', - (string) trans('firefly.earned_in_specific_double', ['account' => $name]), - $currency['currency_name'] - ), - 'type' => 'bar', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_id' => $currency['currency_id'], - 'entries' => $this->makeEntries($start, $end), - ]; + 'label' => sprintf( + '%s (%s)', + (string)trans('firefly.earned_in_specific_double', ['account' => $name]), + $currency['currency_name'] + ), + 'type' => 'bar', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_id' => $currency['currency_id'], + 'entries' => $this->makeEntries($start, $end), + ]; foreach ($currency['transaction_journals'] as $journal) { $key = $journal['date']->isoFormat($format); @@ -249,12 +248,12 @@ class DoubleReportController extends Controller } /** - * See reference nr. 51 + * TODO duplicate function * - * @param Collection $accounts - * @param int $id - * @param string $name - * @param null|string $iban + * @param Collection $accounts + * @param int $id + * @param string $name + * @param null|string $iban * * @return string */ @@ -274,10 +273,10 @@ class DoubleReportController extends Controller } /** - * See reference nr. 52 + * TODO duplicate function * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -299,10 +298,10 @@ class DoubleReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $others - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $others + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -319,16 +318,16 @@ class DoubleReportController extends Controller $journalId = $journal['transaction_journal_id']; // no tags? also deserves a sport - if (empty($journal['tags'])) { + if (0 === count($journal['tags'])) { $includedJournals[] = $journalId; // do something $tagName = trans('firefly.no_tags'); $title = sprintf('%s (%s)', $tagName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -343,10 +342,10 @@ class DoubleReportController extends Controller $tagName = $tag['name']; $title = sprintf('%s (%s)', $tagName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -359,10 +358,10 @@ class DoubleReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $others - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $others + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -379,16 +378,16 @@ class DoubleReportController extends Controller $journalId = $journal['transaction_journal_id']; // no tags? also deserves a sport - if (empty($journal['tags'])) { + if (0 === count($journal['tags'])) { $includedJournals[] = $journalId; // do something $tagName = trans('firefly.no_tags'); $title = sprintf('%s (%s)', $tagName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -403,10 +402,10 @@ class DoubleReportController extends Controller $tagName = $tag['name']; $title = sprintf('%s (%s)', $tagName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } diff --git a/app/Http/Controllers/Chart/ExpenseReportController.php b/app/Http/Controllers/Chart/ExpenseReportController.php index 3a30860805..09af4994c7 100644 --- a/app/Http/Controllers/Chart/ExpenseReportController.php +++ b/app/Http/Controllers/Chart/ExpenseReportController.php @@ -42,7 +42,8 @@ use JsonException; */ class ExpenseReportController extends Controller { - use AugumentData, TransactionCalculation; + use AugumentData; + use TransactionCalculation; /** @var AccountRepositoryInterface The account repository */ protected $accountRepository; @@ -70,19 +71,19 @@ class ExpenseReportController extends Controller /** * Main chart that shows income and expense for a combination of expense/revenue accounts. * - * See reference nr. 58 + * TODO this chart is not multi currency aware. * - * @param Collection $accounts - * @param Collection $expense - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $expense + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse * @throws JsonException */ public function mainChart(Collection $accounts, Collection $expense, Carbon $start, Carbon $end): JsonResponse { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('chart.expense.report.main'); $cache->addProperty($accounts); $cache->addProperty($expense); @@ -98,42 +99,42 @@ class ExpenseReportController extends Controller $currentStart = clone $start; $combined = $this->combineAccounts($expense); // make "all" set: - $all = new Collection; + $all = new Collection(); foreach ($combined as $name => $combination) { $all = $all->merge($combination); } // prep chart data: /** - * @var string $name + * @var string $name * @var Collection $combination */ foreach ($combined as $name => $combination) { // first is always expense account: /** @var Account $exp */ - $exp = $combination->first(); - $chartData[$exp->id . '-in'] = [ - 'label' => sprintf('%s (%s)', $name, (string) trans('firefly.income')), + $exp = $combination->first(); + $chartData[$exp->id.'-in'] = [ + 'label' => sprintf('%s (%s)', $name, (string)trans('firefly.income')), 'type' => 'bar', 'yAxisID' => 'y-axis-0', 'entries' => [], ]; - $chartData[$exp->id . '-out'] = [ - 'label' => sprintf('%s (%s)', $name, (string) trans('firefly.expenses')), + $chartData[$exp->id.'-out'] = [ + 'label' => sprintf('%s (%s)', $name, (string)trans('firefly.expenses')), 'type' => 'bar', 'yAxisID' => 'y-axis-0', 'entries' => [], ]; // total in, total out: - $chartData[$exp->id . '-total-in'] = [ - 'label' => sprintf('%s (%s)', $name, (string) trans('firefly.sum_of_income')), + $chartData[$exp->id.'-total-in'] = [ + 'label' => sprintf('%s (%s)', $name, (string)trans('firefly.sum_of_income')), 'type' => 'line', 'fill' => false, 'yAxisID' => 'y-axis-1', 'entries' => [], ]; - $chartData[$exp->id . '-total-out'] = [ - 'label' => sprintf('%s (%s)', $name, (string) trans('firefly.sum_of_expenses')), + $chartData[$exp->id.'-total-out'] = [ + 'label' => sprintf('%s (%s)', $name, (string)trans('firefly.sum_of_expenses')), 'type' => 'line', 'fill' => false, 'yAxisID' => 'y-axis-1', @@ -157,10 +158,10 @@ class ExpenseReportController extends Controller // first is always expense account: /** @var Account $exp */ $exp = $combination->first(); - $labelIn = $exp->id . '-in'; - $labelOut = $exp->id . '-out'; - $labelSumIn = $exp->id . '-total-in'; - $labelSumOut = $exp->id . '-total-out'; + $labelIn = $exp->id.'-in'; + $labelOut = $exp->id.'-out'; + $labelSumIn = $exp->id.'-total-in'; + $labelSumOut = $exp->id.'-total-out'; $currentIncome = bcmul($income[$name] ?? '0', '-1'); $currentExpense = $expenses[$name] ?? '0'; @@ -184,11 +185,12 @@ class ExpenseReportController extends Controller // remove all empty entries to prevent cluttering: $newSet = []; foreach ($chartData as $key => $entry) { + // TODO not sure, this is a bad comparison. if (0 === !array_sum($entry['entries'])) { $newSet[$key] = $entry; } } - if (empty($newSet)) { + if (0 === count($newSet)) { $newSet = $chartData; } $data = $this->generator->multiSet($newSet); diff --git a/app/Http/Controllers/Chart/PiggyBankController.php b/app/Http/Controllers/Chart/PiggyBankController.php index 7efc12d07a..7e5c609470 100644 --- a/app/Http/Controllers/Chart/PiggyBankController.php +++ b/app/Http/Controllers/Chart/PiggyBankController.php @@ -1,4 +1,5 @@ addProperty('chart.piggy-bank.history'); $cache->addProperty($piggyBank->id); if ($cache->has()) { @@ -82,9 +83,9 @@ class PiggyBankController extends Controller // get first event or start date of piggy bank or today $startDate = $piggyBank->startdate ?? today(config('app.timezone')); - /** @var PiggyBankEvent $firstEvent */ + /** @var PiggyBankEvent|null $firstEvent */ $firstEvent = $set->first(); - $firstDate = null === $firstEvent ? new Carbon : $firstEvent->date; + $firstDate = null === $firstEvent ? new Carbon() : $firstEvent->date; // which ever is older: $oldest = $startDate->lt($firstDate) ? $startDate : $firstDate; @@ -100,7 +101,7 @@ class PiggyBankController extends Controller } ); $currentSum = $filtered->sum('amount'); - $label = $oldest->isoFormat((string) trans('config.month_and_day_js', [], $locale)); + $label = $oldest->isoFormat((string)trans('config.month_and_day_js', [], $locale)); $chartData[$label] = $currentSum; $oldest = app('navigation')->addPeriod($oldest, $step, 0); } @@ -110,7 +111,7 @@ class PiggyBankController extends Controller } ); $finalSum = $finalFiltered->sum('amount'); - $finalLabel = $today->isoFormat((string) trans('config.month_and_day_js', [], $locale)); + $finalLabel = $today->isoFormat((string)trans('config.month_and_day_js', [], $locale)); $chartData[$finalLabel] = $finalSum; $data = $this->generator->singleSet($piggyBank->name, $chartData); diff --git a/app/Http/Controllers/Chart/ReportController.php b/app/Http/Controllers/Chart/ReportController.php index 360fd65f68..915934fd44 100644 --- a/app/Http/Controllers/Chart/ReportController.php +++ b/app/Http/Controllers/Chart/ReportController.php @@ -1,4 +1,5 @@ addProperty('chart.report.net-worth'); $cache->addProperty($start); $cache->addProperty(implode(',', $accounts->pluck('id')->toArray())); @@ -104,7 +107,7 @@ class ReportController extends Controller } ); - // See reference nr. 56 + // TODO get liabilities and include those as well? while ($current < $end) { // get balances by date, grouped by currency. @@ -114,10 +117,10 @@ class ReportController extends Controller /** @var array $netWorthItem */ foreach ($result as $netWorthItem) { $currencyId = $netWorthItem['currency']->id; - $label = $current->isoFormat((string) trans('config.month_and_day_js', [], $locale)); + $label = $current->isoFormat((string)trans('config.month_and_day_js', [], $locale)); if (!array_key_exists($currencyId, $chartData)) { $chartData[$currencyId] = [ - 'label' => 'Net worth in ' . $netWorthItem['currency']->name, + 'label' => 'Net worth in '.$netWorthItem['currency']->name, 'type' => 'line', 'currency_symbol' => $netWorthItem['currency']->symbol, 'currency_code' => $netWorthItem['currency']->code, @@ -125,7 +128,6 @@ class ReportController extends Controller ]; } $chartData[$currencyId]['entries'][$label] = $netWorthItem['balance']; - } $current->addDays(7); } @@ -139,9 +141,9 @@ class ReportController extends Controller /** * Shows income and expense, debit/credit: operations. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse * @throws JsonException @@ -149,7 +151,7 @@ class ReportController extends Controller public function operations(Collection $accounts, Carbon $start, Carbon $end): JsonResponse { // chart properties for cache: - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('chart.report.operations'); $cache->addProperty($start); $cache->addProperty($accounts); @@ -179,13 +181,13 @@ class ReportController extends Controller /** @var array $journal */ foreach ($journals as $journal) { $period = $journal['date']->format($format); - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $data[$currencyId] = $data[$currencyId] ?? [ 'currency_id' => $currencyId, 'currency_symbol' => $journal['currency_symbol'], 'currency_code' => $journal['currency_code'], 'currency_name' => $journal['currency_name'], - 'currency_decimal_places' => (int) $journal['currency_decimal_places'], + 'currency_decimal_places' => (int)$journal['currency_decimal_places'], ]; $data[$currencyId][$period] = $data[$currencyId][$period] ?? [ 'period' => $period, @@ -220,7 +222,7 @@ class ReportController extends Controller /** @var array $currency */ foreach ($data as $currency) { $income = [ - 'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]), + 'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $currency['currency_name']]), 'type' => 'bar', 'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green 'currency_id' => $currency['currency_id'], @@ -229,7 +231,7 @@ class ReportController extends Controller 'entries' => [], ]; $expense = [ - 'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]), + 'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $currency['currency_name']]), 'type' => 'bar', 'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red 'currency_id' => $currency['currency_id'], diff --git a/app/Http/Controllers/Chart/TagReportController.php b/app/Http/Controllers/Chart/TagReportController.php index 75a452165a..355b240a4c 100644 --- a/app/Http/Controllers/Chart/TagReportController.php +++ b/app/Http/Controllers/Chart/TagReportController.php @@ -1,4 +1,5 @@ '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -102,10 +104,10 @@ class TagReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -122,10 +124,10 @@ class TagReportController extends Controller $objectName = $journal['category_name'] ?? trans('firefly.no_category'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -138,10 +140,10 @@ class TagReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -158,10 +160,10 @@ class TagReportController extends Controller $objectName = $journal['category_name'] ?? trans('firefly.no_category'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -174,10 +176,10 @@ class TagReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -194,10 +196,10 @@ class TagReportController extends Controller $objectName = $journal['destination_account_name'] ?? trans('firefly.empty'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -210,10 +212,10 @@ class TagReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -230,10 +232,10 @@ class TagReportController extends Controller $objectName = $journal['destination_account_name'] ?? trans('firefly.empty'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -248,10 +250,10 @@ class TagReportController extends Controller /** * Generate main tag overview chart. * - * @param Collection $accounts - * @param Tag $tag - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse * @@ -268,17 +270,17 @@ class TagReportController extends Controller // add things to chart Data for each currency: $spentKey = sprintf('%d-spent', $currency['currency_id']); $chartData[$spentKey] = $chartData[$spentKey] ?? [ - 'label' => sprintf( - '%s (%s)', - (string) trans('firefly.spent_in_specific_tag', ['tag' => $tag->tag]), - $currency['currency_name'] - ), - 'type' => 'bar', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_id' => $currency['currency_id'], - 'entries' => $this->makeEntries($start, $end), - ]; + 'label' => sprintf( + '%s (%s)', + (string)trans('firefly.spent_in_specific_tag', ['tag' => $tag->tag]), + $currency['currency_name'] + ), + 'type' => 'bar', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_id' => $currency['currency_id'], + 'entries' => $this->makeEntries($start, $end), + ]; foreach ($currency['tags'] as $currentTag) { foreach ($currentTag['transaction_journals'] as $journal) { @@ -295,17 +297,17 @@ class TagReportController extends Controller // add things to chart Data for each currency: $spentKey = sprintf('%d-earned', $currency['currency_id']); $chartData[$spentKey] = $chartData[$spentKey] ?? [ - 'label' => sprintf( - '%s (%s)', - (string) trans('firefly.earned_in_specific_tag', ['tag' => $tag->tag]), - $currency['currency_name'] - ), - 'type' => 'bar', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_id' => $currency['currency_id'], - 'entries' => $this->makeEntries($start, $end), - ]; + 'label' => sprintf( + '%s (%s)', + (string)trans('firefly.earned_in_specific_tag', ['tag' => $tag->tag]), + $currency['currency_name'] + ), + 'type' => 'bar', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_id' => $currency['currency_id'], + 'entries' => $this->makeEntries($start, $end), + ]; foreach ($currency['tags'] as $currentTag) { foreach ($currentTag['transaction_journals'] as $journal) { @@ -323,10 +325,10 @@ class TagReportController extends Controller } /** - * See reference nr. 54 + * TODO duplicate function * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -348,10 +350,10 @@ class TagReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -368,10 +370,10 @@ class TagReportController extends Controller $objectName = $journal['source_account_name'] ?? trans('firefly.empty'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -384,10 +386,10 @@ class TagReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -404,10 +406,10 @@ class TagReportController extends Controller $objectName = $journal['source_account_name'] ?? trans('firefly.empty'); $title = sprintf('%s (%s)', $objectName, $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); } @@ -420,10 +422,10 @@ class TagReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -438,10 +440,10 @@ class TagReportController extends Controller foreach ($currency['tags'] as $tag) { $title = sprintf('%s (%s)', $tag['name'], $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; foreach ($tag['transaction_journals'] as $journal) { $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); @@ -454,10 +456,10 @@ class TagReportController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -472,10 +474,10 @@ class TagReportController extends Controller foreach ($currency['tags'] as $tag) { $title = sprintf('%s (%s)', $tag['name'], $currency['currency_name']); $result[$title] = $result[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + ]; foreach ($tag['transaction_journals'] as $journal) { $amount = app('steam')->positive($journal['amount']); $result[$title]['amount'] = bcadd($result[$title]['amount'], $amount); diff --git a/app/Http/Controllers/Chart/TransactionController.php b/app/Http/Controllers/Chart/TransactionController.php index 6aae2bf3db..01a65da0e7 100644 --- a/app/Http/Controllers/Chart/TransactionController.php +++ b/app/Http/Controllers/Chart/TransactionController.php @@ -32,14 +32,12 @@ use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\TransactionType; use FireflyIII\Support\CacheProperties; use Illuminate\Http\JsonResponse; -use JsonException; /** * Class TransactionController */ class TransactionController extends Controller { - /** @var GeneratorInterface Chart generation methods. */ protected $generator; @@ -53,14 +51,14 @@ class TransactionController extends Controller } /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ public function budgets(Carbon $start, Carbon $end) { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('chart.transactions.budgets'); @@ -79,13 +77,13 @@ class TransactionController extends Controller // group by category. /** @var array $journal */ foreach ($result as $journal) { - $budget = $journal['budget_name'] ?? (string) trans('firefly.no_budget'); + $budget = $journal['budget_name'] ?? (string)trans('firefly.no_budget'); $title = sprintf('%s (%s)', $budget, $journal['currency_symbol']); $data[$title] = $data[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + ]; $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['amount']); } $chart = $this->generator->multiCurrencyPieChart($data); @@ -95,16 +93,16 @@ class TransactionController extends Controller } /** - * @param string $objectType - * @param Carbon $start - * @param Carbon $end + * @param string $objectType + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse * @throws FireflyException */ public function categories(string $objectType, Carbon $start, Carbon $end) { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($objectType); @@ -116,35 +114,31 @@ class TransactionController extends Controller $collector = app(GroupCollectorInterface::class); $collector->setRange($start, $end); $collector->withCategoryInformation(); - switch ($objectType) { - default: - throw new FireflyException(sprintf('Cant handle "%s"', $objectType)); - case 'withdrawal': - $collector->setTypes([TransactionType::WITHDRAWAL]); - break; - case 'deposit': - $collector->setTypes([TransactionType::DEPOSIT]); - break; - case 'transfers': - case 'transfer': - $collector->setTypes([TransactionType::TRANSFER]); - break; + + if ('withdrawal' === $objectType) { + $collector->setTypes([TransactionType::WITHDRAWAL]); } + if ('deposit' === $objectType) { + $collector->setTypes([TransactionType::DEPOSIT]); + } + if ('transfer' === $objectType || 'transfers' === $objectType) { + $collector->setTypes([TransactionType::TRANSFER]); + } + $result = $collector->getExtractedJournals(); $data = []; // group by category. /** @var array $journal */ foreach ($result as $journal) { - $category = $journal['category_name'] ?? (string) trans('firefly.no_category'); + $category = $journal['category_name'] ?? (string)trans('firefly.no_category'); $title = sprintf('%s (%s)', $category, $journal['currency_symbol']); $data[$title] = $data[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + ]; $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['amount']); - } $chart = $this->generator->multiCurrencyPieChart($data); $cache->store($chart); @@ -153,16 +147,16 @@ class TransactionController extends Controller } /** - * @param string $objectType - * @param Carbon $start - * @param Carbon $end + * @param string $objectType + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse * @throws FireflyException */ public function destinationAccounts(string $objectType, Carbon $start, Carbon $end) { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($objectType); @@ -174,20 +168,17 @@ class TransactionController extends Controller $collector = app(GroupCollectorInterface::class); $collector->setRange($start, $end); $collector->withAccountInformation(); - switch ($objectType) { - default: - throw new FireflyException(sprintf('Cant handle "%s"', $objectType)); - case 'withdrawal': - $collector->setTypes([TransactionType::WITHDRAWAL]); - break; - case 'deposit': - $collector->setTypes([TransactionType::DEPOSIT]); - break; - case 'transfers': - case 'transfer': - $collector->setTypes([TransactionType::TRANSFER]); - break; + + if ('withdrawal' === $objectType) { + $collector->setTypes([TransactionType::WITHDRAWAL]); } + if ('deposit' === $objectType) { + $collector->setTypes([TransactionType::DEPOSIT]); + } + if ('transfer' === $objectType || 'transfers' === $objectType) { + $collector->setTypes([TransactionType::TRANSFER]); + } + $result = $collector->getExtractedJournals(); $data = []; @@ -197,10 +188,10 @@ class TransactionController extends Controller $name = $journal['destination_account_name']; $title = sprintf('%s (%s)', $name, $journal['currency_symbol']); $data[$title] = $data[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + ]; $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['amount']); } $chart = $this->generator->multiCurrencyPieChart($data); @@ -210,16 +201,16 @@ class TransactionController extends Controller } /** - * @param string $objectType - * @param Carbon $start - * @param Carbon $end + * @param string $objectType + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse * @throws FireflyException */ public function sourceAccounts(string $objectType, Carbon $start, Carbon $end) { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($objectType); @@ -231,20 +222,17 @@ class TransactionController extends Controller $collector = app(GroupCollectorInterface::class); $collector->setRange($start, $end); $collector->withAccountInformation(); - switch ($objectType) { - default: - throw new FireflyException(sprintf('Cant handle "%s"', $objectType)); - case 'withdrawal': - $collector->setTypes([TransactionType::WITHDRAWAL]); - break; - case 'deposit': - $collector->setTypes([TransactionType::DEPOSIT]); - break; - case 'transfers': - case 'transfer': - $collector->setTypes([TransactionType::TRANSFER]); - break; + + if ('withdrawal' === $objectType) { + $collector->setTypes([TransactionType::WITHDRAWAL]); } + if ('deposit' === $objectType) { + $collector->setTypes([TransactionType::DEPOSIT]); + } + if ('transfer' === $objectType || 'transfers' === $objectType) { + $collector->setTypes([TransactionType::TRANSFER]); + } + $result = $collector->getExtractedJournals(); $data = []; @@ -254,12 +242,11 @@ class TransactionController extends Controller $name = $journal['source_account_name']; $title = sprintf('%s (%s)', $name, $journal['currency_symbol']); $data[$title] = $data[$title] ?? [ - 'amount' => '0', - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - ]; + 'amount' => '0', + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + ]; $data[$title]['amount'] = bcadd($data[$title]['amount'], $journal['amount']); - } $chart = $this->generator->multiCurrencyPieChart($data); $cache->store($chart); diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 6b8e669766..b71dd07d2a 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -1,4 +1,5 @@ getLocale(); // translations for specific strings: - $this->monthFormat = (string) trans('config.month_js', [], $locale); - $this->monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale); - $this->dateTimeFormat = (string) trans('config.date_time_js', [], $locale); + $this->monthFormat = (string)trans('config.month_js', [], $locale); + $this->monthAndDayFormat = (string)trans('config.month_and_day_js', [], $locale); + $this->dateTimeFormat = (string)trans('config.date_time_js', [], $locale); // get shown-intro-preference: if (auth()->check()) { diff --git a/app/Http/Controllers/CurrencyController.php b/app/Http/Controllers/CurrencyController.php index 6b61c923f6..b63cf9030a 100644 --- a/app/Http/Controllers/CurrencyController.php +++ b/app/Http/Controllers/CurrencyController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.currencies')); + app('view')->share('title', (string)trans('firefly.currencies')); app('view')->share('mainTitleIcon', 'fa-usd'); $this->repository = app(CurrencyRepositoryInterface::class); $this->userRepository = app(UserRepositoryInterface::class); @@ -69,7 +72,7 @@ class CurrencyController extends Controller /** * Create a currency. * - * @param Request $request + * @param Request $request * * @return Factory|RedirectResponse|Redirector|View */ @@ -78,13 +81,13 @@ class CurrencyController extends Controller /** @var User $user */ $user = auth()->user(); if (!$this->userRepository->hasRole($user, 'owner')) { - $request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); + $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); return redirect(route('currencies.index')); } $subTitleIcon = 'fa-plus'; - $subTitle = (string) trans('firefly.create_currency'); + $subTitle = (string)trans('firefly.create_currency'); // put previous url in session if not redirect from store (not "create another"). if (true !== session('currencies.create.fromStore')) { @@ -100,14 +103,14 @@ class CurrencyController extends Controller /** * Make currency the default currency. * - * @param Request $request + * @param Request $request * * @return RedirectResponse|Redirector * @throws FireflyException */ public function defaultCurrency(Request $request) { - $currencyId = (int) $request->get('id'); + $currencyId = (int)$request->get('id'); if ($currencyId > 0) { // valid currency? $currency = $this->repository->find($currencyId); @@ -117,7 +120,7 @@ class CurrencyController extends Controller Log::channel('audit')->info(sprintf('Make %s the default currency.', $currency->code)); $this->repository->enable($currency); - $request->session()->flash('success', (string) trans('firefly.new_default_currency', ['name' => $currency->name])); + $request->session()->flash('success', (string)trans('firefly.new_default_currency', ['name' => $currency->name])); return redirect(route('currencies.index')); } @@ -129,8 +132,8 @@ class CurrencyController extends Controller /** * Deletes a currency. * - * @param Request $request - * @param TransactionCurrency $currency + * @param Request $request + * @param TransactionCurrency $currency * * @return Factory|RedirectResponse|Redirector|View */ @@ -139,17 +142,15 @@ class CurrencyController extends Controller /** @var User $user */ $user = auth()->user(); if (!$this->userRepository->hasRole($user, 'owner')) { - - $request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); + $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but is not site owner.', $currency->code)); return redirect(route('currencies.index')); - } if ($this->repository->currencyInUse($currency)) { $location = $this->repository->currencyInUseAt($currency); - $message = (string) trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]); + $message = (string)trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]); $request->session()->flash('error', $message); Log::channel('audit')->info(sprintf('Tried to visit page to delete currency %s but currency is in use.', $currency->code)); @@ -158,7 +159,7 @@ class CurrencyController extends Controller // put previous url in session $this->rememberPreviousUrl('currencies.delete.url'); - $subTitle = (string) trans('form.delete_currency', ['name' => $currency->name]); + $subTitle = (string)trans('form.delete_currency', ['name' => $currency->name]); Log::channel('audit')->info(sprintf('Visit page to delete currency %s.', $currency->code)); return view('currencies.delete', compact('currency', 'subTitle')); @@ -167,8 +168,8 @@ class CurrencyController extends Controller /** * Destroys a currency. * - * @param Request $request - * @param TransactionCurrency $currency + * @param Request $request + * @param TransactionCurrency $currency * * @return RedirectResponse|Redirector */ @@ -177,23 +178,21 @@ class CurrencyController extends Controller /** @var User $user */ $user = auth()->user(); if (!$this->userRepository->hasRole($user, 'owner')) { - - $request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); + $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); Log::channel('audit')->info(sprintf('Tried to delete currency %s but is not site owner.', $currency->code)); return redirect(route('currencies.index')); - } if ($this->repository->currencyInUse($currency)) { - $request->session()->flash('error', (string) trans('firefly.cannot_delete_currency', ['name' => e($currency->name)])); + $request->session()->flash('error', (string)trans('firefly.cannot_delete_currency', ['name' => e($currency->name)])); Log::channel('audit')->info(sprintf('Tried to delete currency %s but is in use.', $currency->code)); return redirect(route('currencies.index')); } if ($this->repository->isFallbackCurrency($currency)) { - $request->session()->flash('error', (string) trans('firefly.cannot_delete_fallback_currency', ['name' => e($currency->name)])); + $request->session()->flash('error', (string)trans('firefly.cannot_delete_fallback_currency', ['name' => e($currency->name)])); Log::channel('audit')->info(sprintf('Tried to delete currency %s but is FALLBACK.', $currency->code)); return redirect(route('currencies.index')); @@ -202,19 +201,19 @@ class CurrencyController extends Controller Log::channel('audit')->info(sprintf('Deleted currency %s.', $currency->code)); $this->repository->destroy($currency); - $request->session()->flash('success', (string) trans('firefly.deleted_currency', ['name' => $currency->name])); + $request->session()->flash('success', (string)trans('firefly.deleted_currency', ['name' => $currency->name])); return redirect($this->getPreviousUrl('currencies.delete.url')); } /** - * @param Request $request + * @param Request $request * @return JsonResponse * @throws FireflyException */ public function disableCurrency(Request $request): JsonResponse { - $currencyId = (int) $request->get('id'); + $currencyId = (int)$request->get('id'); $currency = $this->repository->find($currencyId); // valid currency? @@ -228,18 +227,15 @@ class CurrencyController extends Controller /** @var User $user */ $user = auth()->user(); if (!$this->userRepository->hasRole($user, 'owner')) { - - $request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); + $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); Log::channel('audit')->info(sprintf('Tried to disable currency %s but is not site owner.', $currency->code)); return response()->json([]); - } // currency cannot be in use. if ($this->repository->currencyInUse($currency)) { - $location = $this->repository->currencyInUseAt($currency); - $message = (string) trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]); + $message = (string)trans(sprintf('firefly.cannot_disable_currency_%s', $location), ['name' => e($currency->name)]); $request->session()->flash('error', $message); Log::channel('audit')->info(sprintf('Tried to disable currency %s but is in use.', $currency->code)); @@ -254,18 +250,18 @@ class CurrencyController extends Controller // extra warning if ('EUR' === $currency->code) { - session()->flash('warning', (string) trans('firefly.disable_EUR_side_effects')); + session()->flash('warning', (string)trans('firefly.disable_EUR_side_effects')); } - session()->flash('success', (string) trans('firefly.currency_is_now_disabled', ['name' => $currency->name])); + session()->flash('success', (string)trans('firefly.currency_is_now_disabled', ['name' => $currency->name])); return response()->json([]); } /** * Edit a currency. * - * @param Request $request - * @param TransactionCurrency $currency + * @param Request $request + * @param TransactionCurrency $currency * * @return Factory|RedirectResponse|Redirector|View */ @@ -274,22 +270,20 @@ class CurrencyController extends Controller /** @var User $user */ $user = auth()->user(); if (!$this->userRepository->hasRole($user, 'owner')) { - - $request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); + $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); Log::channel('audit')->info(sprintf('Tried to edit currency %s but is not owner.', $currency->code)); return redirect(route('currencies.index')); - } $subTitleIcon = 'fa-pencil'; - $subTitle = (string) trans('breadcrumbs.edit_currency', ['name' => $currency->name]); + $subTitle = (string)trans('breadcrumbs.edit_currency', ['name' => $currency->name]); $currency->symbol = htmlentities($currency->symbol); // code to handle active-checkboxes $hasOldInput = null !== $request->old('_token'); $preFilled = [ - 'enabled' => $hasOldInput ? (bool) $request->old('enabled') : $currency->enabled, + 'enabled' => $hasOldInput ? (bool)$request->old('enabled') : $currency->enabled, ]; $request->session()->flash('preFilled', $preFilled); @@ -305,12 +299,12 @@ class CurrencyController extends Controller } /** - * @param Request $request - * @return RedirectResponse|Redirector + * @param Request $request + * @return JsonResponse */ public function enableCurrency(Request $request): JsonResponse { - $currencyId = (int) $request->get('id'); + $currencyId = (int)$request->get('id'); if ($currencyId > 0) { // valid currency? $currency = $this->repository->find($currencyId); @@ -318,7 +312,7 @@ class CurrencyController extends Controller app('preferences')->mark(); $this->repository->enable($currency); - session()->flash('success', (string) trans('firefly.currency_is_now_enabled', ['name' => $currency->name])); + session()->flash('success', (string)trans('firefly.currency_is_now_enabled', ['name' => $currency->name])); Log::channel('audit')->info(sprintf('Enabled currency %s.', $currency->code)); } } @@ -329,19 +323,19 @@ class CurrencyController extends Controller /** * Show overview of currencies. * - * @param Request $request + * @param Request $request * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index(Request $request) { /** @var User $user */ $user = auth()->user(); - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $collection = $this->repository->getAll(); $total = $collection->count(); $collection = $collection->slice(($page - 1) * $pageSize, $pageSize); @@ -351,7 +345,7 @@ class CurrencyController extends Controller $defaultCurrency = $this->repository->getCurrencyByPreference(app('preferences')->get('currencyPreference', config('firefly.default_currency', 'EUR'))); $isOwner = true; if (!$this->userRepository->hasRole($user, 'owner')) { - $request->session()->flash('info', (string) trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')])); + $request->session()->flash('info', (string)trans('firefly.ask_site_owner', ['owner' => config('firefly.site_owner')])); $isOwner = false; } @@ -361,7 +355,7 @@ class CurrencyController extends Controller /** * Store new currency. * - * @param CurrencyFormRequest $request + * @param CurrencyFormRequest $request * * @return $this|RedirectResponse|Redirector */ @@ -371,12 +365,10 @@ class CurrencyController extends Controller $user = auth()->user(); $data = $request->getCurrencyData(); if (!$this->userRepository->hasRole($user, 'owner')) { - - Log::error('User ' . auth()->user()->id . ' is not admin, but tried to store a currency.'); + Log::error('User '.auth()->user()->id.' is not admin, but tried to store a currency.'); Log::channel('audit')->info('Tried to create (POST) currency without admin rights.', $data); return redirect($this->getPreviousUrl('currencies.create.url')); - } $data['enabled'] = true; @@ -385,20 +377,18 @@ class CurrencyController extends Controller } catch (FireflyException $e) { Log::error($e->getMessage()); Log::channel('audit')->info('Could not store (POST) currency without admin rights.', $data); - $request->session()->flash('error', (string) trans('firefly.could_not_store_currency')); + $request->session()->flash('error', (string)trans('firefly.could_not_store_currency')); $currency = null; } $redirect = redirect($this->getPreviousUrl('currencies.create.url')); if (null !== $currency) { - $request->session()->flash('success', (string) trans('firefly.created_currency', ['name' => $currency->name])); + $request->session()->flash('success', (string)trans('firefly.created_currency', ['name' => $currency->name])); Log::channel('audit')->info('Created (POST) currency.', $data); - if (1 === (int) $request->get('create_another')) { - + if (1 === (int)$request->get('create_another')) { $request->session()->put('currencies.create.fromStore', true); $redirect = redirect(route('currencies.create'))->withInput(); - } } @@ -408,8 +398,8 @@ class CurrencyController extends Controller /** * Updates a currency. * - * @param CurrencyFormRequest $request - * @param TransactionCurrency $currency + * @param CurrencyFormRequest $request + * @param TransactionCurrency $currency * * @return RedirectResponse|Redirector */ @@ -423,24 +413,20 @@ class CurrencyController extends Controller $data['enabled'] = true; } if (!$this->userRepository->hasRole($user, 'owner')) { - - $request->session()->flash('error', (string) trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); + $request->session()->flash('error', (string)trans('firefly.ask_site_owner', ['owner' => e(config('firefly.site_owner'))])); Log::channel('audit')->info('Tried to update (POST) currency without admin rights.', $data); return redirect(route('currencies.index')); - } $currency = $this->repository->update($currency, $data); Log::channel('audit')->info('Updated (POST) currency.', $data); - $request->session()->flash('success', (string) trans('firefly.updated_currency', ['name' => $currency->name])); + $request->session()->flash('success', (string)trans('firefly.updated_currency', ['name' => $currency->name])); app('preferences')->mark(); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { $request->session()->put('currencies.edit.fromUpdate', true); return redirect(route('currencies.edit', [$currency->id])); - } return redirect($this->getPreviousUrl('currencies.edit.url')); diff --git a/app/Http/Controllers/DebugController.php b/app/Http/Controllers/DebugController.php index 451f92d9d7..0dcac8326f 100644 --- a/app/Http/Controllers/DebugController.php +++ b/app/Http/Controllers/DebugController.php @@ -70,7 +70,7 @@ class DebugController extends Controller Log::debug('This is a test message at the DEBUG level.'); Log::info('This is a test message at the INFO level.'); Log::notice('This is a test message at the NOTICE level.'); - Log::warning('This is a test message at the WARNING level.'); + app('log')->warning('This is a test message at the WARNING level.'); Log::error('This is a test message at the ERROR level.'); Log::critical('This is a test message at the CRITICAL level.'); Log::alert('This is a test message at the ALERT level.'); @@ -81,14 +81,14 @@ class DebugController extends Controller /** * Clear log and session. * - * @param Request $request + * @param Request $request * * @return RedirectResponse|Redirector */ public function flush(Request $request) { app('preferences')->mark(); - $request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range','temp-mfa-secret','temp-mfa-codes']); + $request->session()->forget(['start', 'end', '_previous', 'viewRange', 'range', 'is_custom_range', 'temp-mfa-secret', 'temp-mfa-codes']); Log::debug('Call cache:clear...'); Artisan::call('cache:clear'); Log::debug('Call config:clear...'); @@ -98,9 +98,8 @@ class DebugController extends Controller Log::debug('Call twig:clean...'); try { Artisan::call('twig:clean'); - - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException + } catch (Exception $e) { // intentional generic exception + throw new FireflyException($e->getMessage(), 0, $e); } Log::debug('Call view:clear...'); @@ -113,7 +112,7 @@ class DebugController extends Controller /** * Show debug info. * - * @param Request $request + * @param Request $request * * @return Factory|View * @throws FireflyException @@ -143,10 +142,10 @@ class DebugController extends Controller $logChannel = config('logging.default'); $appLogLevel = config('logging.level'); $displayErrors = ini_get('display_errors'); - $errorReporting = $this->errorReporting((int) ini_get('error_reporting')); + $errorReporting = $this->errorReporting((int)ini_get('error_reporting')); $interface = PHP_SAPI; - $defaultLanguage = (string) config('firefly.default_language'); - $defaultLocale = (string) config('firefly.default_locale'); + $defaultLanguage = (string)config('firefly.default_language'); + $defaultLocale = (string)config('firefly.default_locale'); $bcscale = bcscale(); $drivers = implode(', ', DB::availableDrivers()); $currentDriver = DB::getDriverName(); @@ -181,25 +180,20 @@ class DebugController extends Controller // get latest log file: $logger = Log::driver(); - $handlers = $logger->getHandlers(); + // PHPstan doesn't recognize the method because of its polymorphic nature. + $handlers = $logger->getHandlers(); // @phpstan-ignore-line $logContent = ''; foreach ($handlers as $handler) { if ($handler instanceof RotatingFileHandler) { $logFile = $handler->getUrl(); if (null !== $logFile) { - try { - $logContent = file_get_contents($logFile); - - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - + $logContent = file_get_contents($logFile); } } } if ('' !== $logContent) { // last few lines - $logContent = 'Truncated from this point <----|' . substr($logContent, -8192); + $logContent = 'Truncated from this point <----|'.substr($logContent, -8192); } return view( @@ -238,55 +232,14 @@ class DebugController extends Controller 'defaultLanguage', 'defaultLocale', 'isDocker' - ) ); } - /** - * Return all possible routes. - * - * @return string - */ - public function routes(): string - { - $set = RouteFacade::getRoutes(); - $ignore = ['chart.', 'javascript.', 'json.', 'report-data.', 'popup.', 'debugbar.', 'attachments.download', 'attachments.preview', - 'bills.rescan', 'budgets.income', 'currencies.def', 'error', 'flush', 'help.show', - 'login', 'logout', 'password.reset', 'profile.confirm-email-change', 'profile.undo-email-change', - 'register', 'report.options', 'routes', 'rule-groups.down', 'rule-groups.up', 'rules.up', 'rules.down', - 'rules.select', 'search.search', 'test-flash', 'transactions.link.delete', 'transactions.link.switch', - 'two-factor.lost', 'reports.options', 'debug', - 'preferences.delete-code', 'rules.test-triggers', 'piggy-banks.remove-money', 'piggy-banks.add-money', - 'accounts.reconcile.transactions', 'accounts.reconcile.overview', - 'transactions.clone', 'two-factor.index', 'api.v1', 'installer.', 'attachments.view', 'recurring.events', - 'recurring.suggest', - ]; - $return = ' '; - /** @var Route $route */ - foreach ($set as $route) { - $name = (string) $route->getName(); - if (in_array('GET', $route->methods(), true)) { - $found = false; - foreach ($ignore as $string) { - if (false !== stripos($name, $string)) { - $found = true; - break; - } - } - if (false === $found) { - $return .= 'touch ' . $route->getName() . '.md;'; - } - } - } - - return $return; - } - /** * Flash all types of messages. * - * @param Request $request + * @param Request $request * * @return RedirectResponse|Redirector */ diff --git a/app/Http/Controllers/Export/IndexController.php b/app/Http/Controllers/Export/IndexController.php index f21893777e..ba72ae174b 100644 --- a/app/Http/Controllers/Export/IndexController.php +++ b/app/Http/Controllers/Export/IndexController.php @@ -38,7 +38,6 @@ use Illuminate\View\View; */ class IndexController extends Controller { - private JournalRepositoryInterface $journalRepository; /** @@ -54,7 +53,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-life-bouy'); - app('view')->share('title', (string) trans('firefly.export_data_title')); + app('view')->share('title', (string)trans('firefly.export_data_title')); $this->journalRepository = app(JournalRepositoryInterface::class); $this->middleware(IsDemoUser::class)->except(['index']); @@ -93,7 +92,7 @@ class IndexController extends Controller $response ->header('Content-Description', 'File Transfer') ->header('Content-Type', 'text/x-csv') - ->header('Content-Disposition', 'attachment; filename=' . $quoted) + ->header('Content-Disposition', 'attachment; filename='.$quoted) //->header('Content-Transfer-Encoding', 'binary') ->header('Connection', 'Keep-Alive') ->header('Expires', '0') @@ -112,5 +111,4 @@ class IndexController extends Controller { return view('export.index'); } - } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 07e635b5d8..ef5037cea3 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -1,4 +1,5 @@ $request->get('start'), 'end' => $request->get('end'), 'label' => $request->get('label')]); // check if the label is "everything" or "Custom range" which will betray // a possible problem with the budgets. - if ($label === (string) trans('firefly.everything') || $label === (string) trans('firefly.customRange')) { + if ($label === (string)trans('firefly.everything') || $label === (string)trans('firefly.customRange')) { $isCustomRange = true; Log::debug('Range is now marked as "custom".'); } @@ -80,7 +82,7 @@ class HomeController extends Controller $diff = $start->diffInDays($end) + 1; if ($diff > 50) { - $request->session()->flash('warning', (string) trans('firefly.warning_much_data', ['days' => $diff])); + $request->session()->flash('warning', (string)trans('firefly.warning_much_data', ['days' => $diff])); } $request->session()->put('is_custom_range', $isCustomRange); @@ -96,10 +98,10 @@ class HomeController extends Controller /** * Show index. * - * @param AccountRepositoryInterface $repository + * @param AccountRepositoryInterface $repository * * @return mixed - * @throws \FireflyIII\Exceptions\FireflyException + * @throws FireflyException */ public function index(AccountRepositoryInterface $repository): mixed { @@ -113,14 +115,13 @@ class HomeController extends Controller if (0 === $count) { return redirect(route('new-user.index')); } - $subTitle = (string) trans('firefly.welcome_back'); + $subTitle = (string)trans('firefly.welcome_back'); $transactions = []; $frontPage = app('preferences')->getFresh('frontPageAccounts', $repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray()); /** @var Carbon $start */ $start = session('start', Carbon::now()->startOfMonth()); /** @var Carbon $end */ - $end = session('end', Carbon::now()->endOfMonth()); - /** @noinspection NullPointerExceptionInspection */ + $end = session('end', Carbon::now()->endOfMonth()); $accounts = $repository->getAccountsById($frontPage->data); $today = today(config('app.timezone')); diff --git a/app/Http/Controllers/JavascriptController.php b/app/Http/Controllers/JavascriptController.php index 72d37453bd..68c390fe90 100644 --- a/app/Http/Controllers/JavascriptController.php +++ b/app/Http/Controllers/JavascriptController.php @@ -1,4 +1,5 @@ get('currencyPreference', config('firefly.default_currency', 'EUR')); - /** @noinspection NullPointerExceptionInspection */ - $default = $currencyRepository->findByCodeNull((string) $preference->data); + $default = $currencyRepository->findByCodeNull((string)$preference->data); $data = ['accounts' => []]; /** @var Account $account */ foreach ($accounts as $account) { - $accountId = $account->id; - $currency = (int) $repository->getMetaValue($account, 'currency_id'); - /** @noinspection NullPointerExceptionInspection */ + $accountId = $account->id; + $currency = (int)$repository->getMetaValue($account, 'currency_id'); $currency = 0 === $currency ? $default->id : $currency; $entry = ['preferredCurrency' => $currency, 'name' => $account->name]; $data['accounts'][$accountId] = $entry; @@ -80,7 +82,7 @@ class JavascriptController extends Controller /** * Get info about currencies. * - * @param CurrencyRepositoryInterface $repository + * @param CurrencyRepositoryInterface $repository * * @return Response */ @@ -103,19 +105,19 @@ class JavascriptController extends Controller /** * Show some common variables to be used in scripts. * - * @param Request $request - * @param AccountRepositoryInterface $repository - * @param CurrencyRepositoryInterface $currencyRepository + * @param Request $request + * @param AccountRepositoryInterface $repository + * @param CurrencyRepositoryInterface $currencyRepository * * @return Response * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function variables(Request $request, AccountRepositoryInterface $repository, CurrencyRepositoryInterface $currencyRepository): Response { - $account = $repository->find((int) $request->get('account')); + $account = $repository->find((int)$request->get('account')); $currency = app('amount')->getDefaultCurrency(); if (null !== $account) { $currency = $repository->getAccountCurrency($account) ?? $currency; @@ -124,10 +126,9 @@ class JavascriptController extends Controller $accounting = app('amount')->getJsConfig(); $accounting['frac_digits'] = $currency->decimal_places; $pref = app('preferences')->get('language', config('firefly.default_language', 'en_US')); - /** @noinspection NullPointerExceptionInspection */ - $lang = $pref->data; - $dateRange = $this->getDateRangeConfig(); - $uid = substr(hash('sha256', sprintf('%s-%s-%s', (string) config('app.key'), auth()->user()->id, auth()->user()->email)), 0, 12); + $lang = $pref->data; + $dateRange = $this->getDateRangeConfig(); + $uid = substr(hash('sha256', sprintf('%s-%s-%s', (string)config('app.key'), auth()->user()->id, auth()->user()->email)), 0, 12); $data = [ 'currencyCode' => $currency->code, @@ -149,7 +150,7 @@ class JavascriptController extends Controller /** * Bit of a hack but OK. * - * @param Request $request + * @param Request $request * * @return Response */ @@ -169,5 +170,4 @@ class JavascriptController extends Controller ->view('v2.javascript.variables', $data) ->header('Content-Type', 'text/javascript'); } - } diff --git a/app/Http/Controllers/Json/AutoCompleteController.php b/app/Http/Controllers/Json/AutoCompleteController.php index 86bd5603b2..f77c76c8e2 100644 --- a/app/Http/Controllers/Json/AutoCompleteController.php +++ b/app/Http/Controllers/Json/AutoCompleteController.php @@ -1,4 +1,5 @@ endOfMonth()); $today = today(config('app.timezone')); $display = 2; // see method docs. - $boxTitle = (string) trans('firefly.spent'); + $boxTitle = (string)trans('firefly.spent'); - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($today); @@ -92,21 +92,21 @@ class BoxController extends Controller // spent in this period, in budgets, for default currency. // also calculate spent per day. $spent = $opsRepository->sumExpenses($start, $end, null, null, $currency); - $spentAmount = $spent[(int) $currency->id]['sum'] ?? '0'; + $spentAmount = $spent[(int)$currency->id]['sum'] ?? '0'; $days = $today->between($start, $end) ? $today->diffInDays($start) + 1 : $end->diffInDays($start) + 1; - $spentPerDay = bcdiv($spentAmount, (string) $days); + $spentPerDay = bcdiv($spentAmount, (string)$days); if ($availableBudgets->count() > 0) { $display = 0; // assume user overspent - $boxTitle = (string) trans('firefly.overspent'); - $totalAvailableSum = (string) $availableBudgets->sum('amount'); + $boxTitle = (string)trans('firefly.overspent'); + $totalAvailableSum = (string)$availableBudgets->sum('amount'); // calculate with available budget. $leftToSpendAmount = bcadd($totalAvailableSum, $spentAmount); if (1 === bccomp($leftToSpendAmount, '0')) { - $boxTitle = (string) trans('firefly.left_to_spend'); + $boxTitle = (string)trans('firefly.left_to_spend'); $days = $today->diffInDays($end) + 1; $display = 1; // not overspent - $leftPerDayAmount = bcdiv($leftToSpendAmount, (string) $days); + $leftPerDayAmount = bcdiv($leftToSpendAmount, (string)$days); } } @@ -127,7 +127,7 @@ class BoxController extends Controller /** * Current total balance. * - * @param CurrencyRepositoryInterface $repository + * @param CurrencyRepositoryInterface $repository * * @return JsonResponse */ @@ -138,7 +138,7 @@ class BoxController extends Controller $start = session('start', Carbon::now()->startOfMonth()); /** @var Carbon $end */ $end = session('end', Carbon::now()->endOfMonth()); - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('box-balance'); @@ -159,7 +159,7 @@ class BoxController extends Controller $set = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($set as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $amount = $journal['amount'] ?? '0'; $incomes[$currencyId] = $incomes[$currencyId] ?? '0'; $incomes[$currencyId] = bcadd($incomes[$currencyId], app('steam')->positive($amount)); @@ -175,7 +175,7 @@ class BoxController extends Controller $set = $collector->getExtractedJournals(); /** @var array $journal */ foreach ($set as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $expenses[$currencyId] = $expenses[$currencyId] ?? '0'; $expenses[$currencyId] = bcadd($expenses[$currencyId], $journal['amount'] ?? '0'); $sums[$currencyId] = $sums[$currencyId] ?? '0'; @@ -190,7 +190,7 @@ class BoxController extends Controller $incomes[$currencyId] = app('amount')->formatAnything($currency, $incomes[$currencyId] ?? '0', false); $expenses[$currencyId] = app('amount')->formatAnything($currency, $expenses[$currencyId] ?? '0', false); } - if (empty($sums)) { + if (0 === count($sums)) { $currency = app('amount')->getDefaultCurrency(); $sums[$currency->id] = app('amount')->formatAnything($currency, '0', false); $incomes[$currency->id] = app('amount')->formatAnything($currency, '0', false); @@ -231,7 +231,7 @@ class BoxController extends Controller /** @var AccountRepositoryInterface $accountRepository */ $accountRepository = app(AccountRepositoryInterface::class); $allAccounts = $accountRepository->getActiveAccountsByType( - [AccountType::DEFAULT, AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD] + [AccountType::DEFAULT, AccountType::ASSET] ); Log::debug(sprintf('Found %d accounts.', $allAccounts->count())); @@ -261,5 +261,4 @@ class BoxController extends Controller return response()->json($return); } - } diff --git a/app/Http/Controllers/Json/BudgetController.php b/app/Http/Controllers/Json/BudgetController.php index af1ff647a1..2b1475b1ec 100644 --- a/app/Http/Controllers/Json/BudgetController.php +++ b/app/Http/Controllers/Json/BudgetController.php @@ -30,8 +30,6 @@ use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Budget\AvailableBudgetRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetLimitRepositoryInterface; use FireflyIII\Repositories\Budget\BudgetRepositoryInterface; -use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; -use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Support\Http\Controllers\DateCalculation; use Illuminate\Http\JsonResponse; @@ -42,16 +40,9 @@ class BudgetController extends Controller { use DateCalculation; - /** @var AvailableBudgetRepositoryInterface */ - private $abRepository; - /** @var BudgetLimitRepositoryInterface */ - private $blRepository; - /** @var CurrencyRepositoryInterface */ - private $currencyRepository; - /** @var OperationsRepositoryInterface */ - private $opsRepository; - /** @var BudgetRepositoryInterface The budget repository */ - private $repository; + private AvailableBudgetRepositoryInterface $abRepository; + private BudgetLimitRepositoryInterface $blRepository; + private BudgetRepositoryInterface $repository; /** * IndexController constructor. @@ -64,13 +55,11 @@ class BudgetController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.budgets')); + app('view')->share('title', (string)trans('firefly.budgets')); app('view')->share('mainTitleIcon', 'fa-pie-chart'); - $this->repository = app(BudgetRepositoryInterface::class); - $this->opsRepository = app(OperationsRepositoryInterface::class); - $this->abRepository = app(AvailableBudgetRepositoryInterface::class); - $this->currencyRepository = app(CurrencyRepositoryInterface::class); - $this->blRepository = app(BudgetLimitRepositoryInterface::class); + $this->repository = app(BudgetRepositoryInterface::class); + $this->abRepository = app(AvailableBudgetRepositoryInterface::class); + $this->blRepository = app(BudgetLimitRepositoryInterface::class); $this->repository->cleanupBudgets(); return $next($request); @@ -79,9 +68,9 @@ class BudgetController extends Controller } /** - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end * * @return JsonResponse */ @@ -102,8 +91,8 @@ class BudgetController extends Controller [ 'budgeted' => $budgeted, 'budgeted_formatted' => app('amount')->formatAnything($currency, $budgeted, true), - 'available' => app('amount')->formatAnything($currency, $available, true), - 'available_formatted' => $available, + 'available' => $available, + 'available_formatted' => app('amount')->formatAnything($currency, $available, true), 'percentage' => $percentage, 'currency_id' => $currency->id, 'currency_code' => $currency->code, @@ -113,5 +102,4 @@ class BudgetController extends Controller ] ); } - } diff --git a/app/Http/Controllers/Json/FrontpageController.php b/app/Http/Controllers/Json/FrontpageController.php index 67fcdab3a7..407b524cba 100644 --- a/app/Http/Controllers/Json/FrontpageController.php +++ b/app/Http/Controllers/Json/FrontpageController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Json; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\PiggyBank; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; @@ -53,7 +54,7 @@ class FrontpageController extends Controller // percentage! $pct = 0; if (0 !== bccomp($piggyBank->targetamount, '0')) { - $pct = round(($amount / $piggyBank->targetamount) * 100); + $pct = (int)bcmul(bcdiv($amount, $piggyBank->targetamount), '100'); } $entry = [ @@ -68,12 +69,13 @@ class FrontpageController extends Controller } } $html = ''; - if (!empty($info)) { + if (0 !== count($info)) { try { $html = view('json.piggy-banks', compact('info'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render json.piggy-banks: %s', $e->getMessage())); $html = 'Could not render view.'; + throw new FireflyException($html, 0, $e); } } diff --git a/app/Http/Controllers/Json/IntroController.php b/app/Http/Controllers/Json/IntroController.php index 1c6c796bc5..500c0291c9 100644 --- a/app/Http/Controllers/Json/IntroController.php +++ b/app/Http/Controllers/Json/IntroController.php @@ -1,4 +1,5 @@ getBasicSteps($route); $specificSteps = $this->getSpecificSteps($route, $specificPage); - if (empty($specificSteps)) { + if (0 === count($specificSteps)) { Log::debug(sprintf('No specific steps for route "%s" and page "%s"', $route, $specificPage)); return response()->json($steps); } if ($this->hasOutroStep($route)) { - // save last step: $lastStep = $steps[count($steps) - 1]; // remove last step: @@ -63,7 +63,6 @@ class IntroController extends Controller // merge arrays and add last step again $steps = array_merge($steps, $specificSteps); $steps[] = $lastStep; - } if (!$this->hasOutroStep($route)) { $steps = array_merge($steps, $specificSteps); @@ -75,7 +74,7 @@ class IntroController extends Controller /** * Returns true if there is a general outro step. * - * @param string $route + * @param string $route * * @return bool */ @@ -100,8 +99,8 @@ class IntroController extends Controller /** * Enable the boxes for a specific page again. * - * @param string $route - * @param string|null $specialPage + * @param string $route + * @param string|null $specialPage * * @return JsonResponse * @throws FireflyException @@ -110,22 +109,22 @@ class IntroController extends Controller { $specialPage = $specialPage ?? ''; $route = str_replace('.', '_', $route); - $key = 'shown_demo_' . $route; + $key = 'shown_demo_'.$route; if ('' !== $specialPage) { - $key .= '_' . $specialPage; + $key .= '_'.$specialPage; } Log::debug(sprintf('Going to mark the following route as NOT done: %s with special "%s" (%s)', $route, $specialPage, $key)); app('preferences')->set($key, false); app('preferences')->mark(); - return response()->json(['message' => (string) trans('firefly.intro_boxes_after_refresh')]); + return response()->json(['message' => (string)trans('firefly.intro_boxes_after_refresh')]); } /** * Set that you saw them. * - * @param string $route - * @param string|null $specialPage + * @param string $route + * @param string|null $specialPage * * @return JsonResponse * @throws FireflyException @@ -133,14 +132,13 @@ class IntroController extends Controller public function postFinished(string $route, string $specialPage = null): JsonResponse { $specialPage = $specialPage ?? ''; - $key = 'shown_demo_' . $route; + $key = 'shown_demo_'.$route; if ('' !== $specialPage) { - $key .= '_' . $specialPage; + $key .= '_'.$specialPage; } Log::debug(sprintf('Going to mark the following route as done: %s with special "%s" (%s)', $route, $specialPage, $key)); app('preferences')->set($key, true); return response()->json(['result' => sprintf('Reported demo watched for route "%s" (%s): %s.', $route, $specialPage, $key)]); } - } diff --git a/app/Http/Controllers/Json/ReconcileController.php b/app/Http/Controllers/Json/ReconcileController.php index ba680a7801..562c569474 100644 --- a/app/Http/Controllers/Json/ReconcileController.php +++ b/app/Http/Controllers/Json/ReconcileController.php @@ -47,8 +47,6 @@ use Throwable; class ReconcileController extends Controller { private AccountRepositoryInterface $accountRepos; - private CurrencyRepositoryInterface $currencyRepos; - private JournalRepositoryInterface $repository; /** * ReconcileController constructor. @@ -63,10 +61,8 @@ class ReconcileController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-credit-card'); - app('view')->share('title', (string) trans('firefly.accounts')); - $this->repository = app(JournalRepositoryInterface::class); + app('view')->share('title', (string)trans('firefly.accounts')); $this->accountRepos = app(AccountRepositoryInterface::class); - $this->currencyRepos = app(CurrencyRepositoryInterface::class); return $next($request); } @@ -76,10 +72,10 @@ class ReconcileController extends Controller /** * Overview of reconciliation. * - * @param Request $request - * @param Account|null $account - * @param Carbon|null $start - * @param Carbon|null $end + * @param Request $request + * @param Account|null $account + * @param Carbon|null $start + * @param Carbon|null $end * * @return JsonResponse * @throws FireflyException @@ -161,10 +157,10 @@ class ReconcileController extends Controller 'selectedIds' ) )->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('View error: %s', $e->getMessage())); $view = sprintf('Could not render accounts.reconcile.overview: %s', $e->getMessage()); + throw new FireflyException($view, 0, $e); } $return = [ @@ -176,10 +172,10 @@ class ReconcileController extends Controller } /** - * @param Account $account - * @param TransactionCurrency $currency - * @param array $journal - * @param string $amount + * @param Account $account + * @param TransactionCurrency $currency + * @param array $journal + * @param string $amount * * @return string */ @@ -218,9 +214,9 @@ class ReconcileController extends Controller /** * Returns a list of transactions in a modal. * - * @param Account $account - * @param Carbon|null $start - * @param Carbon|null $end + * @param Account $account + * @param Carbon|null $start + * @param Carbon|null $end * * @return JsonResponse * @throws FireflyException @@ -262,10 +258,10 @@ class ReconcileController extends Controller 'accounts.reconcile.transactions', compact('account', 'journals', 'currency', 'start', 'end', 'selectionStart', 'selectionEnd') )->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render: %s', $e->getMessage())); $html = sprintf('Could not render accounts.reconcile.transactions: %s', $e->getMessage()); + throw new FireflyException($html, 0, $e); } return response()->json(['html' => $html, 'startBalance' => $startBalance, 'endBalance' => $endBalance]); @@ -274,8 +270,8 @@ class ReconcileController extends Controller /** * "fix" amounts to make it easier on the reconciliation overview: * - * @param Account $account - * @param array $array + * @param Account $account + * @param array $array * * @return array */ diff --git a/app/Http/Controllers/Json/RecurrenceController.php b/app/Http/Controllers/Json/RecurrenceController.php index 01b5e56212..7eafb0069b 100644 --- a/app/Http/Controllers/Json/RecurrenceController.php +++ b/app/Http/Controllers/Json/RecurrenceController.php @@ -31,6 +31,8 @@ use FireflyIII\Repositories\Recurring\RecurringRepositoryInterface; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class RecurrenceController @@ -61,7 +63,7 @@ class RecurrenceController extends Controller /** * Shows all events for a repetition. Used in calendar. * - * @param Request $request + * @param Request $request * * @return JsonResponse * @@ -69,14 +71,15 @@ class RecurrenceController extends Controller */ public function events(Request $request): JsonResponse { + $occurrences = []; $return = []; $start = Carbon::createFromFormat('Y-m-d', $request->get('start')); $end = Carbon::createFromFormat('Y-m-d', $request->get('end')); $firstDate = Carbon::createFromFormat('Y-m-d', $request->get('first_date')); - $endDate = '' !== (string) $request->get('end_date') ? Carbon::createFromFormat('Y-m-d', $request->get('end_date')) : null; - $endsAt = (string) $request->get('ends'); + $endDate = '' !== (string)$request->get('end_date') ? Carbon::createFromFormat('Y-m-d', $request->get('end_date')) : null; + $endsAt = (string)$request->get('ends'); $repetitionType = explode(',', $request->get('type'))[0]; - $repetitions = (int) $request->get('reps'); + $repetitions = (int)$request->get('reps'); $repetitionMoment = ''; $start->startOfDay(); @@ -97,32 +100,30 @@ class RecurrenceController extends Controller $repetitionMoment = explode(',', $request->get('type'))[1] ?? '2018-01-01'; } $actualStart->startOfDay(); - $repetition = new RecurrenceRepetition; + $repetition = new RecurrenceRepetition(); $repetition->repetition_type = $repetitionType; $repetition->repetition_moment = $repetitionMoment; - $repetition->repetition_skip = (int) $request->get('skip'); - $repetition->weekend = (int) $request->get('weekend'); + $repetition->repetition_skip = (int)$request->get('skip'); + $repetition->weekend = (int)$request->get('weekend'); $actualEnd = clone $end; - switch ($endsAt) { - default: - case 'forever': - // simply generate up until $end. No change from default behavior. - $occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd); - break; - case 'until_date': - $actualEnd = $endDate ?? clone $end; - $occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd); - break; - case 'times': - $occurrences = $this->recurring->getXOccurrences($repetition, $actualStart, $repetitions); - break; + if ('until_date' === $endsAt) { + $actualEnd = $endDate ?? clone $end; + $occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd); } + if ('times' === $endsAt) { + $occurrences = $this->recurring->getXOccurrences($repetition, $actualStart, $repetitions); + } + if ('times' !== $endsAt && 'until_date' !== $endsAt) { + // 'forever' + $occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd); + } + /** @var Carbon $current */ foreach ($occurrences as $current) { if ($current->gte($start)) { $event = [ - 'id' => $repetitionType . $firstDate->format('Ymd'), + 'id' => $repetitionType.$firstDate->format('Ymd'), 'title' => 'X', 'allDay' => true, 'start' => $current->format('Y-m-d'), @@ -140,43 +141,51 @@ class RecurrenceController extends Controller /** * Suggests repetition moments. * - * @param Request $request + * @param Request $request * * @return JsonResponse * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function suggest(Request $request): JsonResponse { $string = $request->get('date') ?? date('Y-m-d'); $today = Carbon::now()->startOfDay(); $date = Carbon::createFromFormat('Y-m-d', $string)->startOfDay(); - $preSelected = (string) $request->get('pre_select'); + $preSelected = (string)$request->get('pre_select'); $locale = app('steam')->getLocale(); Log::debug(sprintf('date = %s, today = %s. date > today? %s', $date->toAtomString(), $today->toAtomString(), var_export($date > $today, true))); - Log::debug(sprintf('past = true? %s', var_export('true' === (string) $request->get('past'), true))); + Log::debug(sprintf('past = true? %s', var_export('true' === (string)$request->get('past'), true))); $result = []; - if ($date > $today || 'true' === (string) $request->get('past')) { + if ($date > $today || 'true' === (string)$request->get('past')) { Log::debug('Will fill dropdown.'); $weekly = sprintf('weekly,%s', $date->dayOfWeekIso); $monthly = sprintf('monthly,%s', $date->day); - $dayOfWeek = (string) trans(sprintf('config.dow_%s', $date->dayOfWeekIso)); + $dayOfWeek = (string)trans(sprintf('config.dow_%s', $date->dayOfWeekIso)); $ndom = sprintf('ndom,%s,%s', $date->weekOfMonth, $date->dayOfWeekIso); $yearly = sprintf('yearly,%s', $date->format('Y-m-d')); - $yearlyDate = $date->isoFormat((string) trans('config.month_and_day_no_year_js', [], $locale)); + $yearlyDate = $date->isoFormat((string)trans('config.month_and_day_no_year_js', [], $locale)); $result = [ - 'daily' => ['label' => (string) trans('firefly.recurring_daily'), 'selected' => str_starts_with($preSelected, 'daily')], - $weekly => ['label' => (string) trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]), - 'selected' => str_starts_with($preSelected, 'weekly')], - $monthly => ['label' => (string) trans('firefly.recurring_monthly', ['dayOfMonth' => $date->day]), - 'selected' => str_starts_with($preSelected, 'monthly')], - $ndom => ['label' => (string) trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $date->weekOfMonth]), - 'selected' => str_starts_with($preSelected, 'ndom')], - $yearly => ['label' => (string) trans('firefly.recurring_yearly', ['date' => $yearlyDate]), - 'selected' => str_starts_with($preSelected, 'yearly')], + 'daily' => ['label' => (string)trans('firefly.recurring_daily'), 'selected' => str_starts_with($preSelected, 'daily')], + $weekly => [ + 'label' => (string)trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek]), + 'selected' => str_starts_with($preSelected, 'weekly'), + ], + $monthly => [ + 'label' => (string)trans('firefly.recurring_monthly', ['dayOfMonth' => $date->day]), + 'selected' => str_starts_with($preSelected, 'monthly'), + ], + $ndom => [ + 'label' => (string)trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $date->weekOfMonth]), + 'selected' => str_starts_with($preSelected, 'ndom'), + ], + $yearly => [ + 'label' => (string)trans('firefly.recurring_yearly', ['date' => $yearlyDate]), + 'selected' => str_starts_with($preSelected, 'yearly'), + ], ]; } Log::debug('Dropdown is', $result); diff --git a/app/Http/Controllers/Json/RuleController.php b/app/Http/Controllers/Json/RuleController.php index 63d6f5487e..669edb381e 100644 --- a/app/Http/Controllers/Json/RuleController.php +++ b/app/Http/Controllers/Json/RuleController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Json; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; @@ -37,24 +38,24 @@ class RuleController extends Controller /** * Render HTML form for rule action. * - * @param Request $request + * @param Request $request * * @return JsonResponse */ public function action(Request $request): JsonResponse { - $count = (int) $request->get('count') > 0 ? (int) $request->get('count') : 1; + $count = (int)$request->get('count') > 0 ? (int)$request->get('count') : 1; $keys = array_keys(config('firefly.rule-actions')); $actions = []; foreach ($keys as $key) { - $actions[$key] = (string) trans('firefly.rule_action_' . $key . '_choice'); + $actions[$key] = (string)trans('firefly.rule_action_'.$key.'_choice'); } try { $view = view('rules.partials.action', compact('actions', 'count'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render rules.partials.action: %s', $e->getMessage())); $view = 'Could not render view.'; + throw new FireflyException($view, 0, $e); } return response()->json(['html' => $view]); @@ -63,31 +64,30 @@ class RuleController extends Controller /** * Render HTML for rule trigger. * - * @param Request $request + * @param Request $request * * @return JsonResponse */ public function trigger(Request $request): JsonResponse { - $count = (int) $request->get('count') > 0 ? (int) $request->get('count') : 1; + $count = (int)$request->get('count') > 0 ? (int)$request->get('count') : 1; $operators = config('search.operators'); $triggers = []; foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - - $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); try { $view = view('rules.partials.trigger', compact('triggers', 'count'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render rules.partials.trigger: %s', $e->getMessage())); $view = 'Could not render view.'; + throw new FireflyException($view, 0, $e); } return response()->json(['html' => $view]); } - } diff --git a/app/Http/Controllers/NewUserController.php b/app/Http/Controllers/NewUserController.php index e0c3ab04e7..cfae0db8c8 100644 --- a/app/Http/Controllers/NewUserController.php +++ b/app/Http/Controllers/NewUserController.php @@ -1,4 +1,5 @@ share('title', (string) trans('firefly.welcome')); + app('view')->share('title', (string)trans('firefly.welcome')); app('view')->share('mainTitleIcon', 'fa-fire'); $types = config('firefly.accountTypesByIdentifier.asset'); @@ -84,8 +85,8 @@ class NewUserController extends Controller /** * Store his new settings. * - * @param NewUserFormRequest $request - * @param CurrencyRepositoryInterface $currencyRepository + * @param NewUserFormRequest $request + * @param CurrencyRepositoryInterface $currencyRepository * * @return RedirectResponse|Redirector * @throws FireflyException @@ -95,13 +96,12 @@ class NewUserController extends Controller $language = $request->convertString('language'); if (!array_key_exists($language, config('firefly.languages'))) { $language = 'en_US'; - } // set language preference: app('preferences')->set('language', $language); // Store currency preference from input: - $currency = $currencyRepository->find((int) $request->input('amount_currency_id_bank_balance')); + $currency = $currencyRepository->find((int)$request->input('amount_currency_id_bank_balance')); // if is null, set to EUR: if (null === $currency) { @@ -124,14 +124,22 @@ class NewUserController extends Controller app('preferences')->mark(); // set default optional fields: - $visibleFields = ['interest_date' => true, 'book_date' => false, 'process_date' => false, 'due_date' => false, 'payment_date' => false, - 'invoice_date' => false, 'internal_reference' => false, 'notes' => true, 'attachments' => true,]; + $visibleFields = [ + 'interest_date' => true, + 'book_date' => false, + 'process_date' => false, + 'due_date' => false, + 'payment_date' => false, + 'invoice_date' => false, + 'internal_reference' => false, + 'notes' => true, + 'attachments' => true, + ]; app('preferences')->set('transaction_journal_optional_fields', $visibleFields); - session()->flash('success', (string) trans('firefly.stored_new_accounts_new_user')); + session()->flash('success', (string)trans('firefly.stored_new_accounts_new_user')); app('preferences')->mark(); return redirect(route('index')); } - } diff --git a/app/Http/Controllers/ObjectGroup/DeleteController.php b/app/Http/Controllers/ObjectGroup/DeleteController.php index 00b6f521b3..b53c5fa710 100644 --- a/app/Http/Controllers/ObjectGroup/DeleteController.php +++ b/app/Http/Controllers/ObjectGroup/DeleteController.php @@ -50,7 +50,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-envelope-o'); - app('view')->share('title', (string) trans('firefly.object_groups_page_title')); + app('view')->share('title', (string)trans('firefly.object_groups_page_title')); $this->repository = app(ObjectGroupRepositoryInterface::class); @@ -62,13 +62,13 @@ class DeleteController extends Controller /** * Delete a piggy bank. * - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return Factory|View */ public function delete(ObjectGroup $objectGroup) { - $subTitle = (string) trans('firefly.delete_object_group', ['title' => $objectGroup->title]); + $subTitle = (string)trans('firefly.delete_object_group', ['title' => $objectGroup->title]); $piggyBanks = $objectGroup->piggyBanks()->count(); // put previous url in session @@ -80,17 +80,16 @@ class DeleteController extends Controller /** * Destroy the piggy bank. * - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return RedirectResponse */ public function destroy(ObjectGroup $objectGroup): RedirectResponse { - session()->flash('success', (string) trans('firefly.deleted_object_group', ['title' => $objectGroup->title])); + session()->flash('success', (string)trans('firefly.deleted_object_group', ['title' => $objectGroup->title])); app('preferences')->mark(); $this->repository->destroy($objectGroup); return redirect($this->getPreviousUrl('object-groups.delete.url')); } - } diff --git a/app/Http/Controllers/ObjectGroup/EditController.php b/app/Http/Controllers/ObjectGroup/EditController.php index 7771052f50..cdb35c0b81 100644 --- a/app/Http/Controllers/ObjectGroup/EditController.php +++ b/app/Http/Controllers/ObjectGroup/EditController.php @@ -53,7 +53,7 @@ class EditController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-envelope-o'); - app('view')->share('title', (string) trans('firefly.object_groups_page_title')); + app('view')->share('title', (string)trans('firefly.object_groups_page_title')); $this->repository = app(ObjectGroupRepositoryInterface::class); @@ -65,13 +65,13 @@ class EditController extends Controller /** * Edit an object group. * - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return Factory|View */ public function edit(ObjectGroup $objectGroup) { - $subTitle = (string) trans('firefly.edit_object_group', ['title' => $objectGroup->title]); + $subTitle = (string)trans('firefly.edit_object_group', ['title' => $objectGroup->title]); $subTitleIcon = 'fa-pencil'; if (true !== session('object-groups.edit.fromUpdate')) { @@ -85,8 +85,8 @@ class EditController extends Controller /** * Update a piggy bank. * - * @param ObjectGroupFormRequest $request - * @param ObjectGroup $objectGroup + * @param ObjectGroupFormRequest $request + * @param ObjectGroup $objectGroup * * @return Application|RedirectResponse|Redirector */ @@ -95,17 +95,15 @@ class EditController extends Controller $data = $request->getObjectGroupData(); $piggyBank = $this->repository->update($objectGroup, $data); - session()->flash('success', (string) trans('firefly.updated_object_group', ['title' => $objectGroup->title])); + session()->flash('success', (string)trans('firefly.updated_object_group', ['title' => $objectGroup->title])); app('preferences')->mark(); $redirect = redirect($this->getPreviousUrl('object-groups.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { session()->put('object-groups.edit.fromUpdate', true); $redirect = redirect(route('object-groups.edit', [$piggyBank->id])); - } return $redirect; diff --git a/app/Http/Controllers/ObjectGroup/IndexController.php b/app/Http/Controllers/ObjectGroup/IndexController.php index 918535cd13..5a5c0fc59e 100644 --- a/app/Http/Controllers/ObjectGroup/IndexController.php +++ b/app/Http/Controllers/ObjectGroup/IndexController.php @@ -53,7 +53,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-envelope-o'); - app('view')->share('title', (string) trans('firefly.object_groups_page_title')); + app('view')->share('title', (string)trans('firefly.object_groups_page_title')); $this->repository = app(ObjectGroupRepositoryInterface::class); return $next($request); @@ -68,25 +68,24 @@ class IndexController extends Controller { $this->repository->deleteEmpty(); $this->repository->resetOrder(); - $subTitle = (string) trans('firefly.object_groups_index'); + $subTitle = (string)trans('firefly.object_groups_index'); $objectGroups = $this->repository->get(); return view('object-groups.index', compact('subTitle', 'objectGroups')); } /** - * @param Request $request - * @param ObjectGroup $objectGroup + * @param Request $request + * @param ObjectGroup $objectGroup * * @return JsonResponse */ public function setOrder(Request $request, ObjectGroup $objectGroup) { Log::debug(sprintf('Found object group #%d "%s"', $objectGroup->id, $objectGroup->title)); - $newOrder = (int) $request->get('order'); + $newOrder = (int)$request->get('order'); $this->repository->setOrder($objectGroup, $newOrder); return response()->json([]); } - } diff --git a/app/Http/Controllers/PiggyBank/AmountController.php b/app/Http/Controllers/PiggyBank/AmountController.php index 8b5292c100..b7e4d3af04 100644 --- a/app/Http/Controllers/PiggyBank/AmountController.php +++ b/app/Http/Controllers/PiggyBank/AmountController.php @@ -40,7 +40,6 @@ use Log; */ class AmountController extends Controller { - private AccountRepositoryInterface $accountRepos; private PiggyBankRepositoryInterface $piggyRepos; @@ -55,7 +54,7 @@ class AmountController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.piggyBanks')); + app('view')->share('title', (string)trans('firefly.piggyBanks')); app('view')->share('mainTitleIcon', 'fa-bullseye'); $this->piggyRepos = app(PiggyBankRepositoryInterface::class); @@ -69,7 +68,7 @@ class AmountController extends Controller /** * Add money to piggy bank. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return Factory|View */ @@ -78,7 +77,7 @@ class AmountController extends Controller $leftOnAccount = $this->piggyRepos->leftOnAccount($piggyBank, today(config('app.timezone'))); $savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank); $maxAmount = $leftOnAccount; - if (0 !== bccomp($piggyBank->targetamount,'0')) { + if (0 !== bccomp($piggyBank->targetamount, '0')) { $leftToSave = bcsub($piggyBank->targetamount, $savedSoFar); $maxAmount = min($leftOnAccount, $leftToSave); } @@ -90,7 +89,7 @@ class AmountController extends Controller /** * Add money to piggy bank (for mobile devices). * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return Factory|View */ @@ -102,7 +101,7 @@ class AmountController extends Controller $savedSoFar = $this->piggyRepos->getCurrentAmount($piggyBank); $maxAmount = $leftOnAccount; - if (0 !== bccomp($piggyBank->targetamount,'0')) { + if (0 !== bccomp($piggyBank->targetamount, '0')) { $leftToSave = bcsub($piggyBank->targetamount, $savedSoFar); $maxAmount = min($leftOnAccount, $leftToSave); } @@ -114,8 +113,8 @@ class AmountController extends Controller /** * Add money to piggy bank. * - * @param Request $request - * @param PiggyBank $piggyBank + * @param Request $request + * @param PiggyBank $piggyBank * * @return RedirectResponse */ @@ -131,7 +130,7 @@ class AmountController extends Controller $this->piggyRepos->addAmount($piggyBank, $amount); session()->flash( 'success', - (string) trans( + (string)trans( 'firefly.added_amount_to_piggy', ['amount' => app('amount')->formatAnything($currency, $amount, false), 'name' => $piggyBank->name] ) @@ -141,10 +140,10 @@ class AmountController extends Controller return redirect(route('piggy-banks.index')); } - Log::error('Cannot add ' . $amount . ' because canAddAmount returned false.'); + Log::error('Cannot add '.$amount.' because canAddAmount returned false.'); session()->flash( 'error', - (string) trans( + (string)trans( 'firefly.cannot_add_amount_piggy', ['amount' => app('amount')->formatAnything($currency, $amount, false), 'name' => e($piggyBank->name)] ) @@ -156,8 +155,8 @@ class AmountController extends Controller /** * Remove money from piggy bank. * - * @param Request $request - * @param PiggyBank $piggyBank + * @param Request $request + * @param PiggyBank $piggyBank * * @return RedirectResponse */ @@ -173,7 +172,7 @@ class AmountController extends Controller $this->piggyRepos->removeAmount($piggyBank, $amount); session()->flash( 'success', - (string) trans( + (string)trans( 'firefly.removed_amount_from_piggy', ['amount' => app('amount')->formatAnything($currency, $amount, false), 'name' => $piggyBank->name] ) @@ -182,11 +181,11 @@ class AmountController extends Controller return redirect(route('piggy-banks.index')); } - $amount = (string) $request->get('amount'); + $amount = (string)$request->get('amount'); session()->flash( 'error', - (string) trans( + (string)trans( 'firefly.cannot_remove_from_piggy', ['amount' => app('amount')->formatAnything($currency, $amount, false), 'name' => e($piggyBank->name)] ) @@ -198,7 +197,7 @@ class AmountController extends Controller /** * Remove money from piggy bank form. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return Factory|View */ @@ -213,7 +212,7 @@ class AmountController extends Controller /** * Remove money from piggy bank (for mobile devices). * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return Factory|View */ diff --git a/app/Http/Controllers/PiggyBank/CreateController.php b/app/Http/Controllers/PiggyBank/CreateController.php index 80a59610c7..9347bda81b 100644 --- a/app/Http/Controllers/PiggyBank/CreateController.php +++ b/app/Http/Controllers/PiggyBank/CreateController.php @@ -53,7 +53,7 @@ class CreateController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.piggyBanks')); + app('view')->share('title', (string)trans('firefly.piggyBanks')); app('view')->share('mainTitleIcon', 'fa-bullseye'); $this->attachments = app(AttachmentHelperInterface::class); @@ -71,7 +71,7 @@ class CreateController extends Controller */ public function create() { - $subTitle = (string) trans('firefly.new_piggy_bank'); + $subTitle = (string)trans('firefly.new_piggy_bank'); $subTitleIcon = 'fa-plus'; // put previous url in session if not redirect from store (not "create another"). @@ -86,7 +86,7 @@ class CreateController extends Controller /** * Store a new piggy bank. * - * @param PiggyBankStoreRequest $request + * @param PiggyBankStoreRequest $request * * @return RedirectResponse|Redirector * @throws FireflyException @@ -99,7 +99,7 @@ class CreateController extends Controller } $piggyBank = $this->piggyRepos->store($data); - session()->flash('success', (string) trans('firefly.stored_piggy_bank', ['name' => $piggyBank->name])); + session()->flash('success', (string)trans('firefly.stored_piggy_bank', ['name' => $piggyBank->name])); app('preferences')->mark(); // store attachment(s): @@ -109,7 +109,7 @@ class CreateController extends Controller $this->attachments->saveAttachmentsForModel($piggyBank, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { @@ -117,12 +117,10 @@ class CreateController extends Controller } $redirect = redirect($this->getPreviousUrl('piggy-banks.create.url')); - if (1 === (int) $request->get('create_another')) { - + if (1 === (int)$request->get('create_another')) { session()->put('piggy-banks.create.fromStore', true); $redirect = redirect(route('piggy-banks.create'))->withInput(); - } return $redirect; diff --git a/app/Http/Controllers/PiggyBank/DeleteController.php b/app/Http/Controllers/PiggyBank/DeleteController.php index b4f374e7c5..1c019b2839 100644 --- a/app/Http/Controllers/PiggyBank/DeleteController.php +++ b/app/Http/Controllers/PiggyBank/DeleteController.php @@ -36,7 +36,6 @@ use Illuminate\View\View; */ class DeleteController extends Controller { - private PiggyBankRepositoryInterface $piggyRepos; /** @@ -50,7 +49,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.piggyBanks')); + app('view')->share('title', (string)trans('firefly.piggyBanks')); app('view')->share('mainTitleIcon', 'fa-bullseye'); $this->piggyRepos = app(PiggyBankRepositoryInterface::class); @@ -63,13 +62,13 @@ class DeleteController extends Controller /** * Delete a piggy bank. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return Factory|View */ public function delete(PiggyBank $piggyBank) { - $subTitle = (string) trans('firefly.delete_piggy_bank', ['name' => $piggyBank->name]); + $subTitle = (string)trans('firefly.delete_piggy_bank', ['name' => $piggyBank->name]); // put previous url in session $this->rememberPreviousUrl('piggy-banks.delete.url'); @@ -80,13 +79,13 @@ class DeleteController extends Controller /** * Destroy the piggy bank. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return RedirectResponse */ public function destroy(PiggyBank $piggyBank): RedirectResponse { - session()->flash('success', (string) trans('firefly.deleted_piggy_bank', ['name' => $piggyBank->name])); + session()->flash('success', (string)trans('firefly.deleted_piggy_bank', ['name' => $piggyBank->name])); app('preferences')->mark(); $this->piggyRepos->destroy($piggyBank); diff --git a/app/Http/Controllers/PiggyBank/EditController.php b/app/Http/Controllers/PiggyBank/EditController.php index 3857b2b491..a789f6c8c3 100644 --- a/app/Http/Controllers/PiggyBank/EditController.php +++ b/app/Http/Controllers/PiggyBank/EditController.php @@ -149,5 +149,4 @@ class EditController extends Controller return $redirect; } - } diff --git a/app/Http/Controllers/PiggyBank/IndexController.php b/app/Http/Controllers/PiggyBank/IndexController.php index b512b16f3f..4a7d4f49af 100644 --- a/app/Http/Controllers/PiggyBank/IndexController.php +++ b/app/Http/Controllers/PiggyBank/IndexController.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\PiggyBank; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\PiggyBank; use FireflyIII\Repositories\ObjectGroup\OrganisesObjectGroups; @@ -35,6 +36,7 @@ use Illuminate\Contracts\View\Factory; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; use Illuminate\View\View; +use JsonException; use Symfony\Component\HttpFoundation\ParameterBag; /** @@ -57,7 +59,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.piggyBanks')); + app('view')->share('title', (string)trans('firefly.piggyBanks')); app('view')->share('mainTitleIcon', 'fa-bullseye'); $this->piggyRepos = app(PiggyBankRepositoryInterface::class); @@ -69,13 +71,14 @@ class IndexController extends Controller /** * Show overview of all piggy banks. - * See reference nr. 66 * - * @param Request $request + * TODO very complicated function. + * + * @param Request $request * * @return Factory|View - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException + * @throws FireflyException + * @throws JsonException */ public function index(Request $request) { @@ -87,7 +90,7 @@ class IndexController extends Controller $end = session('end', Carbon::now()->endOfMonth()); // transform piggies using the transformer: - $parameters = new ParameterBag; + $parameters = new ParameterBag(); $parameters->set('end', $end); // make piggy bank groups: @@ -95,7 +98,7 @@ class IndexController extends Controller /** @var PiggyBankTransformer $transformer */ $transformer = app(PiggyBankTransformer::class); - $transformer->setParameters(new ParameterBag); + $transformer->setParameters(new ParameterBag()); /** @var AccountTransformer $accountTransformer */ $accountTransformer = app(AccountTransformer::class); @@ -103,16 +106,16 @@ class IndexController extends Controller /** @var PiggyBank $piggy */ foreach ($collection as $piggy) { $array = $transformer->transform($piggy); - $groupOrder = (int) $array['object_group_order']; + $groupOrder = (int)$array['object_group_order']; // make group array if necessary: $piggyBanks[$groupOrder] = $piggyBanks[$groupOrder] ?? [ - 'object_group_id' => $array['object_group_id'] ?? 0, - 'object_group_title' => $array['object_group_title'] ?? trans('firefly.default_group_title_name'), - 'piggy_banks' => [], - ]; + 'object_group_id' => $array['object_group_id'] ?? 0, + 'object_group_title' => $array['object_group_title'] ?? trans('firefly.default_group_title_name'), + 'piggy_banks' => [], + ]; $account = $accountTransformer->transform($piggy->account); - $accountId = (int) $account['id']; + $accountId = (int)$account['id']; $array['attachments'] = $this->piggyRepos->getAttachments($piggy); if (!array_key_exists($accountId, $accounts)) { // create new: @@ -142,7 +145,7 @@ class IndexController extends Controller } /** - * @param array $piggyBanks + * @param array $piggyBanks * * @return array */ @@ -154,23 +157,23 @@ class IndexController extends Controller foreach ($group['piggy_banks'] as $piggy) { $currencyId = $piggy['currency_id']; $sums[$groupId][$currencyId] = $sums[$groupId][$currencyId] ?? [ - 'target' => '0', - 'saved' => '0', - 'left_to_save' => '0', - 'save_per_month' => '0', - 'currency_id' => $currencyId, - 'currency_code' => $piggy['currency_code'], - 'currency_symbol' => $piggy['currency_symbol'], - 'currency_decimal_places' => $piggy['currency_decimal_places'], - ]; + 'target' => '0', + 'saved' => '0', + 'left_to_save' => '0', + 'save_per_month' => '0', + 'currency_id' => $currencyId, + 'currency_code' => $piggy['currency_code'], + 'currency_symbol' => $piggy['currency_symbol'], + 'currency_decimal_places' => $piggy['currency_decimal_places'], + ]; // target_amount // current_amount // left_to_save // save_per_month - $sums[$groupId][$currencyId]['target'] = bcadd($sums[$groupId][$currencyId]['target'], (string) $piggy['target_amount']); - $sums[$groupId][$currencyId]['saved'] = bcadd($sums[$groupId][$currencyId]['saved'], (string) $piggy['current_amount']); - $sums[$groupId][$currencyId]['left_to_save'] = bcadd($sums[$groupId][$currencyId]['left_to_save'], (string) $piggy['left_to_save']); - $sums[$groupId][$currencyId]['save_per_month'] = bcadd($sums[$groupId][$currencyId]['save_per_month'], (string) $piggy['save_per_month']); + $sums[$groupId][$currencyId]['target'] = bcadd($sums[$groupId][$currencyId]['target'], (string)$piggy['target_amount']); + $sums[$groupId][$currencyId]['saved'] = bcadd($sums[$groupId][$currencyId]['saved'], (string)$piggy['current_amount']); + $sums[$groupId][$currencyId]['left_to_save'] = bcadd($sums[$groupId][$currencyId]['left_to_save'], (string)$piggy['left_to_save']); + $sums[$groupId][$currencyId]['save_per_month'] = bcadd($sums[$groupId][$currencyId]['save_per_month'], (string)$piggy['save_per_month']); } } foreach ($piggyBanks as $groupOrder => $group) { @@ -184,15 +187,15 @@ class IndexController extends Controller /** * Set the order of a piggy bank. * - * @param Request $request - * @param PiggyBank $piggyBank + * @param Request $request + * @param PiggyBank $piggyBank * * @return JsonResponse */ public function setOrder(Request $request, PiggyBank $piggyBank): JsonResponse { - $objectGroupTitle = (string) $request->get('objectGroupTitle'); - $newOrder = (int) $request->get('order'); + $objectGroupTitle = (string)$request->get('objectGroupTitle'); + $newOrder = (int)$request->get('order'); $this->piggyRepos->setOrder($piggyBank, $newOrder); if ('' !== $objectGroupTitle) { $this->piggyRepos->setObjectGroup($piggyBank, $objectGroupTitle); diff --git a/app/Http/Controllers/PiggyBank/ShowController.php b/app/Http/Controllers/PiggyBank/ShowController.php index 6aba89dfdd..93905891c9 100644 --- a/app/Http/Controllers/PiggyBank/ShowController.php +++ b/app/Http/Controllers/PiggyBank/ShowController.php @@ -51,7 +51,7 @@ class ShowController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.piggyBanks')); + app('view')->share('title', (string)trans('firefly.piggyBanks')); app('view')->share('mainTitleIcon', 'fa-bullseye'); $this->piggyRepos = app(PiggyBankRepositoryInterface::class); @@ -64,7 +64,7 @@ class ShowController extends Controller /** * Show a single piggy bank. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return Factory|View */ @@ -73,7 +73,7 @@ class ShowController extends Controller /** @var Carbon $end */ $end = session('end', Carbon::now()->endOfMonth()); // transform piggies using the transformer: - $parameters = new ParameterBag; + $parameters = new ParameterBag(); $parameters->set('end', $end); /** @var PiggyBankTransformer $transformer */ diff --git a/app/Http/Controllers/Popup/ReportController.php b/app/Http/Controllers/Popup/ReportController.php index b5a442c988..93fdcc9a67 100644 --- a/app/Http/Controllers/Popup/ReportController.php +++ b/app/Http/Controllers/Popup/ReportController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.preferences')); + app('view')->share('title', (string)trans('firefly.preferences')); app('view')->share('mainTitleIcon', 'fa-gear'); return $next($request); @@ -62,12 +65,12 @@ class PreferencesController extends Controller /** * Show overview of preferences. * - * @param AccountRepositoryInterface $repository + * @param AccountRepositoryInterface $repository * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index(AccountRepositoryInterface $repository) { @@ -85,7 +88,7 @@ class PreferencesController extends Controller $role = sprintf('opt_group_l_%s', $type); } - if ('' === $role || 'opt_group_' === $role) { + if ('opt_group_' === $role) { $role = 'opt_group_defaultAsset'; } $groupedAccounts[trans(sprintf('firefly.%s', $role))][$account->id] = $account->name; @@ -101,11 +104,19 @@ class PreferencesController extends Controller $languages = config('firefly.languages'); $locale = app('preferences')->get('locale', config('firefly.default_locale', 'equal'))->data; $listPageSize = app('preferences')->get('listPageSize', 50)->data; + $slackUrl = app('preferences')->get('slack_webhook_url', '')->data; $customFiscalYear = app('preferences')->get('customFiscalYear', 0)->data; $fiscalYearStartStr = app('preferences')->get('fiscalYearStart', '01-01')->data; - $fiscalYearStart = date('Y') . '-' . $fiscalYearStartStr; + $fiscalYearStart = date('Y').'-'.$fiscalYearStartStr; $tjOptionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data; + // notification preferences (single value for each): + + $notifications = []; + foreach (config('firefly.available_notifications') as $notification) { + $notifications[$notification] = app('preferences')->get(sprintf('notification_%s', $notification), true)->data; + } + ksort($languages); // list of locales also has "equal" which makes it equal to whatever the language is. @@ -116,10 +127,10 @@ class PreferencesController extends Controller Log::error($e->getMessage()); $locales = []; } - $locales = ['equal' => (string) trans('firefly.equal_to_language')] + $locales; + $locales = ['equal' => (string)trans('firefly.equal_to_language')] + $locales; // an important fallback is that the frontPageAccount array gets refilled automatically // when it turns up empty. - if (empty($frontPageAccounts->data)) { + if (0 === count($frontPageAccounts->data)) { $frontPageAccounts = $accountIds; } @@ -131,6 +142,8 @@ class PreferencesController extends Controller 'isDocker', 'frontPageAccounts', 'languages', + 'notifications', + 'slackUrl', 'locales', 'locale', 'tjOptionalFields', @@ -145,12 +158,12 @@ class PreferencesController extends Controller /** * Store new preferences. * - * @param Request $request + * @param Request $request * * @return RedirectResponse|Redirector * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function postIndex(Request $request) { @@ -158,11 +171,23 @@ class PreferencesController extends Controller $frontPageAccounts = []; if (is_array($request->get('frontPageAccounts')) && count($request->get('frontPageAccounts')) > 0) { foreach ($request->get('frontPageAccounts') as $id) { - $frontPageAccounts[] = (int) $id; + $frontPageAccounts[] = (int)$id; } app('preferences')->set('frontPageAccounts', $frontPageAccounts); } + // extract notifications: + $all = $request->all(); + foreach (config('firefly.available_notifications') as $option) { + $key = sprintf('notification_%s', $option); + if (array_key_exists($key, $all)) { + app('preferences')->set($key, true); + } + if (!array_key_exists($key, $all)) { + app('preferences')->set($key, false); + } + } + // view range: app('preferences')->set('viewRange', $request->get('viewRange')); // forget session values: @@ -170,9 +195,19 @@ class PreferencesController extends Controller session()->forget('end'); session()->forget('range'); + + // slack URL: + $url = (string)$request->get('slackUrl'); + if (str_starts_with($url, 'https://hooks.slack.com/services/')) { + app('preferences')->set('slack_webhook_url', $url); + } + if ('' === $url) { + app('preferences')->delete('slack_webhook_url'); + } + // custom fiscal year - $customFiscalYear = 1 === (int) $request->get('customFiscalYear'); - $string = strtotime((string) $request->get('fiscalYearStart')); + $customFiscalYear = 1 === (int)$request->get('customFiscalYear'); + $string = strtotime((string)$request->get('fiscalYearStart')); if (false !== $string) { $fiscalYearStart = date('m-d', $string); app('preferences')->set('customFiscalYear', $customFiscalYear); @@ -182,7 +217,7 @@ class PreferencesController extends Controller // save page size: app('preferences')->set('listPageSize', 50); - $listPageSize = (int) $request->get('listPageSize'); + $listPageSize = (int)$request->get('listPageSize'); if ($listPageSize > 0 && $listPageSize < 1337) { app('preferences')->set('listPageSize', $listPageSize); } @@ -224,7 +259,7 @@ class PreferencesController extends Controller ]; app('preferences')->set('transaction_journal_optional_fields', $optionalTj); - session()->flash('success', (string) trans('firefly.saved_preferences')); + session()->flash('success', (string)trans('firefly.saved_preferences')); app('preferences')->mark(); return redirect(route('preferences.index')); diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index af76cfd2f2..7a6a8e171a 100644 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -1,4 +1,5 @@ middleware( static function ($request, $next) { - app('view')->share('title', (string) trans('firefly.profile')); + app('view')->share('title', (string)trans('firefly.profile')); app('view')->share('mainTitleIcon', 'fa-user'); return $next($request); @@ -94,64 +97,19 @@ class ProfileController extends Controller $this->middleware(IsDemoUser::class)->except(['index']); } - /** - * Change your email address. - * - * @param Request $request - * - * @return Factory|RedirectResponse|Redirector|View - */ - public function changeEmail(Request $request) - { - if (!$this->internalAuth || !$this->internalIdentity) { - $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); - - return redirect(route('profile.index')); - } - - $title = auth()->user()->email; - $email = auth()->user()->email; - $subTitle = (string) trans('firefly.change_your_email'); - $subTitleIcon = 'fa-envelope'; - - return view('profile.change-email', compact('title', 'subTitle', 'subTitleIcon', 'email')); - } - - /** - * Change your password. - * - * @param Request $request - * - * @return Factory|RedirectResponse|Redirector|View - */ - public function changePassword(Request $request) - { - if (!$this->internalAuth || !$this->internalIdentity) { - $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); - - return redirect(route('profile.index')); - } - - $title = auth()->user()->email; - $subTitle = (string) trans('firefly.change_your_password'); - $subTitleIcon = 'fa-key'; - - return view('profile.change-password', compact('title', 'subTitle', 'subTitleIcon')); - } - /** * View that generates a 2FA code for the user. * - * @param Request $request + * @param Request $request * - * @return Factory|View + * @return Factory|View|RedirectResponse * @throws IncompatibleWithGoogleAuthenticatorException * @throws InvalidCharactersException * @throws SecretKeyTooShortException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ - public function code(Request $request) + public function code(Request $request): Factory|View|RedirectResponse { if (!$this->internalAuth || !$this->internalIdentity) { $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); @@ -200,19 +158,17 @@ class ProfileController extends Controller /** * Screen to confirm email change. * - * @param UserRepositoryInterface $repository - * @param string $token + * @param UserRepositoryInterface $repository + * @param string $token * * @return RedirectResponse|Redirector * * @throws FireflyException */ - public function confirmEmailChange(UserRepositoryInterface $repository, string $token) + public function confirmEmailChange(UserRepositoryInterface $repository, string $token): RedirectResponse|Redirector { if (!$this->internalAuth || !$this->internalIdentity) { - throw new FireflyException(trans('firefly.external_user_mgt_disabled')); - } // find preference with this token value. /** @var Collection $set */ @@ -230,8 +186,8 @@ class ProfileController extends Controller } $repository->unblockUser($user); - // return to login. - session()->flash('success', (string) trans('firefly.login_with_new_email')); + // return to log in. + session()->flash('success', (string)trans('firefly.login_with_new_email')); return redirect(route('login')); } @@ -239,11 +195,11 @@ class ProfileController extends Controller /** * Delete your account view. * - * @param Request $request + * @param Request $request * - * @return Application|RedirectResponse|Redirector + * @return View|RedirectResponse */ - public function deleteAccount(Request $request) + public function deleteAccount(Request $request): View|RedirectResponse { if (!$this->internalAuth || !$this->internalIdentity) { $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); @@ -251,7 +207,7 @@ class ProfileController extends Controller return redirect(route('profile.index')); } $title = auth()->user()->email; - $subTitle = (string) trans('firefly.delete_account'); + $subTitle = (string)trans('firefly.delete_account'); $subTitleIcon = 'fa-trash'; return view('profile.delete-account', compact('title', 'subTitle', 'subTitleIcon')); @@ -262,7 +218,7 @@ class ProfileController extends Controller * * @return RedirectResponse|Redirector */ - public function deleteCode(Request $request) + public function deleteCode(Request $request): RedirectResponse|Redirector { if (!$this->internalAuth || !$this->internalIdentity) { $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); @@ -280,8 +236,8 @@ class ProfileController extends Controller $repository->setMFACode($user, null); app('preferences')->mark(); - session()->flash('success', (string) trans('firefly.pref_two_factor_auth_disabled')); - session()->flash('info', (string) trans('firefly.pref_two_factor_auth_remove_it')); + session()->flash('success', (string)trans('firefly.pref_two_factor_auth_disabled')); + session()->flash('info', (string)trans('firefly.pref_two_factor_auth_remove_it')); return redirect(route('profile.index')); } @@ -291,7 +247,7 @@ class ProfileController extends Controller * * @return RedirectResponse|Redirector */ - public function enable2FA(Request $request) + public function enable2FA(Request $request): RedirectResponse|Redirector { if (!$this->internalAuth || !$this->internalIdentity) { $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); @@ -310,7 +266,7 @@ class ProfileController extends Controller // If FF3 already has a secret, just set the two factor auth enabled to 1, // and let the user continue with the existing secret. - session()->flash('info', (string) trans('firefly.2fa_already_enabled')); + session()->flash('info', (string)trans('firefly.2fa_already_enabled')); return redirect(route('profile.index')); } @@ -320,10 +276,10 @@ class ProfileController extends Controller * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ - public function index() + public function index(): Factory|View { /** @var User $user */ $user = auth()->user(); @@ -339,7 +295,7 @@ class ProfileController extends Controller if (0 === $count) { /** @var ClientRepository $repository */ $repository = app(ClientRepository::class); - $repository->createPersonalAccessClient(null, config('app.name') . ' Personal Access Client', 'http://localhost'); + $repository->createPersonalAccessClient(null, config('app.name').' Personal Access Client', 'http://localhost'); } $accessToken = app('preferences')->get('access_token'); @@ -349,17 +305,18 @@ class ProfileController extends Controller } return view( - 'profile.index', compact('subTitle', 'mfaBackupCount', 'userId', 'accessToken', 'enabled2FA', 'isInternalAuth', 'isInternalIdentity') + 'profile.index', + compact('subTitle', 'mfaBackupCount', 'userId', 'accessToken', 'enabled2FA', 'isInternalAuth', 'isInternalIdentity') ); } /** - * + * @return Factory|View|RedirectResponse */ - public function logoutOtherSessions() + public function logoutOtherSessions(): Factory|View|RedirectResponse { if (!$this->internalAuth) { - session()->flash('info', (string) trans('firefly.external_auth_disabled')); + session()->flash('info', (string)trans('firefly.external_auth_disabled')); return redirect(route('profile.index')); } @@ -368,12 +325,12 @@ class ProfileController extends Controller } /** - * @param Request $request + * @param Request $request * - * @return Factory|View + * @return Factory|View|RedirectResponse * @throws FireflyException */ - public function newBackupCodes(Request $request) + public function newBackupCodes(Request $request): Factory|View|RedirectResponse { if (!$this->internalAuth || !$this->internalIdentity) { $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); @@ -399,12 +356,12 @@ class ProfileController extends Controller /** * Submit the change email form. * - * @param EmailFormRequest $request - * @param UserRepositoryInterface $repository + * @param EmailFormRequest $request + * @param UserRepositoryInterface $repository * - * @return $this|RedirectResponse|Redirector + * @return Factory|RedirectResponse|Redirector */ - public function postChangeEmail(EmailFormRequest $request, UserRepositoryInterface $repository) + public function postChangeEmail(EmailFormRequest $request, UserRepositoryInterface $repository): Factory|RedirectResponse|Redirector { if (!$this->internalAuth || !$this->internalIdentity) { $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); @@ -417,17 +374,17 @@ class ProfileController extends Controller $newEmail = $request->convertString('email'); $oldEmail = $user->email; if ($newEmail === $user->email) { - session()->flash('error', (string) trans('firefly.email_not_changed')); + session()->flash('error', (string)trans('firefly.email_not_changed')); return redirect(route('profile.change-email'))->withInput(); } $existing = $repository->findByEmail($newEmail); if (null !== $existing) { // force user logout. - Auth::guard()->logout(); + Auth::guard()->logout(); // @phpstan-ignore-line (does not recognize function) $request->session()->invalidate(); - session()->flash('success', (string) trans('firefly.email_changed')); + session()->flash('success', (string)trans('firefly.email_changed')); return redirect(route('index')); } @@ -438,18 +395,41 @@ class ProfileController extends Controller event(new UserChangedEmail($user, $newEmail, $oldEmail)); // force user logout. - Auth::guard()->logout(); + Auth::guard()->logout(); // @phpstan-ignore-line (does not recognize function) $request->session()->invalidate(); - session()->flash('success', (string) trans('firefly.email_changed')); + session()->flash('success', (string)trans('firefly.email_changed')); return redirect(route('index')); } + /** + * Change your email address. + * + * @param Request $request + * + * @return Factory|RedirectResponse|View + */ + public function changeEmail(Request $request): Factory|RedirectResponse|View + { + if (!$this->internalAuth || !$this->internalIdentity) { + $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); + + return redirect(route('profile.index')); + } + + $title = auth()->user()->email; + $email = auth()->user()->email; + $subTitle = (string)trans('firefly.change_your_email'); + $subTitleIcon = 'fa-envelope'; + + return view('profile.change-email', compact('title', 'subTitle', 'subTitleIcon', 'email')); + } + /** * Submit change password form. * - * @param ProfileFormRequest $request - * @param UserRepositoryInterface $repository + * @param ProfileFormRequest $request + * @param UserRepositoryInterface $repository * * @return RedirectResponse|Redirector */ @@ -475,20 +455,42 @@ class ProfileController extends Controller } $repository->changePassword($user, $request->get('new_password')); - session()->flash('success', (string) trans('firefly.password_changed')); + session()->flash('success', (string)trans('firefly.password_changed')); return redirect(route('profile.index')); } + /** + * Change your password. + * + * @param Request $request + * + * @return Factory|RedirectResponse|Redirector|View + */ + public function changePassword(Request $request) + { + if (!$this->internalAuth || !$this->internalIdentity) { + $request->session()->flash('error', trans('firefly.external_user_mgt_disabled')); + + return redirect(route('profile.index')); + } + + $title = auth()->user()->email; + $subTitle = (string)trans('firefly.change_your_password'); + $subTitleIcon = 'fa-key'; + + return view('profile.change-password', compact('title', 'subTitle', 'subTitleIcon')); + } + /** * Submit 2FA for the first time. * - * @param TokenFormRequest $request + * @param TokenFormRequest $request * * @return RedirectResponse|Redirector * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function postCode(TokenFormRequest $request) { @@ -509,7 +511,7 @@ class ProfileController extends Controller Preferences::delete('temp-mfa-secret'); Preferences::delete('temp-mfa-codes'); - session()->flash('success', (string) trans('firefly.saved_preferences')); + session()->flash('success', (string)trans('firefly.saved_preferences')); app('preferences')->mark(); // also save the code so replay attack is prevented. @@ -531,13 +533,13 @@ class ProfileController extends Controller } /** - * See reference nr. 64 + * TODO duplicate code. * - * @param string $mfaCode + * @param string $mfaCode * * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function addToMFAHistory(string $mfaCode): void { @@ -578,8 +580,8 @@ class ProfileController extends Controller /** * Submit delete account. * - * @param UserRepositoryInterface $repository - * @param DeleteAccountFormRequest $request + * @param UserRepositoryInterface $repository + * @param DeleteAccountFormRequest $request * * @return RedirectResponse|Redirector */ @@ -592,7 +594,7 @@ class ProfileController extends Controller } if (!Hash::check($request->get('password'), auth()->user()->password)) { - session()->flash('error', (string) trans('firefly.invalid_password')); + session()->flash('error', (string)trans('firefly.invalid_password')); return redirect(route('profile.delete-account')); } @@ -608,7 +610,7 @@ class ProfileController extends Controller } /** - * @param Request $request + * @param Request $request * * @return Application|RedirectResponse|Redirector * @throws AuthenticationException @@ -616,7 +618,7 @@ class ProfileController extends Controller public function postLogoutOtherSessions(Request $request) { if (!$this->internalAuth) { - session()->flash('info', (string) trans('firefly.external_auth_disabled')); + session()->flash('info', (string)trans('firefly.external_auth_disabled')); return redirect(route('profile.index')); } @@ -626,20 +628,19 @@ class ProfileController extends Controller ]; if (Auth::once($creds)) { Auth::logoutOtherDevices($request->get('password')); - session()->flash('info', (string) trans('firefly.other_sessions_logged_out')); + session()->flash('info', (string)trans('firefly.other_sessions_logged_out')); return redirect(route('profile.index')); } - session()->flash('error', (string) trans('auth.failed')); + session()->flash('error', (string)trans('auth.failed')); return redirect(route('profile.index')); - } /** * Regenerate access token. * - * @param Request $request + * @param Request $request * * @return RedirectResponse|Redirector * @throws FireflyException @@ -656,7 +657,7 @@ class ProfileController extends Controller $user = auth()->user(); $token = $user->generateAccessToken(); app('preferences')->set('access_token', $token); - session()->flash('success', (string) trans('firefly.token_regenerated')); + session()->flash('success', (string)trans('firefly.token_regenerated')); return redirect(route('profile.index')); } @@ -664,9 +665,9 @@ class ProfileController extends Controller /** * Undo change of user email address. * - * @param UserRepositoryInterface $repository - * @param string $token - * @param string $hash + * @param UserRepositoryInterface $repository + * @param string $token + * @param string $hash * * @return RedirectResponse|Redirector * @@ -696,7 +697,7 @@ class ProfileController extends Controller /** @var string $match */ $match = null; foreach ($set as $entry) { - $hashed = hash('sha256', sprintf('%s%s', (string) config('app.key'), $entry->data)); + $hashed = hash('sha256', sprintf('%s%s', (string)config('app.key'), $entry->data)); if ($hashed === $hash) { $match = $entry->data; break; @@ -711,7 +712,7 @@ class ProfileController extends Controller $repository->unblockUser($user); // return to login. - session()->flash('success', (string) trans('firefly.login_with_old_email')); + session()->flash('success', (string)trans('firefly.login_with_old_email')); return redirect(route('login')); } diff --git a/app/Http/Controllers/Recurring/CreateController.php b/app/Http/Controllers/Recurring/CreateController.php index ff2ca1650a..884155e1e9 100644 --- a/app/Http/Controllers/Recurring/CreateController.php +++ b/app/Http/Controllers/Recurring/CreateController.php @@ -63,8 +63,8 @@ class CreateController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-paint-brush'); - app('view')->share('title', (string) trans('firefly.recurrences')); - app('view')->share('subTitle', (string) trans('firefly.create_new_recurrence')); + app('view')->share('title', (string)trans('firefly.recurrences')); + app('view')->share('subTitle', (string)trans('firefly.create_new_recurrence')); $this->recurring = app(RecurringRepositoryInterface::class); $this->budgetRepos = app(BudgetRepositoryInterface::class); @@ -79,7 +79,7 @@ class CreateController extends Controller /** * Create a new recurring transaction. * - * @param Request $request + * @param Request $request * * @return Factory|View */ @@ -98,22 +98,22 @@ class CreateController extends Controller } $request->session()->forget('recurring.create.fromStore'); $repetitionEnds = [ - 'forever' => (string) trans('firefly.repeat_forever'), - 'until_date' => (string) trans('firefly.repeat_until_date'), - 'times' => (string) trans('firefly.repeat_times'), + 'forever' => (string)trans('firefly.repeat_forever'), + 'until_date' => (string)trans('firefly.repeat_until_date'), + 'times' => (string)trans('firefly.repeat_times'), ]; $weekendResponses = [ - RecurrenceRepetition::WEEKEND_DO_NOTHING => (string) trans('firefly.do_nothing'), - RecurrenceRepetition::WEEKEND_SKIP_CREATION => (string) trans('firefly.skip_transaction'), - RecurrenceRepetition::WEEKEND_TO_FRIDAY => (string) trans('firefly.jump_to_friday'), - RecurrenceRepetition::WEEKEND_TO_MONDAY => (string) trans('firefly.jump_to_monday'), + RecurrenceRepetition::WEEKEND_DO_NOTHING => (string)trans('firefly.do_nothing'), + RecurrenceRepetition::WEEKEND_SKIP_CREATION => (string)trans('firefly.skip_transaction'), + RecurrenceRepetition::WEEKEND_TO_FRIDAY => (string)trans('firefly.jump_to_friday'), + RecurrenceRepetition::WEEKEND_TO_MONDAY => (string)trans('firefly.jump_to_monday'), ]; $hasOldInput = null !== $request->old('_token'); // flash some data $preFilled = [ 'first_date' => $tomorrow->format('Y-m-d'), 'transaction_type' => $hasOldInput ? $request->old('transaction_type') : 'withdrawal', - 'active' => $hasOldInput ? (bool) $request->old('active') : true, - 'apply_rules' => $hasOldInput ? (bool) $request->old('apply_rules') : true, + 'active' => $hasOldInput ? (bool)$request->old('active') : true, + 'apply_rules' => $hasOldInput ? (bool)$request->old('apply_rules') : true, ]; $request->session()->flash('preFilled', $preFilled); @@ -124,8 +124,8 @@ class CreateController extends Controller } /** - * @param Request $request - * @param TransactionJournal $journal + * @param Request $request + * @param TransactionJournal $journal * * @return Factory|\Illuminate\Contracts\View\View */ @@ -144,15 +144,15 @@ class CreateController extends Controller } $request->session()->forget('recurring.create.fromStore'); $repetitionEnds = [ - 'forever' => (string) trans('firefly.repeat_forever'), - 'until_date' => (string) trans('firefly.repeat_until_date'), - 'times' => (string) trans('firefly.repeat_times'), + 'forever' => (string)trans('firefly.repeat_forever'), + 'until_date' => (string)trans('firefly.repeat_until_date'), + 'times' => (string)trans('firefly.repeat_times'), ]; $weekendResponses = [ - RecurrenceRepetition::WEEKEND_DO_NOTHING => (string) trans('firefly.do_nothing'), - RecurrenceRepetition::WEEKEND_SKIP_CREATION => (string) trans('firefly.skip_transaction'), - RecurrenceRepetition::WEEKEND_TO_FRIDAY => (string) trans('firefly.jump_to_friday'), - RecurrenceRepetition::WEEKEND_TO_MONDAY => (string) trans('firefly.jump_to_monday'), + RecurrenceRepetition::WEEKEND_DO_NOTHING => (string)trans('firefly.do_nothing'), + RecurrenceRepetition::WEEKEND_SKIP_CREATION => (string)trans('firefly.skip_transaction'), + RecurrenceRepetition::WEEKEND_TO_FRIDAY => (string)trans('firefly.jump_to_friday'), + RecurrenceRepetition::WEEKEND_TO_MONDAY => (string)trans('firefly.jump_to_monday'), ]; @@ -185,8 +185,8 @@ class CreateController extends Controller 'category' => $request->old('category'), 'budget_id' => $request->old('budget_id'), 'bill_id' => $request->old('bill_id'), - 'active' => (bool) $request->old('active'), - 'apply_rules' => (bool) $request->old('apply_rules'), + 'active' => (bool)$request->old('active'), + 'apply_rules' => (bool)$request->old('apply_rules'), ]; } if (false === $hasOldInput) { @@ -221,7 +221,7 @@ class CreateController extends Controller /** * Store a recurring transaction. * - * @param RecurrenceFormRequest $request + * @param RecurrenceFormRequest $request * * @return RedirectResponse|Redirector * @throws FireflyException @@ -237,7 +237,7 @@ class CreateController extends Controller return redirect(route('recurring.create'))->withInput(); } - $request->session()->flash('success', (string) trans('firefly.stored_new_recurrence', ['title' => $recurrence->title])); + $request->session()->flash('success', (string)trans('firefly.stored_new_recurrence', ['title' => $recurrence->title])); app('preferences')->mark(); // store attachment(s): @@ -247,7 +247,7 @@ class CreateController extends Controller $this->attachments->saveAttachmentsForModel($recurrence, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { @@ -255,7 +255,7 @@ class CreateController extends Controller } $redirect = redirect($this->getPreviousUrl('recurring.create.url')); - if (1 === (int) $request->get('create_another')) { + if (1 === (int)$request->get('create_another')) { // set value so create routine will not overwrite URL: $request->session()->put('recurring.create.fromStore', true); diff --git a/app/Http/Controllers/Recurring/DeleteController.php b/app/Http/Controllers/Recurring/DeleteController.php index 712555899f..c45bdb1bdb 100644 --- a/app/Http/Controllers/Recurring/DeleteController.php +++ b/app/Http/Controllers/Recurring/DeleteController.php @@ -53,7 +53,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-paint-brush'); - app('view')->share('title', (string) trans('firefly.recurrences')); + app('view')->share('title', (string)trans('firefly.recurrences')); $this->recurring = app(RecurringRepositoryInterface::class); @@ -65,13 +65,13 @@ class DeleteController extends Controller /** * Delete a recurring transaction form. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return Factory|View */ public function delete(Recurrence $recurrence) { - $subTitle = (string) trans('firefly.delete_recurring', ['title' => $recurrence->title]); + $subTitle = (string)trans('firefly.delete_recurring', ['title' => $recurrence->title]); // put previous url in session $this->rememberPreviousUrl('recurrences.delete.url'); @@ -83,19 +83,18 @@ class DeleteController extends Controller /** * Destroy the recurring transaction. * - * @param RecurringRepositoryInterface $repository - * @param Request $request - * @param Recurrence $recurrence + * @param RecurringRepositoryInterface $repository + * @param Request $request + * @param Recurrence $recurrence * * @return RedirectResponse|Redirector */ public function destroy(RecurringRepositoryInterface $repository, Request $request, Recurrence $recurrence) { $repository->destroy($recurrence); - $request->session()->flash('success', (string) trans('firefly.' . 'recurrence_deleted', ['title' => $recurrence->title])); + $request->session()->flash('success', (string)trans('firefly.'.'recurrence_deleted', ['title' => $recurrence->title])); app('preferences')->mark(); return redirect($this->getPreviousUrl('recurrences.delete.url')); } - } diff --git a/app/Http/Controllers/Recurring/EditController.php b/app/Http/Controllers/Recurring/EditController.php index fc75d33572..a0a908ac62 100644 --- a/app/Http/Controllers/Recurring/EditController.php +++ b/app/Http/Controllers/Recurring/EditController.php @@ -64,8 +64,8 @@ class EditController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-paint-brush'); - app('view')->share('title', (string) trans('firefly.recurrences')); - app('view')->share('subTitle', (string) trans('firefly.recurrences')); + app('view')->share('title', (string)trans('firefly.recurrences')); + app('view')->share('subTitle', (string)trans('firefly.recurrences')); $this->recurring = app(RecurringRepositoryInterface::class); $this->budgetRepos = app(BudgetRepositoryInterface::class); @@ -80,8 +80,8 @@ class EditController extends Controller /** * Edit a recurring transaction. * - * @param Request $request - * @param Recurrence $recurrence + * @param Request $request + * @param Recurrence $recurrence * * @return Factory|View * @throws FireflyException @@ -89,7 +89,7 @@ class EditController extends Controller */ public function edit(Request $request, Recurrence $recurrence) { - // See reference nr. 69 + // TODO this should be in the repository. $count = $recurrence->recurrenceTransactions()->count(); if (0 === $count) { throw new FireflyException('This recurring transaction has no meta-data. You will have to delete it and recreate it. Sorry!'); @@ -97,7 +97,7 @@ class EditController extends Controller /** @var RecurrenceTransformer $transformer */ $transformer = app(RecurrenceTransformer::class); - $transformer->setParameters(new ParameterBag); + $transformer->setParameters(new ParameterBag()); $array = $transformer->transform($recurrence); $budgets = app('expandedform')->makeSelectListWithEmpty($this->budgetRepos->getActiveBudgets()); @@ -107,7 +107,7 @@ class EditController extends Controller $repetition = $recurrence->recurrenceRepetitions()->first(); $currentRepType = $repetition->repetition_type; if ('' !== $repetition->repetition_moment) { - $currentRepType .= ',' . $repetition->repetition_moment; + $currentRepType .= ','.$repetition->repetition_moment; } // put previous url in session if not redirect from store (not "return_to_edit"). @@ -118,9 +118,9 @@ class EditController extends Controller $repetitionEnd = 'forever'; $repetitionEnds = [ - 'forever' => (string) trans('firefly.repeat_forever'), - 'until_date' => (string) trans('firefly.repeat_until_date'), - 'times' => (string) trans('firefly.repeat_times'), + 'forever' => (string)trans('firefly.repeat_forever'), + 'until_date' => (string)trans('firefly.repeat_until_date'), + 'times' => (string)trans('firefly.repeat_times'), ]; if (null !== $recurrence->repeat_until) { $repetitionEnd = 'until_date'; @@ -130,29 +130,36 @@ class EditController extends Controller } $weekendResponses = [ - RecurrenceRepetition::WEEKEND_DO_NOTHING => (string) trans('firefly.do_nothing'), - RecurrenceRepetition::WEEKEND_SKIP_CREATION => (string) trans('firefly.skip_transaction'), - RecurrenceRepetition::WEEKEND_TO_FRIDAY => (string) trans('firefly.jump_to_friday'), - RecurrenceRepetition::WEEKEND_TO_MONDAY => (string) trans('firefly.jump_to_monday'), + RecurrenceRepetition::WEEKEND_DO_NOTHING => (string)trans('firefly.do_nothing'), + RecurrenceRepetition::WEEKEND_SKIP_CREATION => (string)trans('firefly.skip_transaction'), + RecurrenceRepetition::WEEKEND_TO_FRIDAY => (string)trans('firefly.jump_to_friday'), + RecurrenceRepetition::WEEKEND_TO_MONDAY => (string)trans('firefly.jump_to_monday'), ]; $hasOldInput = null !== $request->old('_token'); $preFilled = [ 'transaction_type' => strtolower($recurrence->transactionType->type), - 'active' => $hasOldInput ? (bool) $request->old('active') : $recurrence->active, - 'apply_rules' => $hasOldInput ? (bool) $request->old('apply_rules') : $recurrence->apply_rules, + 'active' => $hasOldInput ? (bool)$request->old('active') : $recurrence->active, + 'apply_rules' => $hasOldInput ? (bool)$request->old('apply_rules') : $recurrence->apply_rules, 'deposit_source_id' => $array['transactions'][0]['source_id'], 'withdrawal_destination_id' => $array['transactions'][0]['destination_id'], ]; - $array['first_date'] = substr((string) $array['first_date'], 0, 10); - $array['repeat_until'] = substr((string) $array['repeat_until'], 0, 10); + $array['first_date'] = substr((string)$array['first_date'], 0, 10); + $array['repeat_until'] = substr((string)$array['repeat_until'], 0, 10); $array['transactions'][0]['tags'] = implode(',', $array['transactions'][0]['tags'] ?? []); return view( 'recurring.edit', compact( - 'recurrence', 'array', 'bills', - 'weekendResponses', 'budgets', 'preFilled', 'currentRepType', 'repetitionEnd', 'repetitionEnds' + 'recurrence', + 'array', + 'bills', + 'weekendResponses', + 'budgets', + 'preFilled', + 'currentRepType', + 'repetitionEnd', + 'repetitionEnds' ) ); } @@ -160,8 +167,8 @@ class EditController extends Controller /** * Update the recurring transaction. * - * @param RecurrenceFormRequest $request - * @param Recurrence $recurrence + * @param RecurrenceFormRequest $request + * @param Recurrence $recurrence * * @return RedirectResponse|Redirector * @throws FireflyException @@ -171,7 +178,7 @@ class EditController extends Controller $data = $request->getAll(); $this->recurring->update($recurrence, $data); - $request->session()->flash('success', (string) trans('firefly.updated_recurrence', ['title' => $recurrence->title])); + $request->session()->flash('success', (string)trans('firefly.updated_recurrence', ['title' => $recurrence->title])); // store new attachment(s): $files = $request->hasFile('attachments') ? $request->file('attachments') : null; @@ -179,7 +186,7 @@ class EditController extends Controller $this->attachments->saveAttachmentsForModel($recurrence, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachments->getMessages()->get('attachments')) > 0) { @@ -187,7 +194,7 @@ class EditController extends Controller } app('preferences')->mark(); $redirect = redirect($this->getPreviousUrl('recurrences.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { + if (1 === (int)$request->get('return_to_edit')) { // set value so edit routine will not overwrite URL: $request->session()->put('recurrences.edit.fromUpdate', true); diff --git a/app/Http/Controllers/Recurring/IndexController.php b/app/Http/Controllers/Recurring/IndexController.php index aad08bff71..3e0d426941 100644 --- a/app/Http/Controllers/Recurring/IndexController.php +++ b/app/Http/Controllers/Recurring/IndexController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-paint-brush'); - app('view')->share('title', (string) trans('firefly.recurrences')); + app('view')->share('title', (string)trans('firefly.recurrences')); $this->recurringRepos = app(RecurringRepositoryInterface::class); @@ -68,20 +71,20 @@ class IndexController extends Controller } /** - * See reference nr. 70 + * TODO the notes of a recurrence are pretty pointless at this moment. * Show all recurring transactions. * - * @param Request $request + * @param Request $request * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index(Request $request) { - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $collection = $this->recurringRepos->get(); $today = today(config('app.timezone')); $year = today(config('app.timezone')); @@ -92,12 +95,11 @@ class IndexController extends Controller /** @var RecurrenceTransformer $transformer */ $transformer = app(RecurrenceTransformer::class); - $transformer->setParameters(new ParameterBag); + $transformer->setParameters(new ParameterBag()); $recurring = []; /** @var Recurrence $recurrence */ foreach ($recurrences as $recurrence) { - $year->addYear(); if ($recurrence->first_date > $today) { $today = clone $recurrence->first_date; @@ -128,5 +130,4 @@ class IndexController extends Controller return view('recurring.index', compact('paginator', 'today', 'page', 'pageSize', 'total')); } - } diff --git a/app/Http/Controllers/Recurring/ShowController.php b/app/Http/Controllers/Recurring/ShowController.php index 94b94afcd9..055518626a 100644 --- a/app/Http/Controllers/Recurring/ShowController.php +++ b/app/Http/Controllers/Recurring/ShowController.php @@ -59,7 +59,7 @@ class ShowController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-paint-brush'); - app('view')->share('title', (string) trans('firefly.recurrences')); + app('view')->share('title', (string)trans('firefly.recurrences')); $this->recurring = app(RecurringRepositoryInterface::class); @@ -71,7 +71,7 @@ class ShowController extends Controller /** * Show a single recurring transaction. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return Factory|View * @throws FireflyException @@ -80,21 +80,26 @@ class ShowController extends Controller { /** @var RecurrenceTransformer $transformer */ $transformer = app(RecurrenceTransformer::class); - $transformer->setParameters(new ParameterBag); + $transformer->setParameters(new ParameterBag()); $array = $transformer->transform($recurrence); $groups = $this->recurring->getTransactions($recurrence); $today = today(config('app.timezone')); $array['repeat_until'] = null !== $array['repeat_until'] ? new Carbon($array['repeat_until']) : null; - // transform dates back to Carbon objects: + // transform dates back to Carbon objects and expand information foreach ($array['repetitions'] as $index => $repetition) { foreach ($repetition['occurrences'] as $item => $occurrence) { - $array['repetitions'][$index]['occurrences'][$item] = new Carbon($occurrence); + $date = (new Carbon($occurrence))->startOfDay(); + $set = [ + 'date' => $date, + 'fired' => $this->recurring->createdPreviously($recurrence, $date) || $this->recurring->getJournalCount($recurrence, $date) > 0, + ]; + $array['repetitions'][$index]['occurrences'][$item] = $set; } } - $subTitle = (string) trans('firefly.overview_for_recurrence', ['title' => $recurrence->title]); + $subTitle = (string)trans('firefly.overview_for_recurrence', ['title' => $recurrence->title]); return view('recurring.show', compact('recurrence', 'subTitle', 'array', 'groups', 'today')); } diff --git a/app/Http/Controllers/Recurring/TriggerController.php b/app/Http/Controllers/Recurring/TriggerController.php new file mode 100644 index 0000000000..d6f061e3d9 --- /dev/null +++ b/app/Http/Controllers/Recurring/TriggerController.php @@ -0,0 +1,90 @@ +. + */ + +namespace FireflyIII\Http\Controllers\Recurring; + +use Carbon\Carbon; +use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Http\Requests\TriggerRecurrenceRequest; +use FireflyIII\Jobs\CreateRecurringTransactions; +use FireflyIII\Models\Recurrence; +use FireflyIII\Models\TransactionGroup; +use FireflyIII\Models\TransactionJournal; +use Illuminate\Http\RedirectResponse; +use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; + +/** + * Class TriggerController + */ +class TriggerController extends Controller +{ + /** + * @param Recurrence $recurrence + * @param TriggerRecurrenceRequest $request + * @return RedirectResponse + */ + public function trigger(Recurrence $recurrence, TriggerRecurrenceRequest $request): RedirectResponse + { + $all = $request->getAll(); + $date = $all['date']; + + // grab the date from the last time the recurrence fired: + $backupDate = $recurrence->latest_date; + + // fire the recurring cron job on the given date, then post-date the created transaction. + Log::info(sprintf('Trigger: will now fire recurring cron job task for date "%s".', $date->format('Y-m-d H:i:s'))); + /** @var CreateRecurringTransactions $job */ + $job = app(CreateRecurringTransactions::class); + $job->setRecurrences(new Collection([$recurrence])); + $job->setDate($date); + $job->setForce(false); + $job->handle(); + Log::debug('Done with recurrence.'); + + $groups = $job->getGroups(); + /** @var TransactionGroup $group */ + foreach ($groups as $group) { + /** @var TransactionJournal $journal */ + foreach ($group->transactionJournals as $journal) { + Log::debug(sprintf('Set date of journal #%d to today!', $journal->id)); + $journal->date = Carbon::today(); + $journal->save(); + } + } + $recurrence->latest_date = $backupDate; + $recurrence->save(); + app('preferences')->mark(); + + if (0 === $groups->count()) { + $request->session()->flash('info', (string)trans('firefly.no_new_transaction_in_recurrence')); + } + if (1 === $groups->count()) { + $first = $groups->first(); + $request->session()->flash('success', (string)trans('firefly.stored_journal_no_descr')); + $request->session()->flash('success_url', route('transactions.show', [$first->id])); + } + + + return redirect(route('recurring.show', [$recurrence->id])); + } +} diff --git a/app/Http/Controllers/Report/AccountController.php b/app/Http/Controllers/Report/AccountController.php index b3485536c8..c837be0ec4 100644 --- a/app/Http/Controllers/Report/AccountController.php +++ b/app/Http/Controllers/Report/AccountController.php @@ -1,4 +1,5 @@ addProperty($start); $cache->addProperty($end); $cache->addProperty('account-report'); @@ -63,10 +63,10 @@ class AccountController extends Controller $accountReport = $accountTasker->getAccountReport($accounts, $start, $end); try { $result = view('reports.partials.accounts', compact('accountReport'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.accounts: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } $cache->store($result); diff --git a/app/Http/Controllers/Report/BalanceController.php b/app/Http/Controllers/Report/BalanceController.php index b4c6b37f7b..eb79b1b8e9 100644 --- a/app/Http/Controllers/Report/BalanceController.php +++ b/app/Http/Controllers/Report/BalanceController.php @@ -1,4 +1,5 @@ $sourceAccount, - 'currency_id' => $journal['currency_id'], - 'currency_code' => $journal['currency_code'], - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - 'spent' => '0', - ]; + 'source_account_id' => $sourceAccount, + 'currency_id' => $journal['currency_id'], + 'currency_code' => $journal['currency_code'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + 'spent' => '0', + ]; $spent[$sourceAccount]['spent'] = bcadd($spent[$sourceAccount]['spent'], $journal['amount']); // also fix sum: $report['sums'][$budgetId][$currencyId] = $report['sums'][$budgetId][$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $journal['currency_id'], - 'currency_code' => $journal['currency_code'], - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $journal['currency_id'], + 'currency_code' => $journal['currency_code'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $report['sums'][$budgetId][$currencyId]['sum'] = bcadd($report['sums'][$budgetId][$currencyId]['sum'], $journal['amount']); $report['accounts'][$sourceAccount]['sum'] = bcadd($report['accounts'][$sourceAccount]['sum'], $journal['amount']); @@ -137,10 +139,10 @@ class BalanceController extends Controller } try { $result = view('reports.partials.balance', compact('report'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.balance: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } return $result; diff --git a/app/Http/Controllers/Report/BillController.php b/app/Http/Controllers/Report/BillController.php index d374020f13..0cc81018c6 100644 --- a/app/Http/Controllers/Report/BillController.php +++ b/app/Http/Controllers/Report/BillController.php @@ -24,11 +24,11 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Report; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Report\ReportHelperInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; -use JsonException; use Log; use Throwable; @@ -38,15 +38,15 @@ use Throwable; class BillController extends Controller { /** - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string */ public function overview(Collection $accounts, Carbon $start, Carbon $end) { // chart properties for cache: - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('bill-report'); @@ -59,15 +59,14 @@ class BillController extends Controller $report = $helper->getBillReport($accounts, $start, $end); try { $result = view('reports.partials.bills', compact('report'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budgets: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } $cache->store($result); return $result; - } } diff --git a/app/Http/Controllers/Report/BudgetController.php b/app/Http/Controllers/Report/BudgetController.php index 20a5016076..cac91f5608 100644 --- a/app/Http/Controllers/Report/BudgetController.php +++ b/app/Http/Controllers/Report/BudgetController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { $this->opsRepository = app(OperationsRepositoryInterface::class); - $this->repository = app(BudgetRepositoryInterface::class); - $this->blRepository = app(BudgetLimitRepositoryInterface::class); - $this->nbRepository = app(NoBudgetRepositoryInterface::class); return $next($request); } @@ -75,10 +68,10 @@ class BudgetController extends Controller /** * Partial used in the budget report. * - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -100,10 +93,10 @@ class BudgetController extends Controller } /** - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -116,33 +109,33 @@ class BudgetController extends Controller foreach ($accounts as $account) { $accountId = $account->id; $report[$accountId] = $report[$accountId] ?? [ - 'name' => $account->name, - 'id' => $account->id, - 'iban' => $account->iban, - 'currencies' => [], - ]; + 'name' => $account->name, + 'id' => $account->id, + 'iban' => $account->iban, + 'currencies' => [], + ]; } // loop expenses. foreach ($spent as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'sum' => '0', + ]; foreach ($currency['budgets'] as $budget) { foreach ($budget['transaction_journals'] as $journal) { $sourceAccountId = $journal['source_account_id']; $report[$sourceAccountId]['currencies'][$currencyId] = $report[$sourceAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'sum' => '0', + ]; $report[$sourceAccountId]['currencies'][$currencyId]['sum'] = bcadd( $report[$sourceAccountId]['currencies'][$currencyId]['sum'], $journal['amount'] @@ -156,10 +149,10 @@ class BudgetController extends Controller } /** - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -173,21 +166,21 @@ class BudgetController extends Controller $destinationId = $journal['destination_account_id']; $key = sprintf('%d-%d', $destinationId, $currency['currency_id']); $result[$key] = $result[$key] ?? [ - 'transactions' => 0, - 'sum' => '0', - 'avg' => '0', - 'avg_float' => 0, - 'destination_account_name' => $journal['destination_account_name'], - 'destination_account_id' => $journal['destination_account_id'], - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'transactions' => 0, + 'sum' => '0', + 'avg' => '0', + 'avg_float' => 0, + 'destination_account_name' => $journal['destination_account_name'], + 'destination_account_id' => $journal['destination_account_id'], + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $result[$key]['transactions']++; $result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']); - $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']); - $result[$key]['avg_float'] = (float) $result[$key]['avg']; // intentional float + $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string)$result[$key]['transactions']); + $result[$key]['avg_float'] = (float)$result[$key]['avg']; // intentional float } } } @@ -198,20 +191,20 @@ class BudgetController extends Controller try { $result = view('reports.budget.partials.avg-expenses', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -224,20 +217,20 @@ class BudgetController extends Controller foreach ($budgets as $budget) { $budgetId = $budget->id; $report[$budgetId] = $report[$budgetId] ?? [ - 'name' => $budget->name, - 'id' => $budget->id, - 'currencies' => [], - ]; + 'name' => $budget->name, + 'id' => $budget->id, + 'currencies' => [], + ]; } foreach ($spent as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'sum' => '0', + ]; /** @var array $budget */ foreach ($currency['budgets'] as $budget) { $budgetId = $budget['id']; @@ -245,14 +238,14 @@ class BudgetController extends Controller foreach ($budget['transaction_journals'] as $journal) { // add currency info to report array: $report[$budgetId]['currencies'][$currencyId] = $report[$budgetId]['currencies'][$currencyId] ?? [ - 'sum' => '0', - 'sum_pct' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], + 'sum' => '0', + 'sum_pct' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + ]; $report[$budgetId]['currencies'][$currencyId]['sum'] = bcadd($report[$budgetId]['currencies'][$currencyId]['sum'], $journal['amount']); $sums[$currencyId]['sum'] = bcadd($sums[$currencyId]['sum'], $journal['amount']); } @@ -266,7 +259,7 @@ class BudgetController extends Controller $total = $sums[$currencyId]['sum'] ?? '0'; $pct = '0'; if (0 !== bccomp($sum, '0') && 0 !== bccomp($total, '9')) { - $pct = round((float) bcmul(bcdiv($sum, $total), '100')); // intentional float + $pct = round((float)bcmul(bcdiv($sum, $total), '100')); // intentional float } $report[$budgetId]['currencies'][$currencyId]['sum_pct'] = $pct; } @@ -278,9 +271,9 @@ class BudgetController extends Controller /** * Show partial overview of budgets. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -303,16 +296,16 @@ class BudgetController extends Controller /** * Show budget overview for a period. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string * @throws JsonException */ public function period(Collection $accounts, Carbon $start, Carbon $end) { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('budget-period-report'); @@ -335,29 +328,29 @@ class BudgetController extends Controller $key = sprintf('%d-%d', $budget['id'], $currency['currency_id']); $dateKey = $journal['date']->format($keyFormat); $report[$key] = $report[$key] ?? [ - 'id' => $budget['id'], - 'name' => sprintf('%s (%s)', $budget['name'], $currency['currency_name']), - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'entries' => [], - ]; + 'id' => $budget['id'], + 'name' => sprintf('%s (%s)', $budget['name'], $currency['currency_name']), + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'entries' => [], + ]; $report[$key]['entries'][$dateKey] = $report[$key] ['entries'][$dateKey] ?? '0'; $report[$key]['entries'][$dateKey] = bcadd($journal['amount'], $report[$key] ['entries'][$dateKey]); $report[$key]['sum'] = bcadd($report[$key] ['sum'], $journal['amount']); - $report[$key]['avg'] = bcdiv($report[$key]['sum'], (string) count($periods)); + $report[$key]['avg'] = bcdiv($report[$key]['sum'], (string)count($periods)); } } } try { $result = view('reports.partials.budget-period', compact('report', 'periods'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } $cache->store($result); @@ -366,10 +359,10 @@ class BudgetController extends Controller } /** - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -383,7 +376,7 @@ class BudgetController extends Controller $result[] = [ 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], - 'amount_float' => (float) $journal['amount'], // intentional float + 'amount_float' => (float)$journal['amount'], // intentional float 'amount' => $journal['amount'], 'date' => $journal['date']->isoFormat($this->monthAndDayFormat), 'date_sort' => $journal['date']->format('Y-m-d'), @@ -406,10 +399,10 @@ class BudgetController extends Controller try { $result = view('reports.budget.partials.top-expenses', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; diff --git a/app/Http/Controllers/Report/CategoryController.php b/app/Http/Controllers/Report/CategoryController.php index 5b2294f67b..7a8c66f23f 100644 --- a/app/Http/Controllers/Report/CategoryController.php +++ b/app/Http/Controllers/Report/CategoryController.php @@ -1,4 +1,5 @@ id; $report[$accountId] = $report[$accountId] ?? [ - 'name' => $account->name, - 'id' => $account->id, - 'iban' => $account->iban, - 'currencies' => [], - ]; + 'name' => $account->name, + 'id' => $account->id, + 'iban' => $account->iban, + 'currencies' => [], + ]; } // loop expenses. @@ -99,12 +101,12 @@ class CategoryController extends Controller foreach ($category['transaction_journals'] as $journal) { $sourceAccountId = $journal['source_account_id']; $report[$sourceAccountId]['currencies'][$currencyId] = $report[$sourceAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'categories' => [], - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'categories' => [], + ]; $report[$sourceAccountId]['currencies'][$currencyId]['categories'][$category['id']] = $report[$sourceAccountId]['currencies'][$currencyId]['categories'][$category['id']] @@ -166,10 +168,10 @@ class CategoryController extends Controller } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -183,37 +185,37 @@ class CategoryController extends Controller foreach ($accounts as $account) { $accountId = $account->id; $report[$accountId] = $report[$accountId] ?? [ - 'name' => $account->name, - 'id' => $account->id, - 'iban' => $account->iban, - 'currencies' => [], - ]; + 'name' => $account->name, + 'id' => $account->id, + 'iban' => $account->iban, + 'currencies' => [], + ]; } // loop expenses. foreach ($spent as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent_sum' => '0', - 'earned_sum' => '0', - 'total_sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent_sum' => '0', + 'earned_sum' => '0', + 'total_sum' => '0', + ]; foreach ($currency['categories'] as $category) { foreach ($category['transaction_journals'] as $journal) { $sourceAccountId = $journal['source_account_id']; $report[$sourceAccountId]['currencies'][$currencyId] = $report[$sourceAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; $report[$sourceAccountId]['currencies'][$currencyId]['spent'] = bcadd( $report[$sourceAccountId]['currencies'][$currencyId]['spent'], $journal['amount'] @@ -232,26 +234,26 @@ class CategoryController extends Controller foreach ($earned as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent_sum' => '0', - 'earned_sum' => '0', - 'total_sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent_sum' => '0', + 'earned_sum' => '0', + 'total_sum' => '0', + ]; foreach ($currency['categories'] as $category) { foreach ($category['transaction_journals'] as $journal) { $destinationAccountId = $journal['destination_account_id']; $report[$destinationAccountId]['currencies'][$currencyId] = $report[$destinationAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; $report[$destinationAccountId]['currencies'][$currencyId]['earned'] = bcadd( $report[$destinationAccountId]['currencies'][$currencyId]['earned'], $journal['amount'] @@ -270,10 +272,10 @@ class CategoryController extends Controller } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -287,21 +289,21 @@ class CategoryController extends Controller $destinationId = $journal['destination_account_id']; $key = sprintf('%d-%d', $destinationId, $currency['currency_id']); $result[$key] = $result[$key] ?? [ - 'transactions' => 0, - 'sum' => '0', - 'avg' => '0', - 'avg_float' => 0, - 'destination_account_name' => $journal['destination_account_name'], - 'destination_account_id' => $journal['destination_account_id'], - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'transactions' => 0, + 'sum' => '0', + 'avg' => '0', + 'avg_float' => 0, + 'destination_account_name' => $journal['destination_account_name'], + 'destination_account_id' => $journal['destination_account_id'], + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $result[$key]['transactions']++; $result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']); - $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']); - $result[$key]['avg_float'] = (float) $result[$key]['avg']; // intentional float + $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string)$result[$key]['transactions']); + $result[$key]['avg_float'] = (float)$result[$key]['avg']; // intentional float } } } @@ -312,20 +314,20 @@ class CategoryController extends Controller try { $result = view('reports.category.partials.avg-expenses', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -339,21 +341,21 @@ class CategoryController extends Controller $sourceId = $journal['source_account_id']; $key = sprintf('%d-%d', $sourceId, $currency['currency_id']); $result[$key] = $result[$key] ?? [ - 'transactions' => 0, - 'sum' => '0', - 'avg' => '0', - 'avg_float' => 0, - 'source_account_name' => $journal['source_account_name'], - 'source_account_id' => $journal['source_account_id'], - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'transactions' => 0, + 'sum' => '0', + 'avg' => '0', + 'avg_float' => 0, + 'source_account_name' => $journal['source_account_name'], + 'source_account_id' => $journal['source_account_id'], + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $result[$key]['transactions']++; $result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']); - $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']); - $result[$key]['avg_float'] = (float) $result[$key]['avg']; + $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string)$result[$key]['transactions']); + $result[$key]['avg_float'] = (float)$result[$key]['avg']; } } } @@ -364,20 +366,20 @@ class CategoryController extends Controller try { $result = view('reports.category.partials.avg-income', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -391,22 +393,22 @@ class CategoryController extends Controller foreach ($categories as $category) { $categoryId = $category->id; $report[$categoryId] = $report[$categoryId] ?? [ - 'name' => $category->name, - 'id' => $category->id, - 'currencies' => [], - ]; + 'name' => $category->name, + 'id' => $category->id, + 'currencies' => [], + ]; } foreach ($spent as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'earned_sum' => '0', - 'spent_sum' => '0', - 'total_sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'earned_sum' => '0', + 'spent_sum' => '0', + 'total_sum' => '0', + ]; /** @var array $category */ foreach ($currency['categories'] as $category) { $categoryId = $category['id']; @@ -414,14 +416,14 @@ class CategoryController extends Controller foreach ($category['transaction_journals'] as $journal) { // add currency info to report array: $report[$categoryId]['currencies'][$currencyId] = $report[$categoryId]['currencies'][$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $report[$categoryId]['currencies'][$currencyId]['spent'] = bcadd( $report[$categoryId]['currencies'][$currencyId]['spent'], $journal['amount'] @@ -440,14 +442,14 @@ class CategoryController extends Controller foreach ($earned as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'earned_sum' => '0', - 'spent_sum' => '0', - 'total_sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'earned_sum' => '0', + 'spent_sum' => '0', + 'total_sum' => '0', + ]; /** @var array $category */ foreach ($currency['categories'] as $category) { $categoryId = $category['id']; @@ -455,14 +457,14 @@ class CategoryController extends Controller foreach ($category['transaction_journals'] as $journal) { // add currency info to report array: $report[$categoryId]['currencies'][$currencyId] = $report[$categoryId]['currencies'][$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $report[$categoryId]['currencies'][$currencyId]['earned'] = bcadd( $report[$categoryId]['currencies'][$currencyId]['earned'], $journal['amount'] @@ -484,16 +486,16 @@ class CategoryController extends Controller /** * Show overview of expenses in category. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string * @throws JsonException */ public function expenses(Collection $accounts, Carbon $start, Carbon $end) { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('category-period-expenses-report'); @@ -522,17 +524,17 @@ class CategoryController extends Controller foreach ($currencyRow['categories'] as $categoryId => $categoryRow) { $key = sprintf('%d-%d', $currencyId, $categoryId); $data[$key] = $data[$key] ?? [ - 'id' => $categoryRow['id'], - 'title' => sprintf('%s (%s)', $categoryRow['name'], $currencyRow['currency_name']), - 'currency_id' => $currencyRow['currency_id'], - 'currency_symbol' => $currencyRow['currency_symbol'], - 'currency_name' => $currencyRow['currency_name'], - 'currency_code' => $currencyRow['currency_code'], - 'currency_decimal_places' => $currencyRow['currency_decimal_places'], - 'sum' => '0', - 'entries' => [], + 'id' => $categoryRow['id'], + 'title' => sprintf('%s (%s)', $categoryRow['name'], $currencyRow['currency_name']), + 'currency_id' => $currencyRow['currency_id'], + 'currency_symbol' => $currencyRow['currency_symbol'], + 'currency_name' => $currencyRow['currency_name'], + 'currency_code' => $currencyRow['currency_code'], + 'currency_decimal_places' => $currencyRow['currency_decimal_places'], + 'sum' => '0', + 'entries' => [], - ]; + ]; foreach ($categoryRow['transaction_journals'] as $journal) { $date = $journal['date']->format($format); $data[$key]['entries'][$date] = $data[$key]['entries'][$date] ?? '0'; @@ -549,10 +551,10 @@ class CategoryController extends Controller try { $result = view('reports.partials.category-period', compact('report', 'periods'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage())); $result = sprintf('An error prevented Firefly III from rendering: %s. Apologies.', $e->getMessage()); + throw new FireflyException($result, 0, $e); } @@ -564,17 +566,17 @@ class CategoryController extends Controller /** * Show overview of income in category. * - * @param Collection $accounts + * @param Collection $accounts * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return string * @throws JsonException */ public function income(Collection $accounts, Carbon $start, Carbon $end): string { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('category-period-income-report'); @@ -603,17 +605,17 @@ class CategoryController extends Controller foreach ($currencyRow['categories'] as $categoryId => $categoryRow) { $key = sprintf('%d-%d', $currencyId, $categoryId); $data[$key] = $data[$key] ?? [ - 'id' => $categoryRow['id'], - 'title' => sprintf('%s (%s)', $categoryRow['name'], $currencyRow['currency_name']), - 'currency_id' => $currencyRow['currency_id'], - 'currency_symbol' => $currencyRow['currency_symbol'], - 'currency_name' => $currencyRow['currency_name'], - 'currency_code' => $currencyRow['currency_code'], - 'currency_decimal_places' => $currencyRow['currency_decimal_places'], - 'sum' => '0', - 'entries' => [], + 'id' => $categoryRow['id'], + 'title' => sprintf('%s (%s)', $categoryRow['name'], $currencyRow['currency_name']), + 'currency_id' => $currencyRow['currency_id'], + 'currency_symbol' => $currencyRow['currency_symbol'], + 'currency_name' => $currencyRow['currency_name'], + 'currency_code' => $currencyRow['currency_code'], + 'currency_decimal_places' => $currencyRow['currency_decimal_places'], + 'sum' => '0', + 'entries' => [], - ]; + ]; foreach ($categoryRow['transaction_journals'] as $journal) { $date = $journal['date']->format($format); $data[$key]['entries'][$date] = $data[$key]['entries'][$date] ?? '0'; @@ -629,10 +631,10 @@ class CategoryController extends Controller try { $result = view('reports.partials.category-period', compact('report', 'periods'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage())); $result = sprintf('An error prevented Firefly III from rendering: %s. Apologies.', $e->getMessage()); + throw new FireflyException($result, 0, $e); } @@ -644,16 +646,16 @@ class CategoryController extends Controller /** * Show overview of category transactions on the default report. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return string */ public function operations(Collection $accounts, Carbon $start, Carbon $end): string { // chart properties for cache: - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('category-report'); @@ -672,21 +674,22 @@ class CategoryController extends Controller try { - $result = (string) view('reports.partials.categories', compact('report'))->render(); + $result = (string)view('reports.partials.categories', compact('report'))->render(); $cache->store($result); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render category::expenses: %s', $e->getMessage())); $result = sprintf('An error prevented Firefly III from rendering: %s. Apologies.', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -700,7 +703,7 @@ class CategoryController extends Controller $result[] = [ 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], - 'amount_float' => (float) $journal['amount'], + 'amount_float' => (float)$journal['amount'], 'amount' => $journal['amount'], 'date' => $journal['date']->isoFormat($this->monthAndDayFormat), 'date_sort' => $journal['date']->format('Y-m-d'), @@ -723,20 +726,20 @@ class CategoryController extends Controller try { $result = view('reports.category.partials.top-expenses', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -750,7 +753,7 @@ class CategoryController extends Controller $result[] = [ 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], - 'amount_float' => (float) $journal['amount'], + 'amount_float' => (float)$journal['amount'], 'amount' => $journal['amount'], 'date' => $journal['date']->isoFormat($this->monthAndDayFormat), 'date_sort' => $journal['date']->format('Y-m-d'), @@ -773,13 +776,12 @@ class CategoryController extends Controller try { $result = view('reports.category.partials.top-income', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } return $result; } - } diff --git a/app/Http/Controllers/Report/DoubleController.php b/app/Http/Controllers/Report/DoubleController.php index 5472e9741b..50605fb754 100644 --- a/app/Http/Controllers/Report/DoubleController.php +++ b/app/Http/Controllers/Report/DoubleController.php @@ -1,4 +1,5 @@ 0, - 'sum' => '0', - 'avg' => '0', - 'avg_float' => 0, - 'source_account_name' => $journal['source_account_name'], - 'source_account_id' => $journal['source_account_id'], - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'transactions' => 0, + 'sum' => '0', + 'avg' => '0', + 'avg_float' => 0, + 'source_account_name' => $journal['source_account_name'], + 'source_account_id' => $journal['source_account_id'], + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $result[$key]['transactions']++; $result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']); - $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']); - $result[$key]['avg_float'] = (float) $result[$key]['avg']; + $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string)$result[$key]['transactions']); + $result[$key]['avg_float'] = (float)$result[$key]['avg']; } } // sort by amount_float @@ -111,20 +113,20 @@ class DoubleController extends Controller try { $result = view('reports.double.partials.avg-expenses', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $doubles - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $doubles + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -139,21 +141,21 @@ class DoubleController extends Controller $destinationId = $journal['destination_account_id']; $key = sprintf('%d-%d', $destinationId, $currency['currency_id']); $result[$key] = $result[$key] ?? [ - 'transactions' => 0, - 'sum' => '0', - 'avg' => '0', - 'avg_float' => 0, - 'destination_account_name' => $journal['destination_account_name'], - 'destination_account_id' => $journal['destination_account_id'], - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'transactions' => 0, + 'sum' => '0', + 'avg' => '0', + 'avg_float' => 0, + 'destination_account_name' => $journal['destination_account_name'], + 'destination_account_id' => $journal['destination_account_id'], + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $result[$key]['transactions']++; $result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']); - $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']); - $result[$key]['avg_float'] = (float) $result[$key]['avg']; + $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string)$result[$key]['transactions']); + $result[$key]['avg_float'] = (float)$result[$key]['avg']; } } // sort by amount_float @@ -163,20 +165,20 @@ class DoubleController extends Controller try { $result = view('reports.double.partials.avg-income', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $double - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $double + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -196,15 +198,15 @@ class DoubleController extends Controller $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; /** @var array $journal */ foreach ($currency['transaction_journals'] as $journal) { @@ -214,19 +216,19 @@ class DoubleController extends Controller $genericName = $this->getCounterpartName($withCounterpart, $destId, $destName, $destIban); $objectName = sprintf('%s (%s)', $genericName, $currency['currency_name']); $report[$objectName] = $report[$objectName] ?? [ - 'dest_name' => '', - 'dest_iban' => '', - 'source_name' => '', - 'source_iban' => '', - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'dest_name' => '', + 'dest_iban' => '', + 'source_name' => '', + 'source_iban' => '', + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; // set name $report[$objectName]['dest_name'] = $destName; $report[$objectName]['dest_iban'] = $destIban; @@ -244,15 +246,15 @@ class DoubleController extends Controller $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; /** @var array $journal */ foreach ($currency['transaction_journals'] as $journal) { @@ -262,19 +264,19 @@ class DoubleController extends Controller $genericName = $this->getCounterpartName($withCounterpart, $sourceId, $sourceName, $sourceIban); $objectName = sprintf('%s (%s)', $genericName, $currency['currency_name']); $report[$objectName] = $report[$objectName] ?? [ - 'dest_name' => '', - 'dest_iban' => '', - 'source_name' => '', - 'source_iban' => '', - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'dest_name' => '', + 'dest_iban' => '', + 'source_name' => '', + 'source_iban' => '', + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; // set name $report[$objectName]['source_name'] = $sourceName; @@ -292,12 +294,12 @@ class DoubleController extends Controller } /** - * See reference nr. 67 + * TODO this method is duplicated. * - * @param Collection $accounts - * @param int $id - * @param string $name - * @param string|null $iban + * @param Collection $accounts + * @param int $id + * @param string $name + * @param string|null $iban * * @return string */ @@ -317,10 +319,10 @@ class DoubleController extends Controller } /** - * @param Collection $accounts - * @param Collection $double - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $double + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -340,31 +342,31 @@ class DoubleController extends Controller $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; /** @var array $journal */ foreach ($currency['transaction_journals'] as $journal) { $objectName = sprintf('%s (%s)', $journal['source_account_name'], $currency['currency_name']); $report[$objectName] = $report[$objectName] ?? [ - 'account_id' => $journal['source_account_id'], - 'account_name' => $objectName, - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'account_id' => $journal['source_account_id'], + 'account_name' => $objectName, + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; // set name // add amounts: $report[$objectName]['spent'] = bcadd($report[$objectName]['spent'], $journal['amount']); @@ -379,31 +381,31 @@ class DoubleController extends Controller $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; /** @var array $journal */ foreach ($currency['transaction_journals'] as $journal) { $objectName = sprintf('%s (%s)', $journal['destination_account_name'], $currency['currency_name']); $report[$objectName] = $report[$objectName] ?? [ - 'account_id' => $journal['destination_account_id'], - 'account_name' => $objectName, - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'account_id' => $journal['destination_account_id'], + 'account_name' => $objectName, + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; // add amounts: $report[$objectName]['earned'] = bcadd($report[$objectName]['earned'], $journal['amount']); @@ -417,10 +419,10 @@ class DoubleController extends Controller } /** - * @param Collection $accounts - * @param Collection $doubles - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $doubles + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -435,7 +437,7 @@ class DoubleController extends Controller $result[] = [ 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], - 'amount_float' => (float) $journal['amount'], + 'amount_float' => (float)$journal['amount'], 'amount' => $journal['amount'], 'date' => $journal['date']->isoFormat($this->monthAndDayFormat), 'date_sort' => $journal['date']->format('Y-m-d'), @@ -457,20 +459,20 @@ class DoubleController extends Controller try { $result = view('reports.double.partials.top-expenses', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $doubles - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $doubles + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -485,7 +487,7 @@ class DoubleController extends Controller $result[] = [ 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], - 'amount_float' => (float) $journal['amount'], + 'amount_float' => (float)$journal['amount'], 'amount' => $journal['amount'], 'date' => $journal['date']->isoFormat($this->monthAndDayFormat), 'date_sort' => $journal['date']->format('Y-m-d'), @@ -507,10 +509,10 @@ class DoubleController extends Controller try { $result = view('reports.double.partials.top-income', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($e->getMessage(), 0, $e); } return $result; diff --git a/app/Http/Controllers/Report/OperationsController.php b/app/Http/Controllers/Report/OperationsController.php index aba2fd000b..6569fddad0 100644 --- a/app/Http/Controllers/Report/OperationsController.php +++ b/app/Http/Controllers/Report/OperationsController.php @@ -1,4 +1,5 @@ addProperty($start); $cache->addProperty($end); $cache->addProperty('expense-report'); @@ -83,10 +83,10 @@ class OperationsController extends Controller $type = 'expense-entry'; try { $result = view('reports.partials.income-expenses', compact('report', 'type'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.income-expense: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } $cache->store($result); @@ -97,16 +97,16 @@ class OperationsController extends Controller /** * View of income. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return string */ public function income(Collection $accounts, Carbon $start, Carbon $end): string { // chart properties for cache: - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('income-report'); @@ -118,10 +118,10 @@ class OperationsController extends Controller $type = 'income-entry'; try { $result = view('reports.partials.income-expenses', compact('report', 'type'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.income-expenses: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } $cache->store($result); @@ -132,16 +132,16 @@ class OperationsController extends Controller /** * Overview of income and expense. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return mixed|string */ public function operations(Collection $accounts, Carbon $start, Carbon $end) { // chart properties for cache: - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('inc-exp-report'); @@ -159,23 +159,24 @@ class OperationsController extends Controller foreach ($keys as $currencyId) { $currencyInfo = $incomes['sums'][$currencyId] ?? $expenses['sums'][$currencyId]; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currencyId, - 'currency_name' => $currencyInfo['currency_name'], - 'currency_code' => $currencyInfo['currency_code'], - 'currency_symbol' => $currencyInfo['currency_symbol'], - 'currency_decimal_places' => $currencyInfo['currency_decimal_places'], - 'in' => $incomes['sums'][$currencyId]['sum'] ?? '0', - 'out' => $expenses['sums'][$currencyId]['sum'] ?? '0', - 'sum' => '0', - ]; + 'currency_id' => $currencyId, + 'currency_name' => $currencyInfo['currency_name'], + 'currency_code' => $currencyInfo['currency_code'], + 'currency_symbol' => $currencyInfo['currency_symbol'], + 'currency_decimal_places' => $currencyInfo['currency_decimal_places'], + 'in' => $incomes['sums'][$currencyId]['sum'] ?? '0', + 'out' => $expenses['sums'][$currencyId]['sum'] ?? '0', + 'sum' => '0', + ]; $sums[$currencyId]['sum'] = bcadd($sums[$currencyId]['in'], $sums[$currencyId]['out']); } try { $result = view('reports.partials.operations', compact('sums'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.operations: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } $cache->store($result); diff --git a/app/Http/Controllers/Report/TagController.php b/app/Http/Controllers/Report/TagController.php index e83a3c25b1..557cb75f84 100644 --- a/app/Http/Controllers/Report/TagController.php +++ b/app/Http/Controllers/Report/TagController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Report; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; use FireflyIII\Models\Tag; @@ -60,10 +61,10 @@ class TagController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -76,11 +77,11 @@ class TagController extends Controller foreach ($accounts as $account) { $accountId = $account->id; $report[$accountId] = $report[$accountId] ?? [ - 'name' => $account->name, - 'id' => $account->id, - 'iban' => $account->iban, - 'currencies' => [], - ]; + 'name' => $account->name, + 'id' => $account->id, + 'iban' => $account->iban, + 'currencies' => [], + ]; } // loop expenses. @@ -92,12 +93,12 @@ class TagController extends Controller foreach ($tag['transaction_journals'] as $journal) { $sourceAccountId = $journal['source_account_id']; $report[$sourceAccountId]['currencies'][$currencyId] = $report[$sourceAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'tags' => [], - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'tags' => [], + ]; $report[$sourceAccountId]['currencies'][$currencyId]['tags'][$tag['id']] = $report[$sourceAccountId]['currencies'][$currencyId]['tags'][$tag['id']] @@ -159,10 +160,10 @@ class TagController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -176,37 +177,37 @@ class TagController extends Controller foreach ($accounts as $account) { $accountId = $account->id; $report[$accountId] = $report[$accountId] ?? [ - 'name' => $account->name, - 'id' => $account->id, - 'iban' => $account->iban, - 'currencies' => [], - ]; + 'name' => $account->name, + 'id' => $account->id, + 'iban' => $account->iban, + 'currencies' => [], + ]; } // loop expenses. foreach ($spent as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent_sum' => '0', - 'earned_sum' => '0', - 'total_sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent_sum' => '0', + 'earned_sum' => '0', + 'total_sum' => '0', + ]; foreach ($currency['tags'] as $tag) { foreach ($tag['transaction_journals'] as $journal) { $sourceAccountId = $journal['source_account_id']; $report[$sourceAccountId]['currencies'][$currencyId] = $report[$sourceAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; $report[$sourceAccountId]['currencies'][$currencyId]['spent'] = bcadd( $report[$sourceAccountId]['currencies'][$currencyId]['spent'], $journal['amount'] @@ -225,26 +226,26 @@ class TagController extends Controller foreach ($earned as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent_sum' => '0', - 'earned_sum' => '0', - 'total_sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent_sum' => '0', + 'earned_sum' => '0', + 'total_sum' => '0', + ]; foreach ($currency['tags'] as $tag) { foreach ($tag['transaction_journals'] as $journal) { $destinationAccountId = $journal['destination_account_id']; $report[$destinationAccountId]['currencies'][$currencyId] = $report[$destinationAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; $report[$destinationAccountId]['currencies'][$currencyId]['earned'] = bcadd( $report[$destinationAccountId]['currencies'][$currencyId]['earned'], $journal['amount'] @@ -263,10 +264,10 @@ class TagController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -280,21 +281,21 @@ class TagController extends Controller $destinationId = $journal['destination_account_id']; $key = sprintf('%d-%d', $destinationId, $currency['currency_id']); $result[$key] = $result[$key] ?? [ - 'transactions' => 0, - 'sum' => '0', - 'avg' => '0', - 'avg_float' => 0, - 'destination_account_name' => $journal['destination_account_name'], - 'destination_account_id' => $journal['destination_account_id'], - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'transactions' => 0, + 'sum' => '0', + 'avg' => '0', + 'avg_float' => 0, + 'destination_account_name' => $journal['destination_account_name'], + 'destination_account_id' => $journal['destination_account_id'], + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $result[$key]['transactions']++; $result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']); - $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']); - $result[$key]['avg_float'] = (float) $result[$key]['avg']; + $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string)$result[$key]['transactions']); + $result[$key]['avg_float'] = (float)$result[$key]['avg']; } } } @@ -305,20 +306,20 @@ class TagController extends Controller try { $result = view('reports.tag.partials.avg-expenses', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -332,21 +333,21 @@ class TagController extends Controller $sourceId = $journal['source_account_id']; $key = sprintf('%d-%d', $sourceId, $currency['currency_id']); $result[$key] = $result[$key] ?? [ - 'transactions' => 0, - 'sum' => '0', - 'avg' => '0', - 'avg_float' => 0, - 'source_account_name' => $journal['source_account_name'], - 'source_account_id' => $journal['source_account_id'], - 'currency_id' => $currency['currency_id'], - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'transactions' => 0, + 'sum' => '0', + 'avg' => '0', + 'avg_float' => 0, + 'source_account_name' => $journal['source_account_name'], + 'source_account_id' => $journal['source_account_id'], + 'currency_id' => $currency['currency_id'], + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $result[$key]['transactions']++; $result[$key]['sum'] = bcadd($journal['amount'], $result[$key]['sum']); - $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string) $result[$key]['transactions']); - $result[$key]['avg_float'] = (float) $result[$key]['avg']; + $result[$key]['avg'] = bcdiv($result[$key]['sum'], (string)$result[$key]['transactions']); + $result[$key]['avg_float'] = (float)$result[$key]['avg']; } } } @@ -357,20 +358,20 @@ class TagController extends Controller try { $result = view('reports.tag.partials.avg-income', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return Factory|View */ @@ -384,22 +385,22 @@ class TagController extends Controller foreach ($tags as $tag) { $tagId = $tag->id; $report[$tagId] = $report[$tagId] ?? [ - 'name' => $tag->tag, - 'id' => $tag->id, - 'currencies' => [], - ]; + 'name' => $tag->tag, + 'id' => $tag->id, + 'currencies' => [], + ]; } foreach ($spent as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'earned_sum' => '0', - 'spent_sum' => '0', - 'total_sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'earned_sum' => '0', + 'spent_sum' => '0', + 'total_sum' => '0', + ]; /** @var array $tag */ foreach ($currency['tags'] as $tag) { $tagId = $tag['id']; @@ -407,14 +408,14 @@ class TagController extends Controller foreach ($tag['transaction_journals'] as $journal) { // add currency info to report array: $report[$tagId]['currencies'][$currencyId] = $report[$tagId]['currencies'][$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $report[$tagId]['currencies'][$currencyId]['spent'] = bcadd( $report[$tagId]['currencies'][$currencyId]['spent'], $journal['amount'] @@ -433,14 +434,14 @@ class TagController extends Controller foreach ($earned as $currency) { $currencyId = $currency['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - 'earned_sum' => '0', - 'spent_sum' => '0', - 'total_sum' => '0', - ]; + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + 'earned_sum' => '0', + 'spent_sum' => '0', + 'total_sum' => '0', + ]; /** @var array $tag */ foreach ($currency['tags'] as $tag) { $tagId = $tag['id']; @@ -448,14 +449,14 @@ class TagController extends Controller foreach ($tag['transaction_journals'] as $journal) { // add currency info to report array: $report[$tagId]['currencies'][$currencyId] = $report[$tagId]['currencies'][$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currency['currency_id'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_name' => $currency['currency_name'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currency['currency_id'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_name' => $currency['currency_name'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; $report[$tagId]['currencies'][$currencyId]['earned'] = bcadd( $report[$tagId]['currencies'][$currencyId]['earned'], $journal['amount'] @@ -475,10 +476,10 @@ class TagController extends Controller } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -492,7 +493,7 @@ class TagController extends Controller $result[] = [ 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], - 'amount_float' => (float) $journal['amount'], + 'amount_float' => (float)$journal['amount'], 'amount' => $journal['amount'], 'date' => $journal['date']->isoFormat($this->monthAndDayFormat), 'date_sort' => $journal['date']->format('Y-m-d'), @@ -515,20 +516,20 @@ class TagController extends Controller try { $result = view('reports.tag.partials.top-expenses', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; } /** - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -542,7 +543,7 @@ class TagController extends Controller $result[] = [ 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], - 'amount_float' => (float) $journal['amount'], // intentional float. + 'amount_float' => (float)$journal['amount'], // intentional float. 'amount' => $journal['amount'], 'date' => $journal['date']->isoFormat($this->monthAndDayFormat), 'date_sort' => $journal['date']->format('Y-m-d'), @@ -565,10 +566,10 @@ class TagController extends Controller try { $result = view('reports.tag.partials.top-income', compact('result'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + throw new FireflyException($result, 0, $e); } return $result; diff --git a/app/Http/Controllers/ReportController.php b/app/Http/Controllers/ReportController.php index f964375e52..9607e2e107 100644 --- a/app/Http/Controllers/ReportController.php +++ b/app/Http/Controllers/ReportController.php @@ -1,4 +1,5 @@ . */ -/** @noinspection CallableParameterUseCaseInTypeContextInspection */ declare(strict_types=1); namespace FireflyIII\Http\Controllers; @@ -40,6 +40,8 @@ use Illuminate\Routing\Redirector; use Illuminate\Support\Collection; use Illuminate\View\View; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class ReportController. @@ -64,7 +66,7 @@ class ReportController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.reports')); + app('view')->share('title', (string)trans('firefly.reports')); app('view')->share('mainTitleIcon', 'fa-bar-chart'); app('view')->share('subTitleIcon', 'fa-calendar'); $this->helper = app(ReportHelperInterface::class); @@ -78,9 +80,9 @@ class ReportController extends Controller /** * Show audit report. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return Factory|View|string * @@ -89,7 +91,7 @@ class ReportController extends Controller public function auditReport(Collection $accounts, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', (string) trans('firefly.end_after_start_date')); + return view('error')->with('message', (string)trans('firefly.end_after_start_date')); } $this->repository->cleanupBudgets(); @@ -113,10 +115,10 @@ class ReportController extends Controller /** * Show budget report. * - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return Factory|View|string * @@ -125,7 +127,7 @@ class ReportController extends Controller public function budgetReport(Collection $accounts, Collection $budgets, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', (string) trans('firefly.end_after_start_date')); + return view('error')->with('message', (string)trans('firefly.end_after_start_date')); } $this->repository->cleanupBudgets(); @@ -150,10 +152,10 @@ class ReportController extends Controller /** * Show category report. * - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return Factory|View|string * @@ -162,7 +164,7 @@ class ReportController extends Controller public function categoryReport(Collection $accounts, Collection $categories, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', (string) trans('firefly.end_after_start_date')); + return view('error')->with('message', (string)trans('firefly.end_after_start_date')); } $this->repository->cleanupBudgets(); @@ -187,9 +189,9 @@ class ReportController extends Controller /** * Show default report. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return Factory|View|string * @@ -198,7 +200,7 @@ class ReportController extends Controller public function defaultReport(Collection $accounts, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', (string) trans('firefly.end_after_start_date')); + return view('error')->with('message', (string)trans('firefly.end_after_start_date')); } $this->repository->cleanupBudgets(); @@ -223,10 +225,10 @@ class ReportController extends Controller /** * Show account report. * - * @param Collection $accounts - * @param Collection $expense - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $expense + * @param Carbon $start + * @param Carbon $end * * @return string * @throws FireflyException @@ -243,8 +245,10 @@ class ReportController extends Controller 'subTitle', trans( 'firefly.report_double', - ['start' => $start->isoFormat($this->monthAndDayFormat), - 'end' => $end->isoFormat($this->monthAndDayFormat)] + [ + 'start' => $start->isoFormat($this->monthAndDayFormat), + 'end' => $end->isoFormat($this->monthAndDayFormat), + ] ) ); @@ -258,12 +262,12 @@ class ReportController extends Controller /** * Show index. * - * @param AccountRepositoryInterface $repository + * @param AccountRepositoryInterface $repository * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index(AccountRepositoryInterface $repository) { @@ -286,7 +290,7 @@ class ReportController extends Controller $role = sprintf('opt_group_l_%s', $type); } - if ('' === $role || 'opt_group_' === $role) { + if ('opt_group_' === $role) { $role = 'opt_group_defaultAsset'; } $groupedAccounts[trans(sprintf('firefly.%s', $role))][$account->id] = $account; @@ -302,7 +306,7 @@ class ReportController extends Controller /** * Show options for reports. * - * @param string $reportType + * @param string $reportType * * @return JsonResponse * @@ -323,7 +327,7 @@ class ReportController extends Controller /** * Process the submit of report. * - * @param ReportFormRequest $request + * @param ReportFormRequest $request * * @return RedirectResponse|Redirector * @@ -344,37 +348,37 @@ class ReportController extends Controller if (0 === $request->getAccountList()->count()) { Log::debug('Account count is zero'); - session()->flash('error', (string) trans('firefly.select_at_least_one_account')); + session()->flash('error', (string)trans('firefly.select_at_least_one_account')); return redirect(route('reports.index')); } if ('category' === $reportType && 0 === $request->getCategoryList()->count()) { - session()->flash('error', (string) trans('firefly.select_at_least_one_category')); + session()->flash('error', (string)trans('firefly.select_at_least_one_category')); return redirect(route('reports.index')); } if ('budget' === $reportType && 0 === $request->getBudgetList()->count()) { - session()->flash('error', (string) trans('firefly.select_at_least_one_budget')); + session()->flash('error', (string)trans('firefly.select_at_least_one_budget')); return redirect(route('reports.index')); } if ('tag' === $reportType && 0 === $request->getTagList()->count()) { - session()->flash('error', (string) trans('firefly.select_at_least_one_tag')); + session()->flash('error', (string)trans('firefly.select_at_least_one_tag')); return redirect(route('reports.index')); } if ('double' === $reportType && 0 === $request->getDoubleList()->count()) { - session()->flash('error', (string) trans('firefly.select_at_least_one_expense')); + session()->flash('error', (string)trans('firefly.select_at_least_one_expense')); return redirect(route('reports.index')); } if ($request->getEndDate() < $request->getStartDate()) { - return view('error')->with('message', (string) trans('firefly.end_after_start_date')); + return view('error')->with('message', (string)trans('firefly.end_after_start_date')); } $url = match ($reportType) { @@ -392,10 +396,10 @@ class ReportController extends Controller /** * Get a tag report. * - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return Factory|View|string * @throws FireflyException @@ -403,7 +407,7 @@ class ReportController extends Controller public function tagReport(Collection $accounts, Collection $tags, Carbon $start, Carbon $end) { if ($end < $start) { - return view('error')->with('message', (string) trans('firefly.end_after_start_date')); + return view('error')->with('message', (string)trans('firefly.end_after_start_date')); } $this->repository->cleanupBudgets(); diff --git a/app/Http/Controllers/Rule/CreateController.php b/app/Http/Controllers/Rule/CreateController.php index c5095b6274..db1bbe7e0d 100644 --- a/app/Http/Controllers/Rule/CreateController.php +++ b/app/Http/Controllers/Rule/CreateController.php @@ -26,7 +26,6 @@ namespace FireflyIII\Http\Controllers\Rule; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\RuleFormRequest; use FireflyIII\Models\Bill; -use FireflyIII\Models\Rule; use FireflyIII\Models\RuleGroup; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Rule\RuleRepositoryInterface; @@ -45,7 +44,8 @@ use Illuminate\View\View; */ class CreateController extends Controller { - use RuleManagement, ModelInformation; + use RuleManagement; + use ModelInformation; private RuleRepositoryInterface $ruleRepos; @@ -60,7 +60,7 @@ class CreateController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); $this->ruleRepos = app(RuleRepositoryInterface::class); @@ -73,8 +73,8 @@ class CreateController extends Controller /** * Create a new rule. It will be stored under the given $ruleGroup. * - * @param Request $request - * @param RuleGroup|null $ruleGroup + * @param Request $request + * @param RuleGroup|null $ruleGroup * * @return Factory|View */ @@ -88,7 +88,7 @@ class CreateController extends Controller $oldActions = []; // build triggers from query, if present. - $query = (string) $request->get('from_query'); + $query = (string)$request->get('from_query'); if ('' !== $query) { $search = app(SearchInterface::class); $search->parseQuery($query); @@ -112,9 +112,9 @@ class CreateController extends Controller $subTitleIcon = 'fa-clone'; // title depends on whether or not there is a rule group: - $subTitle = (string) trans('firefly.make_new_rule_no_group'); + $subTitle = (string)trans('firefly.make_new_rule_no_group'); if (null !== $ruleGroup) { - $subTitle = (string) trans('firefly.make_new_rule', ['title' => $ruleGroup->title]); + $subTitle = (string)trans('firefly.make_new_rule', ['title' => $ruleGroup->title]); } // flash old data @@ -135,20 +135,20 @@ class CreateController extends Controller /** * Create a new rule. It will be stored under the given $ruleGroup. * - * @param Request $request - * @param Bill $bill + * @param Request $request + * @param Bill $bill * * @return Factory|View */ public function createFromBill(Request $request, Bill $bill) { - $request->session()->flash('info', (string) trans('firefly.instructions_rule_from_bill', ['name' => e($bill->name)])); + $request->session()->flash('info', (string)trans('firefly.instructions_rule_from_bill', ['name' => e($bill->name)])); $this->createDefaultRuleGroup(); $preFilled = [ 'strict' => true, - 'title' => (string) trans('firefly.new_rule_for_bill_title', ['name' => $bill->name]), - 'description' => (string) trans('firefly.new_rule_for_bill_description', ['name' => $bill->name]), + 'title' => (string)trans('firefly.new_rule_for_bill_title', ['name' => $bill->name]), + 'description' => (string)trans('firefly.new_rule_for_bill_description', ['name' => $bill->name]), ]; // make triggers and actions from the bill itself. @@ -168,7 +168,7 @@ class CreateController extends Controller $subTitleIcon = 'fa-clone'; // title depends on whether or not there is a rule group: - $subTitle = (string) trans('firefly.make_new_rule_no_group'); + $subTitle = (string)trans('firefly.make_new_rule_no_group'); // flash old data $request->session()->flash('preFilled', $preFilled); @@ -186,17 +186,17 @@ class CreateController extends Controller } /** - * @param Request $request - * @param TransactionJournal $journal + * @param Request $request + * @param TransactionJournal $journal * * @return Factory|\Illuminate\Contracts\View\View */ public function createFromJournal(Request $request, TransactionJournal $journal) { - $request->session()->flash('info', (string) trans('firefly.instructions_rule_from_journal', ['name' => e($journal->description)])); + $request->session()->flash('info', (string)trans('firefly.instructions_rule_from_journal', ['name' => e($journal->description)])); $subTitleIcon = 'fa-clone'; - $subTitle = (string) trans('firefly.make_new_rule_no_group'); + $subTitle = (string)trans('firefly.make_new_rule_no_group'); // get triggers and actions for journal. $oldTriggers = $this->getTriggersForJournal($journal); @@ -207,8 +207,8 @@ class CreateController extends Controller // collect pre-filled information: $preFilled = [ 'strict' => true, - 'title' => (string) trans('firefly.new_rule_for_journal_title', ['description' => $journal->description]), - 'description' => (string) trans('firefly.new_rule_for_journal_description', ['description' => $journal->description]), + 'title' => (string)trans('firefly.new_rule_for_journal_title', ['description' => $journal->description]), + 'description' => (string)trans('firefly.new_rule_for_journal_description', ['description' => $journal->description]), ]; // restore actions and triggers from old input: @@ -236,12 +236,12 @@ class CreateController extends Controller } /** - * @param Request $request + * @param Request $request * @return JsonResponse */ public function duplicate(Request $request): JsonResponse { - $ruleId = (int) $request->get('id'); + $ruleId = (int)$request->get('id'); $rule = $this->ruleRepos->find($ruleId); if (null !== $rule) { $this->ruleRepos->duplicate($rule); @@ -253,7 +253,7 @@ class CreateController extends Controller /** * Store the new rule. * - * @param RuleFormRequest $request + * @param RuleFormRequest $request * * @return RedirectResponse|Redirector * @@ -261,27 +261,26 @@ class CreateController extends Controller public function store(RuleFormRequest $request) { $data = $request->getRuleData(); + $rule = $this->ruleRepos->store($data); - session()->flash('success', (string) trans('firefly.stored_new_rule', ['title' => $rule->title])); + session()->flash('success', (string)trans('firefly.stored_new_rule', ['title' => $rule->title])); app('preferences')->mark(); // redirect to show bill. - if ('true' === $request->get('return_to_bill') && (int) $request->get('bill_id') > 0) { - return redirect(route('bills.show', [(int) $request->get('bill_id')])); + if ('true' === $request->get('return_to_bill') && (int)$request->get('bill_id') > 0) { + return redirect(route('bills.show', [(int)$request->get('bill_id')])); } // redirect to new bill creation. - if ((int) $request->get('bill_id') > 0) { + if ((int)$request->get('bill_id') > 0) { return redirect($this->getPreviousUrl('bills.create.url')); } $redirect = redirect($this->getPreviousUrl('rules.create.url')); - if (1 === (int) $request->get('create_another')) { - + if (1 === (int)$request->get('create_another')) { session()->put('rules.create.fromStore', true); $redirect = redirect(route('rules.create', [$data['rule_group_id']]))->withInput(); - } return $redirect; diff --git a/app/Http/Controllers/Rule/DeleteController.php b/app/Http/Controllers/Rule/DeleteController.php index 6d8cf7471b..36c4cba793 100644 --- a/app/Http/Controllers/Rule/DeleteController.php +++ b/app/Http/Controllers/Rule/DeleteController.php @@ -49,7 +49,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); $this->ruleRepos = app(RuleRepositoryInterface::class); @@ -62,13 +62,13 @@ class DeleteController extends Controller /** * Delete a given rule. * - * @param Rule $rule + * @param Rule $rule * * @return Factory|View */ public function delete(Rule $rule) { - $subTitle = (string) trans('firefly.delete_rule', ['title' => $rule->title]); + $subTitle = (string)trans('firefly.delete_rule', ['title' => $rule->title]); // put previous url in session $this->rememberPreviousUrl('rules.delete.url'); @@ -79,7 +79,7 @@ class DeleteController extends Controller /** * Actually destroy the given rule. * - * @param Rule $rule + * @param Rule $rule * * @return RedirectResponse */ @@ -88,10 +88,9 @@ class DeleteController extends Controller $title = $rule->title; $this->ruleRepos->destroy($rule); - session()->flash('success', (string) trans('firefly.deleted_rule', ['title' => $title])); + session()->flash('success', (string)trans('firefly.deleted_rule', ['title' => $title])); app('preferences')->mark(); return redirect($this->getPreviousUrl('rules.delete.url')); } - } diff --git a/app/Http/Controllers/Rule/EditController.php b/app/Http/Controllers/Rule/EditController.php index c5a14153d4..5d617a5f7d 100644 --- a/app/Http/Controllers/Rule/EditController.php +++ b/app/Http/Controllers/Rule/EditController.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Rule; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\RuleFormRequest; use FireflyIII\Models\Rule; @@ -44,7 +45,8 @@ use Throwable; */ class EditController extends Controller { - use RuleManagement, RenderPartialViews; + use RuleManagement; + use RenderPartialViews; private RuleRepositoryInterface $ruleRepos; @@ -59,7 +61,7 @@ class EditController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); $this->ruleRepos = app(RuleRepositoryInterface::class); @@ -72,8 +74,8 @@ class EditController extends Controller /** * Edit a rule. * - * @param Request $request - * @param Rule $rule + * @param Request $request + * @param Rule $rule * * @return Factory|View */ @@ -85,7 +87,7 @@ class EditController extends Controller $oldTriggers = []; // build triggers from query, if present. - $query = (string) $request->get('from_query'); + $query = (string)$request->get('from_query'); if ('' !== $query) { $search = app(SearchInterface::class); $search->parseQuery($query); @@ -115,15 +117,15 @@ class EditController extends Controller $hasOldInput = null !== $request->old('_token'); $preFilled = [ - 'active' => $hasOldInput ? (bool) $request->old('active') : $rule->active, - 'stop_processing' => $hasOldInput ? (bool) $request->old('stop_processing') : $rule->stop_processing, - 'strict' => $hasOldInput ? (bool) $request->old('strict') : $rule->strict, + 'active' => $hasOldInput ? (bool)$request->old('active') : $rule->active, + 'stop_processing' => $hasOldInput ? (bool)$request->old('stop_processing') : $rule->stop_processing, + 'strict' => $hasOldInput ? (bool)$request->old('strict') : $rule->strict, ]; // get rule trigger for update / store-journal: $primaryTrigger = $this->ruleRepos->getPrimaryTrigger($rule); - $subTitle = (string) trans('firefly.edit_rule', ['title' => $rule->title]); + $subTitle = (string)trans('firefly.edit_rule', ['title' => $rule->title]); // put previous url in session if not redirect from store (not "return_to_edit"). if (true !== session('rules.edit.fromUpdate')) { @@ -137,20 +139,19 @@ class EditController extends Controller } /** - * @param array $submittedOperators + * @param array $submittedOperators * * @return array */ private function parseFromOperators(array $submittedOperators): array { - // See reference nr. 65 + // TODO this code is duplicate. $operators = config('search.operators'); $renderedEntries = []; $triggers = []; foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - - $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); @@ -168,9 +169,11 @@ class EditController extends Controller 'triggers' => $triggers, ] )->render(); - } catch (Throwable $e) { // @phpstan-ignore-line - Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage())); + } catch (Throwable $e) { + $message = sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage()); + Log::debug($message); Log::error($e->getTraceAsString()); + throw new FireflyException($message, 0, $e); } $index++; } @@ -181,25 +184,24 @@ class EditController extends Controller /** * Update the rule. * - * @param RuleFormRequest $request - * @param Rule $rule + * @param RuleFormRequest $request + * @param Rule $rule * * @return RedirectResponse|Redirector */ public function update(RuleFormRequest $request, Rule $rule) { $data = $request->getRuleData(); + $this->ruleRepos->update($rule, $data); - session()->flash('success', (string) trans('firefly.updated_rule', ['title' => $rule->title])); + session()->flash('success', (string)trans('firefly.updated_rule', ['title' => $rule->title])); app('preferences')->mark(); $redirect = redirect($this->getPreviousUrl('rules.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { session()->put('rules.edit.fromUpdate', true); $redirect = redirect(route('rules.edit', [$rule->id]))->withInput(['return_to_edit' => 1]); - } return $redirect; diff --git a/app/Http/Controllers/Rule/IndexController.php b/app/Http/Controllers/Rule/IndexController.php index ee3f33ed3a..47dd5178db 100644 --- a/app/Http/Controllers/Rule/IndexController.php +++ b/app/Http/Controllers/Rule/IndexController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); $this->ruleGroupRepos = app(RuleGroupRepositoryInterface::class); $this->ruleRepos = app(RuleRepositoryInterface::class); @@ -79,22 +80,22 @@ class IndexController extends Controller } /** - * @param Request $request - * @param Rule $rule - * @param RuleGroup $ruleGroup + * @param Request $request + * @param Rule $rule + * @param RuleGroup $ruleGroup * * @return JsonResponse */ public function moveRule(Request $request, Rule $rule, RuleGroup $ruleGroup): JsonResponse { - $order = (int) $request->get('order'); - $this->ruleRepos->moveRule($rule, $ruleGroup, (int) $order); + $order = (int)$request->get('order'); + $this->ruleRepos->moveRule($rule, $ruleGroup, (int)$order); return response()->json([]); } /** - * @param Rule $rule + * @param Rule $rule * * @return RedirectResponse */ @@ -106,5 +107,4 @@ class IndexController extends Controller return redirect($route); } - } diff --git a/app/Http/Controllers/Rule/SelectController.php b/app/Http/Controllers/Rule/SelectController.php index 999b46343c..ad57565d7e 100644 --- a/app/Http/Controllers/Rule/SelectController.php +++ b/app/Http/Controllers/Rule/SelectController.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Rule; use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Requests\SelectTransactionsRequest; use FireflyIII\Http\Requests\TestRuleFormRequest; @@ -58,7 +59,7 @@ class SelectController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); return $next($request); @@ -69,8 +70,8 @@ class SelectController extends Controller /** * Execute the given rule on a set of existing transactions. * - * @param SelectTransactionsRequest $request - * @param Rule $rule + * @param SelectTransactionsRequest $request + * @param Rule $rule * * @return RedirectResponse */ @@ -97,7 +98,7 @@ class SelectController extends Controller $newRuleEngine->fire(); $resultCount = $newRuleEngine->getResults(); - session()->flash('success', (string) trans_choice('firefly.applied_rule_selection', $resultCount, ['title' => $rule->title])); + session()->flash('success', (string)trans_choice('firefly.applied_rule_selection', $resultCount, ['title' => $rule->title])); return redirect()->route('rules.index'); } @@ -105,7 +106,7 @@ class SelectController extends Controller /** * View to select transactions by a rule. * - * @param Rule $rule + * @param Rule $rule * * @return Factory|View */ @@ -119,7 +120,7 @@ class SelectController extends Controller // does the user have shared accounts? $first = session('first', Carbon::now()->subYear())->format('Y-m-d'); $today = Carbon::now()->format('Y-m-d'); - $subTitle = (string) trans('firefly.apply_rule_selection', ['title' => $rule->title]); + $subTitle = (string)trans('firefly.apply_rule_selection', ['title' => $rule->title]); return view('rules.rule.select-transactions', compact('first', 'today', 'rule', 'subTitle')); } @@ -128,7 +129,7 @@ class SelectController extends Controller * This method allows the user to test a certain set of rule triggers. The rule triggers are passed along * using the URL parameters (GET), and are usually put there using a Javascript thing. * - * @param TestRuleFormRequest $request + * @param TestRuleFormRequest $request * * @return JsonResponse * @@ -136,20 +137,20 @@ class SelectController extends Controller public function testTriggers(TestRuleFormRequest $request): JsonResponse { // build fake rule - $rule = new Rule; - $triggers = new Collection; + $rule = new Rule(); + $triggers = new Collection(); $rule->strict = '1' === $request->get('strict'); // build trigger array from response $textTriggers = $this->getValidTriggerList($request); // warn if nothing. - if (empty($textTriggers)) { - return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]); + if (0 === count($textTriggers)) { + return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]); } foreach ($textTriggers as $textTrigger) { - $trigger = new RuleTrigger; + $trigger = new RuleTrigger(); $trigger->trigger_type = $textTrigger['type']; $trigger->trigger_value = $textTrigger['value']; $triggers->push($trigger); @@ -168,19 +169,19 @@ class SelectController extends Controller // Warn the user if only a subset of transactions is returned $warning = ''; - if (empty($collection)) { - $warning = (string) trans('firefly.warning_no_matching_transactions'); + if (0 === count($collection)) { + $warning = (string)trans('firefly.warning_no_matching_transactions'); } // Return json response $view = 'ERROR, see logs.'; try { $view = view('list.journals-array-tiny', ['groups' => $collection])->render(); - - } catch (Throwable $exception) { // @phpstan-ignore-line + } catch (Throwable $exception) { Log::error(sprintf('Could not render view in testTriggers(): %s', $exception->getMessage())); Log::error($exception->getTraceAsString()); $view = sprintf('Could not render list.journals-tiny: %s', $exception->getMessage()); + throw new FireflyException($view, 0, $exception); } return response()->json(['html' => $view, 'warning' => $warning]); @@ -190,7 +191,7 @@ class SelectController extends Controller * This method allows the user to test a certain set of rule triggers. The rule triggers are grabbed from * the rule itself. * - * @param Rule $rule + * @param Rule $rule * * @return JsonResponse * @@ -199,8 +200,8 @@ class SelectController extends Controller { $triggers = $rule->ruleTriggers; - if (empty($triggers)) { - return response()->json(['html' => '', 'warning' => (string) trans('firefly.warning_no_valid_triggers')]); + if (0 === count($triggers)) { + return response()->json(['html' => '', 'warning' => (string)trans('firefly.warning_no_valid_triggers')]); } // create new rule engine: $newRuleEngine = app(RuleEngineInterface::class); @@ -211,18 +212,19 @@ class SelectController extends Controller $collection = $collection->slice(0, 20); $warning = ''; - if (empty($collection)) { - $warning = (string) trans('firefly.warning_no_matching_transactions'); + if (0 === count($collection)) { + $warning = (string)trans('firefly.warning_no_matching_transactions'); } // Return json response $view = 'ERROR, see logs.'; try { $view = view('list.journals-array-tiny', ['groups' => $collection])->render(); - - } catch (Throwable $exception) { // @phpstan-ignore-line - Log::error(sprintf('Could not render view in testTriggersByRule(): %s', $exception->getMessage())); + } catch (Throwable $exception) { + $message = sprintf('Could not render view in testTriggersByRule(): %s', $exception->getMessage()); + Log::error($message); Log::error($exception->getTraceAsString()); + throw new FireflyException($message, 0, $exception); } return response()->json(['html' => $view, 'warning' => $warning]); diff --git a/app/Http/Controllers/RuleGroup/CreateController.php b/app/Http/Controllers/RuleGroup/CreateController.php index f57446bec5..04df9b1a5f 100644 --- a/app/Http/Controllers/RuleGroup/CreateController.php +++ b/app/Http/Controllers/RuleGroup/CreateController.php @@ -50,7 +50,7 @@ class CreateController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); $this->repository = app(RuleGroupRepositoryInterface::class); @@ -68,7 +68,7 @@ class CreateController extends Controller public function create() { $subTitleIcon = 'fa-clone'; - $subTitle = (string) trans('firefly.make_new_rule_group'); + $subTitle = (string)trans('firefly.make_new_rule_group'); // put previous url in session if not redirect from store (not "create another"). if (true !== session('rule-groups.create.fromStore')) { @@ -82,7 +82,7 @@ class CreateController extends Controller /** * Store the rule group. * - * @param RuleGroupFormRequest $request + * @param RuleGroupFormRequest $request * * @return RedirectResponse|Redirector */ @@ -91,16 +91,14 @@ class CreateController extends Controller $data = $request->getRuleGroupData(); $ruleGroup = $this->repository->store($data); - session()->flash('success', (string) trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])); + session()->flash('success', (string)trans('firefly.created_new_rule_group', ['title' => $ruleGroup->title])); app('preferences')->mark(); $redirect = redirect($this->getPreviousUrl('rule-groups.create.url')); - if (1 === (int) $request->get('create_another')) { - + if (1 === (int)$request->get('create_another')) { session()->put('rule-groups.create.fromStore', true); $redirect = redirect(route('rule-groups.create'))->withInput(); - } return $redirect; diff --git a/app/Http/Controllers/RuleGroup/DeleteController.php b/app/Http/Controllers/RuleGroup/DeleteController.php index fbe0116b7b..eaddb527a3 100644 --- a/app/Http/Controllers/RuleGroup/DeleteController.php +++ b/app/Http/Controllers/RuleGroup/DeleteController.php @@ -51,7 +51,7 @@ class DeleteController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); $this->repository = app(RuleGroupRepositoryInterface::class); @@ -64,13 +64,13 @@ class DeleteController extends Controller /** * Delete a rule group. * - * @param RuleGroup $ruleGroup + * @param RuleGroup $ruleGroup * * @return Factory|View */ public function delete(RuleGroup $ruleGroup) { - $subTitle = (string) trans('firefly.delete_rule_group', ['title' => $ruleGroup->title]); + $subTitle = (string)trans('firefly.delete_rule_group', ['title' => $ruleGroup->title]); // put previous url in session $this->rememberPreviousUrl('rule-groups.delete.url'); @@ -81,8 +81,8 @@ class DeleteController extends Controller /** * Actually destroy the rule group. * - * @param Request $request - * @param RuleGroup $ruleGroup + * @param Request $request + * @param RuleGroup $ruleGroup * * @return RedirectResponse|Redirector */ @@ -91,13 +91,12 @@ class DeleteController extends Controller $title = $ruleGroup->title; /** @var RuleGroup $moveTo */ - $moveTo = $this->repository->find((int) $request->get('move_rules_before_delete')); + $moveTo = $this->repository->find((int)$request->get('move_rules_before_delete')); $this->repository->destroy($ruleGroup, $moveTo); - session()->flash('success', (string) trans('firefly.deleted_rule_group', ['title' => $title])); + session()->flash('success', (string)trans('firefly.deleted_rule_group', ['title' => $title])); app('preferences')->mark(); return redirect($this->getPreviousUrl('rule-groups.delete.url')); } - } diff --git a/app/Http/Controllers/RuleGroup/EditController.php b/app/Http/Controllers/RuleGroup/EditController.php index a6bbf7ce67..b18e66c888 100644 --- a/app/Http/Controllers/RuleGroup/EditController.php +++ b/app/Http/Controllers/RuleGroup/EditController.php @@ -52,7 +52,7 @@ class EditController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); $this->repository = app(RuleGroupRepositoryInterface::class); @@ -65,18 +65,18 @@ class EditController extends Controller /** * Edit a rule group. * - * @param Request $request - * @param RuleGroup $ruleGroup + * @param Request $request + * @param RuleGroup $ruleGroup * * @return Factory|View */ public function edit(Request $request, RuleGroup $ruleGroup) { - $subTitle = (string) trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]); + $subTitle = (string)trans('firefly.edit_rule_group', ['title' => $ruleGroup->title]); $hasOldInput = null !== $request->old('_token'); $preFilled = [ - 'active' => $hasOldInput ? (bool) $request->old('active') : $ruleGroup->active, + 'active' => $hasOldInput ? (bool)$request->old('active') : $ruleGroup->active, ]; // put previous url in session if not redirect from store (not "return_to_edit"). if (true !== session('rule-groups.edit.fromUpdate')) { @@ -91,26 +91,26 @@ class EditController extends Controller /** * Move a rule group in either direction. * - * @param Request $request + * @param Request $request * * @return JsonResponse */ public function moveGroup(Request $request): JsonResponse { - $groupId = (int) $request->get('id'); + $groupId = (int)$request->get('id'); $ruleGroup = $this->repository->find($groupId); if (null !== $ruleGroup) { $direction = $request->get('direction'); if ('down' === $direction) { $maxOrder = $this->repository->maxOrder(); - $order = (int) $ruleGroup->order; + $order = (int)$ruleGroup->order; if ($order < $maxOrder) { $newOrder = $order + 1; $this->repository->setOrder($ruleGroup, $newOrder); } } if ('up' === $direction) { - $order = (int) $ruleGroup->order; + $order = (int)$ruleGroup->order; if ($order > 1) { $newOrder = $order - 1; $this->repository->setOrder($ruleGroup, $newOrder); @@ -123,8 +123,8 @@ class EditController extends Controller /** * Update the rule group. * - * @param RuleGroupFormRequest $request - * @param RuleGroup $ruleGroup + * @param RuleGroupFormRequest $request + * @param RuleGroup $ruleGroup * * @return $this|RedirectResponse|Redirector */ @@ -133,24 +133,21 @@ class EditController extends Controller $data = [ 'title' => $request->convertString('title'), 'description' => $request->stringWithNewlines('description'), - 'active' => 1 === (int) $request->input('active'), + 'active' => 1 === (int)$request->input('active'), ]; $this->repository->update($ruleGroup, $data); - session()->flash('success', (string) trans('firefly.updated_rule_group', ['title' => $ruleGroup->title])); + session()->flash('success', (string)trans('firefly.updated_rule_group', ['title' => $ruleGroup->title])); app('preferences')->mark(); $redirect = redirect($this->getPreviousUrl('rule-groups.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { session()->put('rule-groups.edit.fromUpdate', true); $redirect = redirect(route('rule-groups.edit', [$ruleGroup->id]))->withInput(['return_to_edit' => 1]); - } // redirect to previous URL. return $redirect; } - } diff --git a/app/Http/Controllers/RuleGroup/ExecutionController.php b/app/Http/Controllers/RuleGroup/ExecutionController.php index 39d0bc89b8..14a75e5ea1 100644 --- a/app/Http/Controllers/RuleGroup/ExecutionController.php +++ b/app/Http/Controllers/RuleGroup/ExecutionController.php @@ -53,7 +53,7 @@ class ExecutionController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.rules')); + app('view')->share('title', (string)trans('firefly.rules')); app('view')->share('mainTitleIcon', 'fa-random'); $this->ruleGroupRepository = app(RuleGroupRepositoryInterface::class); @@ -66,8 +66,8 @@ class ExecutionController extends Controller /** * Execute the given rulegroup on a set of existing transactions. * - * @param SelectTransactionsRequest $request - * @param RuleGroup $ruleGroup + * @param SelectTransactionsRequest $request + * @param RuleGroup $ruleGroup * * @return RedirectResponse * @throws Exception @@ -95,7 +95,7 @@ class ExecutionController extends Controller $newRuleEngine->fire(); // Tell the user that the job is queued - session()->flash('success', (string) trans('firefly.applied_rule_group_selection', ['title' => $ruleGroup->title])); + session()->flash('success', (string)trans('firefly.applied_rule_group_selection', ['title' => $ruleGroup->title])); return redirect()->route('rules.index'); } @@ -103,7 +103,7 @@ class ExecutionController extends Controller /** * Select transactions to apply the group on. * - * @param RuleGroup $ruleGroup + * @param RuleGroup $ruleGroup * * @return Factory|View */ @@ -111,7 +111,7 @@ class ExecutionController extends Controller { $first = session('first')->format('Y-m-d'); $today = Carbon::now()->format('Y-m-d'); - $subTitle = (string) trans('firefly.apply_rule_group_selection', ['title' => $ruleGroup->title]); + $subTitle = (string)trans('firefly.apply_rule_group_selection', ['title' => $ruleGroup->title]); return view('rules.rule-group.select-transactions', compact('first', 'today', 'ruleGroup', 'subTitle')); } diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index c532600228..03030e264f 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -1,4 +1,5 @@ middleware( static function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-search'); - app('view')->share('title', (string) trans('firefly.search')); + app('view')->share('title', (string)trans('firefly.search')); return $next($request); } @@ -56,8 +58,8 @@ class SearchController extends Controller /** * Do the search. * - * @param Request $request - * @param SearchInterface $searcher + * @param Request $request + * @param SearchInterface $searcher * * @return Factory|View */ @@ -68,9 +70,9 @@ class SearchController extends Controller if (is_array($request->get('search'))) { $fullQuery = ''; } - $fullQuery = (string) $fullQuery; - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); - $ruleId = (int) $request->get('rule'); + $fullQuery = (string)$fullQuery; + $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); + $ruleId = (int)$request->get('rule'); $ruleChanged = false; // find rule, check if query is different, offer to update. @@ -89,7 +91,7 @@ class SearchController extends Controller $query = $searcher->getWordsAsString(); $operators = $searcher->getOperators(); $invalidOperators = $searcher->getInvalidOperators(); - $subTitle = (string) trans('breadcrumbs.search_result', ['query' => $fullQuery]); + $subTitle = (string)trans('breadcrumbs.search_result', ['query' => $fullQuery]); return view('search.index', compact('query', 'operators', 'page', 'rule', 'fullQuery', 'subTitle', 'ruleId', 'ruleChanged', 'invalidOperators')); } @@ -97,15 +99,15 @@ class SearchController extends Controller /** * JSON request that does the work. * - * @param Request $request - * @param SearchInterface $searcher + * @param Request $request + * @param SearchInterface $searcher * * @return JsonResponse */ public function search(Request $request, SearchInterface $searcher): JsonResponse { - $fullQuery = (string) $request->get('query'); - $page = 0 === (int) $request->get('page') ? 1 : (int) $request->get('page'); + $fullQuery = (string)$request->get('query'); + $page = 0 === (int)$request->get('page') ? 1 : (int)$request->get('page'); $searcher->parseQuery($fullQuery); @@ -114,15 +116,15 @@ class SearchController extends Controller $hasPages = $groups->hasPages(); $searchTime = round($searcher->searchTime(), 3); // in seconds $parameters = ['search' => $fullQuery]; - $url = route('search.index') . '?' . http_build_query($parameters); + $url = route('search.index').'?'.http_build_query($parameters); $groups->setPath($url); try { $html = view('search.search', compact('groups', 'hasPages', 'searchTime'))->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render search.search: %s', $e->getMessage())); $html = 'Could not render view.'; + throw new FireflyException($html, 0, $e); } return response()->json(['count' => $groups->count(), 'html' => $html]); diff --git a/app/Http/Controllers/System/HealthcheckController.php b/app/Http/Controllers/System/HealthcheckController.php index dd5c24cf82..fef70b5b05 100644 --- a/app/Http/Controllers/System/HealthcheckController.php +++ b/app/Http/Controllers/System/HealthcheckController.php @@ -1,4 +1,5 @@ [], 'firefly-iii:fix-frontpage-accounts' => [], 'firefly-iii:fix-ibans' => [], + 'firefly-iii:upgrade-group-information' => [], // final command to set latest version in DB 'firefly-iii:set-latest-version' => ['--james-is-cool' => true], @@ -128,22 +128,22 @@ class InstallController extends Controller public function index() { // index will set FF3 version. - app('fireflyconfig')->set('ff3_version', (string) config('firefly.version')); + app('fireflyconfig')->set('ff3_version', (string)config('firefly.version')); // set new DB version. - app('fireflyconfig')->set('db_version', (int) config('firefly.db_version')); + app('fireflyconfig')->set('db_version', (int)config('firefly.db_version')); return view('install.index'); } /** - * @param Request $request + * @param Request $request * * @return JsonResponse */ public function runCommand(Request $request): JsonResponse { - $requestIndex = (int) $request->get('index'); + $requestIndex = (int)$request->get('index'); $response = [ 'hasNextCommand' => false, 'done' => true, @@ -157,7 +157,7 @@ class InstallController extends Controller $index = 0; /** * @var string $command - * @var array $args + * @var array $args */ foreach ($this->upgradeCommands as $command => $args) { Log::debug(sprintf('Current command is "%s", index is %d', $command, $index)); @@ -166,7 +166,17 @@ class InstallController extends Controller $index++; continue; } - $result = $this->executeCommand($command, $args); + try { + $result = $this->executeCommand($command, $args); + } catch (FireflyException $e) { + Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); + if (strpos($e->getMessage(), 'open_basedir restriction in effect')) { + $this->lastError = self::BASEDIR_ERROR; + } + $result = false; + $this->lastError = sprintf('%s %s', self::OTHER_ERROR, $e->getMessage()); + } if (false === $result) { $response['errorMessage'] = $this->lastError; $response['error'] = true; @@ -183,9 +193,9 @@ class InstallController extends Controller } /** - * @param string $command - * @param array $args - * + * @param string $command + * @param array $args + * @throws FireflyException * @return bool */ private function executeCommand(string $command, array $args): bool @@ -199,20 +209,11 @@ class InstallController extends Controller Artisan::call($command, $args); Log::debug(Artisan::output()); } - } catch (Exception $e) { // @phpstan-ignore-line - Log::error($e->getMessage()); - Log::error($e->getTraceAsString()); - if (strpos($e->getMessage(), 'open_basedir restriction in effect')) { - $this->lastError = self::BASEDIR_ERROR; - - return false; - } - $this->lastError = sprintf('%s %s', self::OTHER_ERROR, $e->getMessage()); - - return false; + } catch (Exception $e) { // intentional generic exception + throw new FireflyException($e->getMessage(), 0, $e); } // clear cache as well. - Cache::clear(); // @phpstan-ignore-line + Cache::clear(); Preferences::mark(); return true; @@ -230,7 +231,7 @@ class InstallController extends Controller if (class_exists(LegacyRSA::class)) { // PHP 7 Log::info('Will run PHP7 code.'); - $keys = (new LegacyRSA)->createKey(4096); + $keys = (new LegacyRSA())->createKey(4096); } if (!class_exists(LegacyRSA::class)) { diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php index 57e7a6684c..ce12403dc1 100644 --- a/app/Http/Controllers/TagController.php +++ b/app/Http/Controllers/TagController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.tags')); + app('view')->share('title', (string)trans('firefly.tags')); app('view')->share('mainTitleIcon', 'fa-tag'); $this->attachmentsHelper = app(AttachmentHelperInterface::class); @@ -74,7 +77,7 @@ class TagController extends Controller */ public function create(Request $request) { - $subTitle = (string) trans('firefly.new_tag'); + $subTitle = (string)trans('firefly.new_tag'); $subTitleIcon = 'fa-tag'; // location info: @@ -100,13 +103,13 @@ class TagController extends Controller /** * Delete a tag. * - * @param Tag $tag + * @param Tag $tag * * @return Factory|View */ public function delete(Tag $tag) { - $subTitle = (string) trans('breadcrumbs.delete_tag', ['tag' => $tag->tag]); + $subTitle = (string)trans('breadcrumbs.delete_tag', ['tag' => $tag->tag]); // put previous url in session $this->rememberPreviousUrl('tags.delete.url'); @@ -114,34 +117,16 @@ class TagController extends Controller return view('tags.delete', compact('tag', 'subTitle')); } - /** - * Destroy a tag. - * - * @param Tag $tag - * - * @return RedirectResponse - */ - public function destroy(Tag $tag): RedirectResponse - { - $tagName = $tag->tag; - $this->repository->destroy($tag); - - session()->flash('success', (string) trans('firefly.deleted_tag', ['tag' => $tagName])); - app('preferences')->mark(); - - return redirect($this->getPreviousUrl('tags.delete.url')); - } - /** * Edit a tag. * - * @param Tag $tag + * @param Tag $tag * * @return Factory|View */ public function edit(Tag $tag) { - $subTitle = (string) trans('firefly.edit_tag', ['tag' => $tag->tag]); + $subTitle = (string)trans('firefly.edit_tag', ['tag' => $tag->tag]); $subTitleIcon = 'fa-tag'; $location = $this->repository->getLocation($tag); @@ -170,7 +155,7 @@ class TagController extends Controller /** * Edit a tag. * - * @param TagRepositoryInterface $repository + * @param TagRepositoryInterface $repository * * @return Factory|View */ @@ -202,51 +187,72 @@ class TagController extends Controller { $tags = $request->get('tags'); if (null === $tags || !is_array($tags)) { - session()->flash('info', (string) trans('firefly.select_tags_to_delete')); + session()->flash('info', (string)trans('firefly.select_tags_to_delete')); return redirect(route('tags.index')); } $count = 0; foreach ($tags as $tagId) { - $tagId = (int) $tagId; + $tagId = (int)$tagId; $tag = $this->repository->find($tagId); if (null !== $tag) { $this->repository->destroy($tag); $count++; } } - session()->flash('success', (string) trans_choice('firefly.deleted_x_tags', $count)); + session()->flash('success', (string)trans_choice('firefly.deleted_x_tags', $count)); return redirect(route('tags.index')); } + /** + * Destroy a tag. + * + * @param Tag $tag + * + * @return RedirectResponse + */ + public function destroy(Tag $tag): RedirectResponse + { + $tagName = $tag->tag; + $this->repository->destroy($tag); + + session()->flash('success', (string)trans('firefly.deleted_tag', ['tag' => $tagName])); + app('preferences')->mark(); + + return redirect($this->getPreviousUrl('tags.delete.url')); + } + /** * Show a single tag. * - * @param Request $request - * @param Tag $tag - * @param Carbon|null $start - * @param Carbon|null $end + * @param Request $request + * @param Tag $tag + * @param Carbon|null $start + * @param Carbon|null $end * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function show(Request $request, Tag $tag, Carbon $start = null, Carbon $end = null) { // default values: $subTitleIcon = 'fa-tag'; - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $start = $start ?? session('start'); $end = $end ?? session('end'); $location = $this->repository->getLocation($tag); $attachments = $this->repository->getAttachments($tag); $subTitle = trans( 'firefly.journals_in_period_for_tag', - ['tag' => $tag->tag, 'start' => $start->isoFormat($this->monthAndDayFormat), - 'end' => $end->isoFormat($this->monthAndDayFormat),] + [ + 'tag' => $tag->tag, + 'start' => $start->isoFormat($this->monthAndDayFormat), + 'end' => $end->isoFormat($this->monthAndDayFormat), + ] ); $startPeriod = $this->repository->firstUseDate($tag); @@ -270,22 +276,22 @@ class TagController extends Controller /** * Show a single tag over all time. * - * @param Request $request - * @param Tag $tag + * @param Request $request + * @param Tag $tag * * @return Factory|View * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function showAll(Request $request, Tag $tag) { // default values: $subTitleIcon = 'fa-tag'; - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $periods = []; - $subTitle = (string) trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]); + $subTitle = (string)trans('firefly.all_journals_for_tag', ['tag' => $tag->tag]); $start = $this->repository->firstUseDate($tag) ?? today(config('app.timezone')); $end = $this->repository->lastUseDate($tag) ?? today(config('app.timezone')); $attachments = $this->repository->getAttachments($tag); @@ -305,7 +311,7 @@ class TagController extends Controller /** * Store a tag. * - * @param TagFormRequest $request + * @param TagFormRequest $request * * @return RedirectResponse */ @@ -317,7 +323,7 @@ class TagController extends Controller $result = $this->repository->store($data); Log::debug('Data after storage', $result->toArray()); - session()->flash('success', (string) trans('firefly.created_tag', ['tag' => $data['tag']])); + session()->flash('success', (string)trans('firefly.created_tag', ['tag' => $data['tag']])); app('preferences')->mark(); // store attachment(s): @@ -327,19 +333,17 @@ class TagController extends Controller $this->attachmentsHelper->saveAttachmentsForModel($result, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachmentsHelper->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachmentsHelper->getMessages()->get('attachments')); } $redirect = redirect($this->getPreviousUrl('tags.create.url')); - if (1 === (int) $request->get('create_another')) { - + if (1 === (int)$request->get('create_another')) { session()->put('tags.create.fromStore', true); $redirect = redirect(route('tags.create'))->withInput(); - } return $redirect; @@ -348,8 +352,8 @@ class TagController extends Controller /** * Update a tag. * - * @param TagFormRequest $request - * @param Tag $tag + * @param TagFormRequest $request + * @param Tag $tag * * @return RedirectResponse */ @@ -358,7 +362,7 @@ class TagController extends Controller $data = $request->collectTagData(); $tag = $this->repository->update($tag, $data); - session()->flash('success', (string) trans('firefly.updated_tag', ['tag' => $data['tag']])); + session()->flash('success', (string)trans('firefly.updated_tag', ['tag' => $data['tag']])); app('preferences')->mark(); // store new attachment(s): @@ -368,19 +372,17 @@ class TagController extends Controller $this->attachmentsHelper->saveAttachmentsForModel($tag, $files); } if (null !== $files && auth()->user()->hasRole('demo')) { - session()->flash('info', (string) trans('firefly.no_att_demo_user')); + session()->flash('info', (string)trans('firefly.no_att_demo_user')); } if (count($this->attachmentsHelper->getMessages()->get('attachments')) > 0) { $request->session()->flash('info', $this->attachmentsHelper->getMessages()->get('attachments')); } $redirect = redirect($this->getPreviousUrl('tags.edit.url')); - if (1 === (int) $request->get('return_to_edit')) { - + if (1 === (int)$request->get('return_to_edit')) { session()->put('tags.edit.fromUpdate', true); $redirect = redirect(route('tags.edit', [$tag->id]))->withInput(['return_to_edit' => 1]); - } // redirect to previous URL. diff --git a/app/Http/Controllers/Transaction/BulkController.php b/app/Http/Controllers/Transaction/BulkController.php index 413299ad1c..ea63afab36 100644 --- a/app/Http/Controllers/Transaction/BulkController.php +++ b/app/Http/Controllers/Transaction/BulkController.php @@ -57,7 +57,7 @@ class BulkController extends Controller $this->middleware( function ($request, $next) { $this->repository = app(JournalRepositoryInterface::class); - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); return $next($request); @@ -68,15 +68,15 @@ class BulkController extends Controller /** * Edit a set of journals in bulk. * - * See reference nr. 47 + * TODO user wont be able to tell if the journal is part of a split. * - * @param array $journals + * @param array $journals * * @return Factory|View */ public function edit(array $journals) { - $subTitle = (string) trans('firefly.mass_bulk_journals'); + $subTitle = (string)trans('firefly.mass_bulk_journals'); $this->rememberPreviousUrl('transactions.bulk-edit.url'); @@ -93,7 +93,7 @@ class BulkController extends Controller /** * Update all journals. * - * @param BulkEditJournalRequest $request + * @param BulkEditJournalRequest $request * * @return Application|RedirectResponse|Redirector */ @@ -101,14 +101,14 @@ class BulkController extends Controller { $journalIds = $request->get('journals'); $journalIds = is_array($journalIds) ? $journalIds : []; - $ignoreCategory = 1 === (int) $request->get('ignore_category'); - $ignoreBudget = 1 === (int) $request->get('ignore_budget'); + $ignoreCategory = 1 === (int)$request->get('ignore_category'); + $ignoreBudget = 1 === (int)$request->get('ignore_budget'); $tagsAction = $request->get('tags_action'); - $collection = new Collection; + $collection = new Collection(); $count = 0; foreach ($journalIds as $journalId) { - $journalId = (int) $journalId; + $journalId = (int)$journalId; $journal = $this->repository->find($journalId); if (null !== $journal) { $resultA = $this->updateJournalBudget($journal, $ignoreBudget, $request->integer('budget_id')); @@ -124,20 +124,20 @@ class BulkController extends Controller // run rules on changed journals: /** @var TransactionJournal $journal */ foreach ($collection as $journal) { - event(new UpdatedTransactionGroup($journal->transactionGroup)); + event(new UpdatedTransactionGroup($journal->transactionGroup, true, true)); } app('preferences')->mark(); - $request->session()->flash('success', (string) trans_choice('firefly.mass_edited_transactions_success', $count)); + $request->session()->flash('success', (string)trans_choice('firefly.mass_edited_transactions_success', $count)); // redirect to previous URL: return redirect($this->getPreviousUrl('transactions.bulk-edit.url')); } /** - * @param TransactionJournal $journal - * @param bool $ignoreUpdate - * @param int $budgetId + * @param TransactionJournal $journal + * @param bool $ignoreUpdate + * @param int $budgetId * * @return bool */ @@ -153,9 +153,9 @@ class BulkController extends Controller } /** - * @param TransactionJournal $journal - * @param string $action - * @param array $tags + * @param TransactionJournal $journal + * @param string $action + * @param array $tags * * @return bool */ @@ -175,9 +175,9 @@ class BulkController extends Controller } /** - * @param TransactionJournal $journal - * @param bool $ignoreUpdate - * @param string $category + * @param TransactionJournal $journal + * @param bool $ignoreUpdate + * @param string $category * * @return bool */ diff --git a/app/Http/Controllers/Transaction/ConvertController.php b/app/Http/Controllers/Transaction/ConvertController.php index 6fe58158ac..b64474d184 100644 --- a/app/Http/Controllers/Transaction/ConvertController.php +++ b/app/Http/Controllers/Transaction/ConvertController.php @@ -1,4 +1,5 @@ repository = app(JournalRepositoryInterface::class); $this->accountRepository = app(AccountRepositoryInterface::class); - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); return $next($request); @@ -81,8 +82,8 @@ class ConvertController extends Controller /** * Show overview of a to be converted transaction. * - * @param TransactionType $destinationType - * @param TransactionGroup $group + * @param TransactionType $destinationType + * @param TransactionGroup $group * * @return RedirectResponse|Redirector|Factory|View * @throws Exception @@ -103,7 +104,7 @@ class ConvertController extends Controller $groupTitle = $group->title ?? $first->description; $groupArray = $transformer->transformObject($group); - $subTitle = (string) trans('firefly.convert_to_' . $destinationType->type, ['description' => $groupTitle]); + $subTitle = (string)trans('firefly.convert_to_'.$destinationType->type, ['description' => $groupTitle]); $subTitleIcon = 'fa-exchange'; // get a list of asset accounts and liabilities and stuff, in various combinations: @@ -119,7 +120,7 @@ class ConvertController extends Controller if ($sourceType->type === $destinationType->type) { // cannot convert to its own type. Log::debug('This is already a transaction of the expected type..'); - session()->flash('info', (string) trans('firefly.convert_is_already_type_' . $destinationType->type)); + session()->flash('info', (string)trans('firefly.convert_is_already_type_'.$destinationType->type)); return redirect(route('transactions.show', [$group->id])); } @@ -156,7 +157,7 @@ class ConvertController extends Controller // group accounts: /** @var Account $account */ foreach ($accountList as $account) { - $role = (string) $this->accountRepository->getMetaValue($account, 'account_role'); + $role = (string)$this->accountRepository->getMetaValue($account, 'account_role'); $name = $account->name; if ('' === $role) { $role = 'no_account_type'; @@ -164,19 +165,17 @@ class ConvertController extends Controller // maybe it's a liability thing: if (in_array($account->accountType->type, $liabilityTypes, true)) { - $role = 'l_' . $account->accountType->type; + $role = 'l_'.$account->accountType->type; } if (AccountType::CASH === $account->accountType->type) { - $role = 'cash_account'; $name = sprintf('(%s)', trans('firefly.cash')); - } if (AccountType::REVENUE === $account->accountType->type) { $role = 'revenue_account'; } - $key = (string) trans('firefly.opt_group_' . $role); + $key = (string)trans('firefly.opt_group_'.$role); $grouped[$key][$account->id] = $name; } @@ -197,7 +196,7 @@ class ConvertController extends Controller // group accounts: /** @var Account $account */ foreach ($accountList as $account) { - $role = (string) $this->accountRepository->getMetaValue($account, 'account_role'); + $role = (string)$this->accountRepository->getMetaValue($account, 'account_role'); $name = $account->name; if ('' === $role) { $role = 'no_account_type'; @@ -205,19 +204,17 @@ class ConvertController extends Controller // maybe it's a liability thing: if (in_array($account->accountType->type, $liabilityTypes, true)) { - $role = 'l_' . $account->accountType->type; + $role = 'l_'.$account->accountType->type; } if (AccountType::CASH === $account->accountType->type) { - $role = 'cash_account'; $name = sprintf('(%s)', trans('firefly.cash')); - } if (AccountType::EXPENSE === $account->accountType->type) { $role = 'expense_account'; } - $key = (string) trans('firefly.opt_group_' . $role); + $key = (string)trans('firefly.opt_group_'.$role); $grouped[$key][$account->id] = $name; } @@ -239,9 +236,9 @@ class ConvertController extends Controller foreach ($accountList as $account) { $balance = app('steam')->balance($account, today()); $currency = $this->accountRepository->getAccountCurrency($account) ?? $defaultCurrency; - $role = 'l_' . $account->accountType->type; - $key = (string) trans('firefly.opt_group_' . $role); - $grouped[$key][$account->id] = $account->name . ' (' . app('amount')->formatAnything($currency, $balance, false) . ')'; + $role = 'l_'.$account->accountType->type; + $key = (string)trans('firefly.opt_group_'.$role); + $grouped[$key][$account->id] = $account->name.' ('.app('amount')->formatAnything($currency, $balance, false).')'; } return $grouped; @@ -262,13 +259,13 @@ class ConvertController extends Controller foreach ($accountList as $account) { $balance = app('steam')->balance($account, today()); $currency = $this->accountRepository->getAccountCurrency($account) ?? $defaultCurrency; - $role = (string) $this->accountRepository->getMetaValue($account, 'account_role'); + $role = (string)$this->accountRepository->getMetaValue($account, 'account_role'); if ('' === $role) { $role = 'no_account_type'; } - $key = (string) trans('firefly.opt_group_' . $role); - $grouped[$key][$account->id] = $account->name . ' (' . app('amount')->formatAnything($currency, $balance, false) . ')'; + $key = (string)trans('firefly.opt_group_'.$role); + $grouped[$key][$account->id] = $account->name.' ('.app('amount')->formatAnything($currency, $balance, false).')'; } return $grouped; @@ -277,9 +274,9 @@ class ConvertController extends Controller /** * Do the conversion. * - * @param Request $request - * @param TransactionType $destinationType - * @param TransactionGroup $group + * @param Request $request + * @param TransactionType $destinationType + * @param TransactionGroup $group * * @return RedirectResponse|Redirector * @@ -305,16 +302,16 @@ class ConvertController extends Controller // correct transfers: $group->refresh(); - session()->flash('success', (string) trans('firefly.converted_to_' . $destinationType->type)); - event(new UpdatedTransactionGroup($group)); + session()->flash('success', (string)trans('firefly.converted_to_'.$destinationType->type)); + event(new UpdatedTransactionGroup($group, true, true)); return redirect(route('transactions.show', [$group->id])); } /** - * @param TransactionJournal $journal - * @param TransactionType $transactionType - * @param array $data + * @param TransactionJournal $journal + * @param TransactionType $transactionType + * @param array $data * * @return TransactionJournal * @throws FireflyException @@ -332,10 +329,10 @@ class ConvertController extends Controller $destinationName = $data['destination_name'][$journal->id] ?? null; // double check its not an empty string. - $sourceId = '' === $sourceId || null === $sourceId ? null : (int) $sourceId; - $sourceName = '' === $sourceName ? null : (string) $sourceName; - $destinationId = '' === $destinationId || null === $destinationId ? null : (int) $destinationId; - $destinationName = '' === $destinationName ? null : (string) $destinationName; + $sourceId = '' === $sourceId || null === $sourceId ? null : (int)$sourceId; + $sourceName = '' === $sourceName ? null : (string)$sourceName; + $destinationId = '' === $destinationId || null === $destinationId ? null : (int)$destinationId; + $destinationName = '' === $destinationName ? null : (string)$destinationName; $validSource = $validator->validateSource(['id' => $sourceId, 'name' => $sourceName,]); $validDestination = $validator->validateDestination(['id' => $destinationId, 'name' => $destinationName,]); @@ -346,7 +343,7 @@ class ConvertController extends Controller throw new FireflyException(sprintf(trans('firefly.convert_invalid_destination'), $journal->id)); } - // See reference nr. 50 + // TODO typeOverrule: the account validator may have another opinion on the transaction type. $update = [ 'source_id' => $sourceId, diff --git a/app/Http/Controllers/Transaction/CreateController.php b/app/Http/Controllers/Transaction/CreateController.php index becc4d6614..cdca03ae74 100644 --- a/app/Http/Controllers/Transaction/CreateController.php +++ b/app/Http/Controllers/Transaction/CreateController.php @@ -33,6 +33,9 @@ use Illuminate\Contracts\View\Factory; use Illuminate\Contracts\View\View; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; +use JsonException; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class CreateController @@ -52,7 +55,7 @@ class CreateController extends Controller $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); $this->repository = app(TransactionGroupRepositoryInterface::class); @@ -62,13 +65,13 @@ class CreateController extends Controller } /** - * @param Request $request + * @param Request $request * * @return JsonResponse */ public function cloneGroup(Request $request): JsonResponse { - $groupId = (int) $request->get('id'); + $groupId = (int)$request->get('id'); if (0 !== $groupId) { $group = $this->repository->find($groupId); if (null !== $group) { @@ -77,7 +80,7 @@ class CreateController extends Controller $newGroup = $service->cloneGroup($group); // event! - event(new StoredTransactionGroup($newGroup)); + event(new StoredTransactionGroup($newGroup, true, true)); app('preferences')->mark(); @@ -96,26 +99,26 @@ class CreateController extends Controller /** * Create a new transaction group. * - * @param string|null $objectType + * @param string|null $objectType * * @return Factory|View * @throws FireflyException - * @throws \JsonException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws JsonException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function create(?string $objectType) { app('preferences')->mark(); - $sourceId = (int) request()->get('source'); - $destinationId = (int) request()->get('destination'); + $sourceId = (int)request()->get('source'); + $destinationId = (int)request()->get('destination'); /** @var AccountRepositoryInterface $accountRepository */ $accountRepository = app(AccountRepositoryInterface::class); $cash = $accountRepository->getCashAccount(); $preFilled = session()->has('preFilled') ? session('preFilled') : []; - $subTitle = (string) trans(sprintf('breadcrumbs.create_%s', strtolower((string) $objectType))); + $subTitle = (string)trans(sprintf('breadcrumbs.create_%s', strtolower((string)$objectType))); $subTitleIcon = 'fa-plus'; $optionalFields = app('preferences')->get('transaction_journal_optional_fields', [])->data; $allowedOpposingTypes = config('firefly.allowed_opposing_types'); diff --git a/app/Http/Controllers/Transaction/DeleteController.php b/app/Http/Controllers/Transaction/DeleteController.php index a540dcd2e9..1daa260bc9 100644 --- a/app/Http/Controllers/Transaction/DeleteController.php +++ b/app/Http/Controllers/Transaction/DeleteController.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Transaction; -use FireflyIII\Events\DestroyedTransactionGroup; use FireflyIII\Events\UpdatedAccount; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\Account; @@ -57,7 +56,7 @@ class DeleteController extends Controller // translations: $this->middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); $this->repository = app(TransactionGroupRepositoryInterface::class); @@ -70,7 +69,7 @@ class DeleteController extends Controller /** * Shows the form that allows a user to delete a transaction journal. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return Factory|View|Redirector|RedirectResponse */ @@ -84,11 +83,11 @@ class DeleteController extends Controller $journal = $group->transactionJournals->first(); if (null === $journal) { - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } $objectType = strtolower($journal->transaction_type_type ?? $journal->transactionType->type); - $subTitle = (string) trans('firefly.delete_' . $objectType, ['description' => $group->title ?? $journal->description]); - $previous = app('steam')->getSafePreviousUrl(route('index')); + $subTitle = (string)trans('firefly.delete_'.$objectType, ['description' => $group->title ?? $journal->description]); + $previous = app('steam')->getSafePreviousUrl(); // put previous url in session Log::debug('Will try to remember previous URL'); $this->rememberPreviousUrl('transactions.delete.url'); @@ -99,7 +98,7 @@ class DeleteController extends Controller /** * Actually destroys the journal. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return RedirectResponse */ @@ -111,20 +110,20 @@ class DeleteController extends Controller $journal = $group->transactionJournals->first(); if (null === $journal) { - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } $objectType = strtolower($journal->transaction_type_type ?? $journal->transactionType->type); - session()->flash('success', (string) trans('firefly.deleted_' . strtolower($objectType), ['description' => $group->title ?? $journal->description])); + session()->flash('success', (string)trans('firefly.deleted_'.strtolower($objectType), ['description' => $group->title ?? $journal->description])); // grab asset account(s) from group: $accounts = []; /** @var TransactionJournal $journal */ - foreach($group->transactionJournals as $journal) { + foreach ($group->transactionJournals as $journal) { /** @var Transaction $transaction */ - foreach($journal->transactions as $transaction) { + foreach ($journal->transactions as $transaction) { $type = $transaction->account->accountType->type; // if is valid liability, trigger event! - if(in_array($type, config('firefly.valid_liabilities'))) { + if (in_array($type, config('firefly.valid_liabilities'), true)) { $accounts[] = $transaction->account; } } @@ -133,7 +132,7 @@ class DeleteController extends Controller $this->repository->destroy($group); /** @var Account $account */ - foreach($accounts as $account) { + foreach ($accounts as $account) { Log::debug(sprintf('Now going to trigger updated account event for account #%d', $account->id)); event(new UpdatedAccount($account)); } diff --git a/app/Http/Controllers/Transaction/EditController.php b/app/Http/Controllers/Transaction/EditController.php index 03ae906813..f34121a3ab 100644 --- a/app/Http/Controllers/Transaction/EditController.php +++ b/app/Http/Controllers/Transaction/EditController.php @@ -48,8 +48,7 @@ class EditController extends Controller // some useful repositories: $this->middleware( static function ($request, $next) { - - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); return $next($request); @@ -58,7 +57,7 @@ class EditController extends Controller } /** - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return Factory|View|RedirectResponse|Redirector */ @@ -88,10 +87,15 @@ class EditController extends Controller return view( 'transactions.edit', compact( - 'cash', 'allowedSourceDests', 'expectedSourceTypes', 'transactionGroup', 'allowedOpposingTypes', 'accountToTypes', 'defaultCurrency', + 'cash', + 'allowedSourceDests', + 'expectedSourceTypes', + 'transactionGroup', + 'allowedOpposingTypes', + 'accountToTypes', + 'defaultCurrency', 'previousUrl' ) ); } - } diff --git a/app/Http/Controllers/Transaction/IndexController.php b/app/Http/Controllers/Transaction/IndexController.php index 77808e48dd..e7c01542fc 100644 --- a/app/Http/Controllers/Transaction/IndexController.php +++ b/app/Http/Controllers/Transaction/IndexController.php @@ -24,7 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Http\Controllers\Transaction; use Carbon\Carbon; -use Exception; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Collector\GroupCollectorInterface; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; @@ -32,6 +32,8 @@ use FireflyIII\Support\Http\Controllers\PeriodOverview; use Illuminate\Contracts\View\Factory; use Illuminate\Http\Request; use Illuminate\View\View; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class IndexController @@ -55,7 +57,7 @@ class IndexController extends Controller $this->middleware( function ($request, $next) { app('view')->share('mainTitleIcon', 'fa-exchange'); - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); $this->repository = app(JournalRepositoryInterface::class); @@ -67,15 +69,15 @@ class IndexController extends Controller /** * Index for a range of transactions. * - * @param Request $request - * @param string $objectType - * @param Carbon|null $start - * @param Carbon|null $end + * @param Request $request + * @param string $objectType + * @param Carbon|null $start + * @param Carbon|null $end * * @return Factory|View - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws FireflyException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function index(Request $request, string $objectType, Carbon $start = null, Carbon $end = null) { @@ -83,10 +85,10 @@ class IndexController extends Controller $objectType = 'transfer'; } - $subTitleIcon = config('firefly.transactionIconsByType.' . $objectType); - $types = config('firefly.transactionTypesByType.' . $objectType); - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $subTitleIcon = config('firefly.transactionIconsByType.'.$objectType); + $types = config('firefly.transactionTypesByType.'.$objectType); + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; if (null === $start) { $start = session('start'); $end = session('end'); @@ -101,10 +103,10 @@ class IndexController extends Controller $path = route('transactions.index', [$objectType, $start->format('Y-m-d'), $end->format('Y-m-d')]); $startStr = $start->isoFormat($this->monthAndDayFormat); $endStr = $end->isoFormat($this->monthAndDayFormat); - $subTitle = (string) trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]); + $subTitle = (string)trans(sprintf('firefly.title_%s_between', $objectType), ['start' => $startStr, 'end' => $endStr]); $firstJournal = $this->repository->firstNull(); - $startPeriod = null === $firstJournal ? new Carbon : $firstJournal->date; + $startPeriod = null === $firstJournal ? new Carbon() : $firstJournal->date; $endPeriod = clone $end; $periods = $this->getTransactionPeriodOverview($objectType, $startPeriod, $endPeriod); @@ -128,26 +130,26 @@ class IndexController extends Controller /** * Index for ALL transactions. * - * @param Request $request - * @param string $objectType + * @param Request $request + * @param string $objectType * * @return Factory|View - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws FireflyException + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function indexAll(Request $request, string $objectType) { - $subTitleIcon = config('firefly.transactionIconsByType.' . $objectType); - $types = config('firefly.transactionTypesByType.' . $objectType); - $page = (int) $request->get('page'); - $pageSize = (int) app('preferences')->get('listPageSize', 50)->data; + $subTitleIcon = config('firefly.transactionIconsByType.'.$objectType); + $types = config('firefly.transactionTypesByType.'.$objectType); + $page = (int)$request->get('page'); + $pageSize = (int)app('preferences')->get('listPageSize', 50)->data; $path = route('transactions.index.all', [$objectType]); $first = $this->repository->firstNull(); - $start = null === $first ? new Carbon : $first->date; + $start = null === $first ? new Carbon() : $first->date; $last = $this->repository->getLast(); $end = $last ? $last->date : today(config('app.timezone')); - $subTitle = (string) trans('firefly.all_' . $objectType); + $subTitle = (string)trans('firefly.all_'.$objectType); /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); diff --git a/app/Http/Controllers/Transaction/LinkController.php b/app/Http/Controllers/Transaction/LinkController.php index 48627302d4..3534bb7b95 100644 --- a/app/Http/Controllers/Transaction/LinkController.php +++ b/app/Http/Controllers/Transaction/LinkController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); $this->journalRepository = app(JournalRepositoryInterface::class); @@ -68,14 +69,14 @@ class LinkController extends Controller /** * Delete a link. * - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link * * @return Factory|View */ public function delete(TransactionJournalLink $link) { $subTitleIcon = 'fa-link'; - $subTitle = (string) trans('breadcrumbs.delete_journal_link'); + $subTitle = (string)trans('breadcrumbs.delete_journal_link'); $this->rememberPreviousUrl('journal_links.delete.url'); return view('transactions.links.delete', compact('link', 'subTitle', 'subTitleIcon')); @@ -84,7 +85,7 @@ class LinkController extends Controller /** * Actually destroy it. * - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link * * @return RedirectResponse|Redirector */ @@ -92,14 +93,14 @@ class LinkController extends Controller { $this->repository->destroyLink($link); - session()->flash('success', (string) trans('firefly.deleted_link')); + session()->flash('success', (string)trans('firefly.deleted_link')); app('preferences')->mark(); - return redirect((string) session('journal_links.delete.url')); + return redirect((string)session('journal_links.delete.url')); } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Factory|View */ @@ -113,8 +114,8 @@ class LinkController extends Controller /** * Store a new link. * - * @param JournalLinkRequest $request - * @param TransactionJournal $journal + * @param JournalLinkRequest $request + * @param TransactionJournal $journal * * @return RedirectResponse|Redirector */ @@ -125,7 +126,7 @@ class LinkController extends Controller Log::debug('We are here (store)'); $other = $this->journalRepository->find($linkInfo['transaction_journal_id']); if (null === $other) { - session()->flash('error', (string) trans('firefly.invalid_link_selection')); + session()->flash('error', (string)trans('firefly.invalid_link_selection')); return redirect(route('transactions.show', [$journal->transaction_group_id])); } @@ -133,19 +134,19 @@ class LinkController extends Controller $alreadyLinked = $this->repository->findLink($journal, $other); if ($other->id === $journal->id) { - session()->flash('error', (string) trans('firefly.journals_link_to_self')); + session()->flash('error', (string)trans('firefly.journals_link_to_self')); return redirect(route('transactions.show', [$journal->transaction_group_id])); } if ($alreadyLinked) { - session()->flash('error', (string) trans('firefly.journals_error_linked')); + session()->flash('error', (string)trans('firefly.journals_error_linked')); return redirect(route('transactions.show', [$journal->transaction_group_id])); } Log::debug(sprintf('Journal is %d, opposing is %d', $journal->id, $other->id)); $this->repository->storeLink($linkInfo, $other, $journal); - session()->flash('success', (string) trans('firefly.journals_linked')); + session()->flash('success', (string)trans('firefly.journals_linked')); return redirect(route('transactions.show', [$journal->transaction_group_id])); } @@ -153,12 +154,12 @@ class LinkController extends Controller /** * Switch link from A <> B to B <> A. * - * @param Request $request + * @param Request $request * @return RedirectResponse|Redirector */ public function switchLink(Request $request) { - $linkId = (int) $request->get('id'); + $linkId = (int)$request->get('id'); $this->repository->switchLinkById($linkId); return redirect(app('steam')->getSafePreviousUrl()); diff --git a/app/Http/Controllers/Transaction/MassController.php b/app/Http/Controllers/Transaction/MassController.php index ccc1dc5f52..91457cbdb2 100644 --- a/app/Http/Controllers/Transaction/MassController.php +++ b/app/Http/Controllers/Transaction/MassController.php @@ -1,4 +1,5 @@ middleware( function ($request, $next) { - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); $this->repository = app(JournalRepositoryInterface::class); @@ -73,13 +74,13 @@ class MassController extends Controller /** * Mass delete transactions. * - * @param array $journals + * @param array $journals * * @return IlluminateView */ public function delete(array $journals): IlluminateView { - $subTitle = (string) trans('firefly.mass_delete_journals'); + $subTitle = (string)trans('firefly.mass_delete_journals'); // put previous url in session $this->rememberPreviousUrl('transactions.mass-delete.url'); @@ -90,7 +91,7 @@ class MassController extends Controller /** * Do the mass delete. * - * @param MassDeleteJournalRequest $request + * @param MassDeleteJournalRequest $request * * @return Application|Redirector|RedirectResponse * @@ -102,17 +103,16 @@ class MassController extends Controller if (is_array($ids)) { /** @var string $journalId */ foreach ($ids as $journalId) { - /** @var TransactionJournal $journal */ - $journal = $this->repository->find((int) $journalId); - if (null !== $journal && (int) $journalId === $journal->id) { + $journal = $this->repository->find((int)$journalId); + if (null !== $journal && (int)$journalId === $journal->id) { $this->repository->destroyJournal($journal); ++$count; } } } app('preferences')->mark(); - session()->flash('success', (string) trans_choice('firefly.mass_deleted_transactions_success', $count)); + session()->flash('success', (string)trans_choice('firefly.mass_deleted_transactions_success', $count)); // redirect to previous URL: return redirect($this->getPreviousUrl('transactions.mass-delete.url')); @@ -121,13 +121,13 @@ class MassController extends Controller /** * Mass edit of journals. * - * @param array $journals + * @param array $journals * * @return IlluminateView */ public function edit(array $journals): IlluminateView { - $subTitle = (string) trans('firefly.mass_edit_journals'); + $subTitle = (string)trans('firefly.mass_edit_journals'); /** @var AccountRepositoryInterface $accountRepository */ $accountRepository = app(AccountRepositoryInterface::class); @@ -159,7 +159,7 @@ class MassController extends Controller /** * Mass update of journals. * - * @param MassEditJournalRequest $request + * @param MassEditJournalRequest $request * * @return RedirectResponse|Redirector * @throws FireflyException @@ -168,13 +168,13 @@ class MassController extends Controller { $journalIds = $request->get('journals'); if (!is_array($journalIds)) { - // See reference nr. 48 + // TODO this is a weird error, should be caught. throw new FireflyException('This is not an array.'); } $count = 0; /** @var string $journalId */ foreach ($journalIds as $journalId) { - $integer = (int) $journalId; + $integer = (int)$journalId; try { $this->updateJournal($integer, $request); $count++; @@ -184,15 +184,15 @@ class MassController extends Controller } app('preferences')->mark(); - session()->flash('success', (string) trans_choice('firefly.mass_edited_transactions_success', $count)); + session()->flash('success', (string)trans_choice('firefly.mass_edited_transactions_success', $count)); // redirect to previous URL: return redirect($this->getPreviousUrl('transactions.mass-edit.url')); } /** - * @param int $journalId - * @param MassEditJournalRequest $request + * @param int $journalId + * @param MassEditJournalRequest $request * * @throws FireflyException */ @@ -224,13 +224,13 @@ class MassController extends Controller $service->setData($data); $service->update(); // trigger rules - event(new UpdatedTransactionGroup($journal->transactionGroup)); + event(new UpdatedTransactionGroup($journal->transactionGroup, true, true)); } /** - * @param MassEditJournalRequest $request - * @param int $journalId - * @param string $key + * @param MassEditJournalRequest $request + * @param int $journalId + * @param string $key * * @return Carbon|null * @codeCoverageIgnore @@ -256,9 +256,9 @@ class MassController extends Controller } /** - * @param MassEditJournalRequest $request - * @param int $journalId - * @param string $string + * @param MassEditJournalRequest $request + * @param int $journalId + * @param string $string * * @return string|null * @codeCoverageIgnore @@ -273,13 +273,13 @@ class MassController extends Controller return null; } - return (string) $value[$journalId]; + return (string)$value[$journalId]; } /** - * @param MassEditJournalRequest $request - * @param int $journalId - * @param string $string + * @param MassEditJournalRequest $request + * @param int $journalId + * @param string $string * * @return int|null * @codeCoverageIgnore @@ -294,6 +294,6 @@ class MassController extends Controller return null; } - return (int) $value[$journalId]; + return (int)$value[$journalId]; } } diff --git a/app/Http/Controllers/Transaction/ShowController.php b/app/Http/Controllers/Transaction/ShowController.php index 4454121bb8..c294ff0c7e 100644 --- a/app/Http/Controllers/Transaction/ShowController.php +++ b/app/Http/Controllers/Transaction/ShowController.php @@ -27,21 +27,21 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Repositories\AuditLogEntry\ALERepositoryInterface; use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface; use FireflyIII\Transformers\TransactionGroupTransformer; use Illuminate\Contracts\View\Factory; use Illuminate\Http\JsonResponse; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Log; use Illuminate\View\View; use Symfony\Component\HttpFoundation\ParameterBag; - /** * Class ShowController */ class ShowController extends Controller { + private ALERepositoryInterface $ALERepository; private TransactionGroupRepositoryInterface $repository; /** @@ -54,9 +54,10 @@ class ShowController extends Controller // some useful repositories: $this->middleware( function ($request, $next) { - $this->repository = app(TransactionGroupRepositoryInterface::class); + $this->repository = app(TransactionGroupRepositoryInterface::class); + $this->ALERepository = app(ALERepositoryInterface::class); - app('view')->share('title', (string) trans('firefly.transactions')); + app('view')->share('title', (string)trans('firefly.transactions')); app('view')->share('mainTitleIcon', 'fa-exchange'); return $next($request); @@ -65,7 +66,7 @@ class ShowController extends Controller } /** - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup * * @return JsonResponse */ @@ -75,8 +76,8 @@ class ShowController extends Controller } /** - * @param Request $request - * @param TransactionGroup $transactionGroup + * @param Request $request + * @param TransactionGroup $transactionGroup * * @return Factory|View * @throws FireflyException @@ -91,13 +92,13 @@ class ShowController extends Controller throw new FireflyException('This transaction is broken :(.'); } - $type = (string) trans(sprintf('firefly.%s', $first->transactionType->type)); + $type = (string)trans(sprintf('firefly.%s', $first->transactionType->type)); $title = 1 === $splits ? $first->description : $transactionGroup->title; $subTitle = sprintf('%s: "%s"', $type, $title); /** @var TransactionGroupTransformer $transformer */ $transformer = app(TransactionGroupTransformer::class); - $transformer->setParameters(new ParameterBag); + $transformer->setParameters(new ParameterBag()); $groupArray = $transformer->transformObject($transactionGroup); // do some calculations: @@ -108,10 +109,17 @@ class ShowController extends Controller $groupArray['transactions'][$index]['tags'] = $this->repository->getTagObjects($groupArray['transactions'][$index]['transaction_journal_id']); } + // get audit log entries: + $logEntries = []; + foreach ($transactionGroup->transactionJournals as $journal) { + $logEntries[$journal->id] = $this->ALERepository->getForObject($journal); + } + $events = $this->repository->getPiggyEvents($transactionGroup); $attachments = $this->repository->getAttachments($transactionGroup); $links = $this->repository->getLinks($transactionGroup); + return view( 'transactions.show', compact( @@ -119,6 +127,7 @@ class ShowController extends Controller 'amounts', 'first', 'type', + 'logEntries', 'subTitle', 'splits', 'groupArray', @@ -131,7 +140,7 @@ class ShowController extends Controller } /** - * @param array $group + * @param array $group * * @return array */ @@ -166,7 +175,7 @@ class ShowController extends Controller } /** - * @param array $group + * @param array $group * * @return array */ @@ -179,12 +188,14 @@ class ShowController extends Controller 'type' => $transaction['source_type'], 'id' => $transaction['source_id'], 'name' => $transaction['source_name'], - 'iban' => $transaction['source_iban']]; + 'iban' => $transaction['source_iban'], + ]; $accounts['destination'][] = [ 'type' => $transaction['destination_type'], 'id' => $transaction['destination_id'], 'name' => $transaction['destination_name'], - 'iban' => $transaction['destination_iban']]; + 'iban' => $transaction['destination_iban'], + ]; } $accounts['source'] = array_unique($accounts['source'], SORT_REGULAR); diff --git a/app/Http/Controllers/Webhooks/CreateController.php b/app/Http/Controllers/Webhooks/CreateController.php new file mode 100644 index 0000000000..4bf123ef0b --- /dev/null +++ b/app/Http/Controllers/Webhooks/CreateController.php @@ -0,0 +1,66 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers\Webhooks; + +use FireflyIII\Http\Controllers\Controller; +use Illuminate\Contracts\View\Factory; +use Illuminate\View\View; + +/** + * Class CreateController + */ +class CreateController extends Controller +{ + /** + * + */ + public function __construct() + { + parent::__construct(); + + // translations: + $this->middleware( + function ($request, $next) { + app('view')->share('mainTitleIcon', 'fa-bolt'); + app('view')->share('subTitleIcon', 'fa-plus'); + app('view')->share('title', (string)trans('firefly.webhooks')); + app('view')->share('subTitle', (string)trans('firefly.create_new_webhook')); + + return $next($request); + } + ); + } + + /** + * Show debug info. + * + * @return Factory|View + */ + public function index() + { + $previousUrl = $this->rememberPreviousUrl('webhooks.create.url'); + return view('webhooks.create', compact('previousUrl')); + } +} diff --git a/app/Http/Controllers/Webhooks/DeleteController.php b/app/Http/Controllers/Webhooks/DeleteController.php new file mode 100644 index 0000000000..6ed53c278a --- /dev/null +++ b/app/Http/Controllers/Webhooks/DeleteController.php @@ -0,0 +1,74 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers\Webhooks; + +use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Models\Webhook; +use Illuminate\Contracts\View\Factory; +use Illuminate\Http\RedirectResponse; +use Illuminate\Routing\Redirector; +use Illuminate\View\View; + +/** + * Class DeleteController + */ +class DeleteController extends Controller +{ + /** + * DeleteController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + + // translations: + $this->middleware( + function ($request, $next) { + app('view')->share('mainTitleIcon', 'fa-bolt'); + app('view')->share('subTitleIcon', 'fa-trash'); + app('view')->share('title', (string)trans('firefly.webhooks')); + app('view')->share('subTitle', (string)trans('firefly.delete_webhook')); + + return $next($request); + } + ); + } + + /** + * Delete account screen. + * + * @param Webhook $webhook + * + * @return Factory|RedirectResponse|Redirector|View + */ + public function index(Webhook $webhook) + { + $subTitle = (string)trans('firefly.delete_webhook', ['title' => $webhook->title]); + $this->rememberPreviousUrl('webhooks.delete.url'); + + return view('webhooks.delete', compact('webhook', 'subTitle')); + } +} diff --git a/app/Http/Controllers/Webhooks/EditController.php b/app/Http/Controllers/Webhooks/EditController.php new file mode 100644 index 0000000000..6f630855ca --- /dev/null +++ b/app/Http/Controllers/Webhooks/EditController.php @@ -0,0 +1,73 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers\Webhooks; + +use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Models\Webhook; +use Illuminate\Contracts\View\Factory; +use Illuminate\Http\RedirectResponse; +use Illuminate\Routing\Redirector; +use Illuminate\View\View; + +/** + * Class EditController + */ +class EditController extends Controller +{ + /** + * DeleteController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + + // translations: + $this->middleware( + function ($request, $next) { + app('view')->share('mainTitleIcon', 'fa-bolt'); + app('view')->share('subTitleIcon', 'fa-pencil'); + app('view')->share('title', (string)trans('firefly.webhooks')); + + return $next($request); + } + ); + } + + /** + * Delete account screen. + * + * @param Webhook $webhook + * + * @return Factory|RedirectResponse|Redirector|View + */ + public function index(Webhook $webhook) + { + $subTitle = (string)trans('firefly.edit_webhook', ['title' => $webhook->title]); + $this->rememberPreviousUrl('webhooks.delete.url'); + + return view('webhooks.edit', compact('webhook', 'subTitle')); + } +} diff --git a/app/Http/Controllers/Webhooks/IndexController.php b/app/Http/Controllers/Webhooks/IndexController.php new file mode 100644 index 0000000000..30c1c414b5 --- /dev/null +++ b/app/Http/Controllers/Webhooks/IndexController.php @@ -0,0 +1,68 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers\Webhooks; + +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Http\Controllers\Controller; +use Illuminate\Contracts\View\Factory; +use Illuminate\Http\Request; +use Illuminate\View\View; + +/** + * Class IndexController + */ +class IndexController extends Controller +{ + /** + * + */ + public function __construct() + { + parent::__construct(); + + // translations: + $this->middleware( + function ($request, $next) { + app('view')->share('mainTitleIcon', 'fa-bolt'); + app('view')->share('title', (string)trans('firefly.webhooks')); + + return $next($request); + } + ); + } + + /** + * Show debug info. + * + * @param Request $request + * + * @return Factory|View + * @throws FireflyException + */ + public function index(Request $request) + { + return view('webhooks.index'); + } +} diff --git a/app/Http/Controllers/Webhooks/ShowController.php b/app/Http/Controllers/Webhooks/ShowController.php new file mode 100644 index 0000000000..236461d339 --- /dev/null +++ b/app/Http/Controllers/Webhooks/ShowController.php @@ -0,0 +1,72 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Controllers\Webhooks; + +use FireflyIII\Http\Controllers\Controller; +use FireflyIII\Models\Webhook; +use Illuminate\Contracts\View\Factory; +use Illuminate\Http\RedirectResponse; +use Illuminate\Routing\Redirector; +use Illuminate\View\View; + +/** + * Class ShowController + */ +class ShowController extends Controller +{ + /** + * DeleteController constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + parent::__construct(); + + // translations: + $this->middleware( + function ($request, $next) { + app('view')->share('mainTitleIcon', 'fa-bolt'); + app('view')->share('subTitleIcon', 'fa-bolt'); + app('view')->share('title', (string)trans('firefly.webhooks')); + + return $next($request); + } + ); + } + + /** + * Delete account screen. + * + * @param Webhook $webhook + * + * @return Factory|RedirectResponse|Redirector|View + */ + public function index(Webhook $webhook) + { + $subTitle = (string)trans('firefly.show_webhook', ['title' => $webhook->title]); + + return view('webhooks.show', compact('webhook', 'subTitle')); + } +} diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 5dbc366ee1..51e0dc48f9 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -1,4 +1,5 @@ [ + AcceptHeaders::class, EnsureFrontendRequestsAreStateful::class, 'auth:api,sanctum', 'bindings', diff --git a/app/Http/Middleware/AcceptHeaders.php b/app/Http/Middleware/AcceptHeaders.php new file mode 100644 index 0000000000..8debaf520d --- /dev/null +++ b/app/Http/Middleware/AcceptHeaders.php @@ -0,0 +1,68 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Middleware; + +use FireflyIII\Exceptions\BadHttpHeaderException; +use Illuminate\Http\Request; +use Illuminate\Http\Response; +use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; + +/** + * + */ +class AcceptHeaders +{ + /** + * Handle the incoming requests. + * + * @param Request $request + * @param callable $next + * @return Response + * @throws BadHttpHeaderException + */ + public function handle($request, $next): mixed + { + $method = $request->getMethod(); + + if ('GET' === $method && !$request->accepts(['application/json', 'application/vdn.api+json'])) { + throw new BadHttpHeaderException('Your request must accept either application/json or application/vdn.api+json.'); + } + $allowed = ['application/x-www-form-urlencoded', 'application/json','']; + $submitted = (string)$request->header('Content-Type'); + if (('POST' === $method || 'PUT' === $method) && !in_array($submitted, $allowed, true)) { + $error = new BadHttpHeaderException(sprintf('Content-Type cannot be "%s"', $submitted)); + $error->statusCode = 415; + throw $error; + } + + // throw bad request if trace id is not a UUID + $uuid = $request->header('X-Trace-Id', null); + if (is_string($uuid) && '' !== trim($uuid) && (preg_match('/^[a-f\d]{8}(-[a-f\d]{4}){4}[a-f\d]{8}$/i', trim($uuid)) !== 1)) { + throw new BadRequestHttpException('Bad X-Trace-Id header.'); + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php index ba3d72b53d..f69bd9b8cb 100644 --- a/app/Http/Middleware/Authenticate.php +++ b/app/Http/Middleware/Authenticate.php @@ -109,24 +109,26 @@ class Authenticate $message = (string)trans('firefly.email_changed_logout'); } app('session')->flash('logoutMessage', $message); - /** @noinspection PhpUndefinedMethodInspection */ - $this->auth->logout(); + $this->auth->logout(); // @phpstan-ignore-line (thinks function is undefined) throw new AuthenticationException('Blocked account.', $guards); } } } - /** @noinspection PhpUndefinedMethodInspection */ - return $this->auth->authenticate(); + return $this->auth->authenticate(); // @phpstan-ignore-line (thinks function returns void) } Log::debug('Guard array is not empty.'); foreach ($guards as $guard) { Log::debug(sprintf('Now in guard loop, guard is "%s"', $guard)); - $this->auth->guard($guard)->authenticate(); - if ($this->auth->guard($guard)->check()) { - /** @noinspection PhpVoidFunctionResultUsedInspection */ + if('api' !== $guard) { + $this->auth->guard($guard)->authenticate(); + } + $result = $this->auth->guard($guard)->check(); + Log::debug(sprintf('Result is %s', var_export($result, true))); + if ($result) { + // According to PHPstan the method returns void, but we'll see. return $this->auth->shouldUse($guard); // @phpstan-ignore-line } } diff --git a/app/Http/Middleware/Binder.php b/app/Http/Middleware/Binder.php index fb5255a15d..7f8287486c 100644 --- a/app/Http/Middleware/Binder.php +++ b/app/Http/Middleware/Binder.php @@ -1,4 +1,5 @@ isAccessDenied($message)) { throw new FireflyException( - 'It seems your database configuration is not correct. Please verify the username and password in your .env file.', 0, $e + 'It seems your database configuration is not correct. Please verify the username and password in your .env file.', + 0, + $e ); } if ($this->noTablesExist($message)) { // redirect to UpdateController - Log::warning('There are no Firefly III tables present. Redirect to migrate routine.'); + app('log')->warning('There are no Firefly III tables present. Redirect to migrate routine.'); return true; } @@ -116,7 +118,7 @@ class Installer /** * Is access denied error. * - * @param string $message + * @param string $message * * @return bool */ @@ -128,7 +130,7 @@ class Installer /** * Is no tables exist error. * - * @param string $message + * @param string $message * * @return bool */ @@ -145,10 +147,10 @@ class Installer private function oldDBVersion(): bool { // older version in config than database? - $configVersion = (int) config('firefly.db_version'); - $dbVersion = (int) app('fireflyconfig')->getFresh('db_version', 1)->data; + $configVersion = (int)config('firefly.db_version'); + $dbVersion = (int)app('fireflyconfig')->getFresh('db_version', 1)->data; if ($configVersion > $dbVersion) { - Log::warning( + app('log')->warning( sprintf( 'The current configured version (%d) is older than the required version (%d). Redirect to migrate routine.', $dbVersion, @@ -172,10 +174,10 @@ class Installer private function oldVersion(): bool { // version compare thing. - $configVersion = (string) config('firefly.version'); - $dbVersion = (string) app('fireflyconfig')->getFresh('ff3_version', '1.0')->data; + $configVersion = (string)config('firefly.version'); + $dbVersion = (string)app('fireflyconfig')->getFresh('ff3_version', '1.0')->data; if (1 === version_compare($configVersion, $dbVersion)) { - Log::warning( + app('log')->warning( sprintf( 'The current configured Firefly III version (%s) is older than the required version (%s). Redirect to migrate routine.', $dbVersion, diff --git a/app/Http/Middleware/InterestingMessage.php b/app/Http/Middleware/InterestingMessage.php index 508eeb579c..f3e264bda7 100644 --- a/app/Http/Middleware/InterestingMessage.php +++ b/app/Http/Middleware/InterestingMessage.php @@ -28,6 +28,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Bill; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\Webhook; use Illuminate\Http\Request; use Preferences; @@ -39,8 +40,8 @@ class InterestingMessage /** * Flashes the user an interesting message if the URL parameters warrant it. * - * @param Request $request - * @param Closure $next + * @param Request $request + * @param Closure $next * * @return mixed * @@ -63,6 +64,10 @@ class InterestingMessage Preferences::mark(); $this->handleBillMessage($request); } + if ($this->webhookMessage($request)) { + Preferences::mark(); + $this->handleWebhookMessage($request); + } return $next($request); } @@ -77,7 +82,7 @@ class InterestingMessage } /** - * @param Request $request + * @param Request $request * * @return bool */ @@ -91,18 +96,17 @@ class InterestingMessage } /** - * @param Request $request + * @param Request $request */ private function handleGroupMessage(Request $request): void { - // get parameters from request. $transactionGroupId = $request->get('transaction_group_id'); $message = $request->get('message'); // send message about newly created transaction group. /** @var TransactionGroup $group */ - $group = auth()->user()->transactionGroups()->with(['transactionJournals', 'transactionJournals.transactionType'])->find((int) $transactionGroupId); + $group = auth()->user()->transactionGroups()->with(['transactionJournals', 'transactionJournals.transactionType'])->find((int)$transactionGroupId); if (null === $group) { return; @@ -118,22 +122,22 @@ class InterestingMessage $title = $count > 1 ? $group->title : $journal->description; if ('created' === $message) { session()->flash('success_url', route('transactions.show', [$transactionGroupId])); - session()->flash('success', (string) trans('firefly.stored_journal', ['description' => $title])); + session()->flash('success', (string)trans('firefly.stored_journal', ['description' => $title])); } if ('updated' === $message) { $type = strtolower($journal->transactionType->type); session()->flash('success_url', route('transactions.show', [$transactionGroupId])); - session()->flash('success', (string) trans(sprintf('firefly.updated_%s', $type), ['description' => $title])); + session()->flash('success', (string)trans(sprintf('firefly.updated_%s', $type), ['description' => $title])); } if ('no_change' === $message) { $type = strtolower($journal->transactionType->type); session()->flash('warning_url', route('transactions.show', [$transactionGroupId])); - session()->flash('warning', (string) trans(sprintf('firefly.no_changes_%s', $type), ['description' => $title])); + session()->flash('warning', (string)trans(sprintf('firefly.no_changes_%s', $type), ['description' => $title])); } } /** - * @param Request $request + * @param Request $request * * @return bool */ @@ -147,11 +151,10 @@ class InterestingMessage } /** - * @param Request $request + * @param Request $request */ private function handleAccountMessage(Request $request): void { - // get parameters from request. $accountId = $request->get('account_id'); $message = $request->get('message'); @@ -163,18 +166,18 @@ class InterestingMessage return; } if ('deleted' === $message) { - session()->flash('success', (string) trans('firefly.account_deleted', ['name' => $account->name])); + session()->flash('success', (string)trans('firefly.account_deleted', ['name' => $account->name])); } if ('created' === $message) { - session()->flash('success', (string) trans('firefly.stored_new_account', ['name' => $account->name])); + session()->flash('success', (string)trans('firefly.stored_new_account', ['name' => $account->name])); } if ('updated' === $message) { - session()->flash('success', (string) trans('firefly.updated_account', ['name' => $account->name])); + session()->flash('success', (string)trans('firefly.updated_account', ['name' => $account->name])); } } /** - * @param Request $request + * @param Request $request * * @return bool */ @@ -188,11 +191,10 @@ class InterestingMessage } /** - * @param Request $request + * @param Request $request */ private function handleBillMessage(Request $request): void { - // get parameters from request. $billId = $request->get('bill_id'); $message = $request->get('message'); @@ -204,10 +206,50 @@ class InterestingMessage return; } if ('deleted' === $message) { - session()->flash('success', (string) trans('firefly.deleted_bill', ['name' => $bill->name])); + session()->flash('success', (string)trans('firefly.deleted_bill', ['name' => $bill->name])); } if ('created' === $message) { - session()->flash('success', (string) trans('firefly.stored_new_bill', ['name' => $bill->name])); + session()->flash('success', (string)trans('firefly.stored_new_bill', ['name' => $bill->name])); + } + } + + /** + * @param Request $request + * + * @return bool + */ + private function webhookMessage(Request $request): bool + { + // get parameters from request. + $billId = $request->get('webhook_id'); + $message = $request->get('message'); + + return null !== $billId && null !== $message; + } + + /** + * @param Request $request + */ + private function handleWebhookMessage(Request $request): void + { + // get parameters from request. + $webhookId = $request->get('webhook_id'); + $message = $request->get('message'); + + /** @var Webhook $webhook */ + $webhook = auth()->user()->webhooks()->withTrashed()->find($webhookId); + + if (null === $webhook) { + return; + } + if ('deleted' === $message) { + session()->flash('success', (string)trans('firefly.deleted_webhook', ['title' => $webhook->title])); + } + if ('updated' === $message) { + session()->flash('success', (string)trans('firefly.updated_webhook', ['title' => $webhook->title])); + } + if ('created' === $message) { + session()->flash('success', (string)trans('firefly.stored_new_webhook', ['title' => $webhook->title])); } } } diff --git a/app/Http/Middleware/IsAdmin.php b/app/Http/Middleware/IsAdmin.php index 8386c3fe93..32d8b04c98 100644 --- a/app/Http/Middleware/IsAdmin.php +++ b/app/Http/Middleware/IsAdmin.php @@ -1,4 +1,5 @@ hasRole($user, 'demo')) { Log::info('User is a demo user.'); - $request->session()->flash('info', (string) trans('firefly.not_available_demo_user')); + $request->session()->flash('info', (string)trans('firefly.not_available_demo_user')); $current = $request->url(); $previous = $request->session()->previousUrl(); if ($current !== $previous) { diff --git a/app/Http/Middleware/Range.php b/app/Http/Middleware/Range.php index 45351ff4bf..3db1a776a9 100644 --- a/app/Http/Middleware/Range.php +++ b/app/Http/Middleware/Range.php @@ -1,4 +1,5 @@ configureList(); - } return $next($request); @@ -113,12 +113,12 @@ class Range } // save some formats: - $monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale); - $dateTimeFormat = (string) trans('config.date_time_js', [], $locale); + $monthAndDayFormat = (string)trans('config.month_and_day_js', [], $locale); + $dateTimeFormat = (string)trans('config.date_time_js', [], $locale); $defaultCurrency = app('amount')->getDefaultCurrency(); // also format for moment JS: - $madMomentJS = (string) trans('config.month_and_day_moment_js', [], $locale); + $madMomentJS = (string)trans('config.month_and_day_moment_js', [], $locale); app('view')->share('madMomentJS', $madMomentJS); app('view')->share('monthAndDayFormat', $monthAndDayFormat); diff --git a/app/Http/Middleware/RedirectIfAuthenticated.php b/app/Http/Middleware/RedirectIfAuthenticated.php index 9b17c7f49a..d48dbcb893 100644 --- a/app/Http/Middleware/RedirectIfAuthenticated.php +++ b/app/Http/Middleware/RedirectIfAuthenticated.php @@ -1,4 +1,5 @@ route(); $customUrl = ''; - $authGuard = (string) config('firefly.authentication_guard'); - $logoutUrl = (string) config('firefly.custom_logout_url'); + $authGuard = (string)config('firefly.authentication_guard'); + $logoutUrl = (string)config('firefly.custom_logout_url'); if ('remote_user_guard' === $authGuard && '' !== $logoutUrl) { $customUrl = $logoutUrl; } @@ -115,8 +115,8 @@ class SecureHeaders */ private function getTrackingScriptSource(): string { - if ('' !== (string) config('firefly.tracker_site_id') && '' !== (string) config('firefly.tracker_url')) { - return (string) config('firefly.tracker_url'); + if ('' !== (string)config('firefly.tracker_site_id') && '' !== (string)config('firefly.tracker_url')) { + return (string)config('firefly.tracker_url'); } return ''; diff --git a/app/Http/Middleware/StartFireflySession.php b/app/Http/Middleware/StartFireflySession.php index 20d1d7d4e6..2ae301774c 100644 --- a/app/Http/Middleware/StartFireflySession.php +++ b/app/Http/Middleware/StartFireflySession.php @@ -1,4 +1,5 @@ proxies = (string) config('firefly.trusted_proxies'); + $this->proxies = (string)config('firefly.trusted_proxies'); } } diff --git a/app/Http/Middleware/VerifyCsrfToken.php b/app/Http/Middleware/VerifyCsrfToken.php index 195b27daaa..8f53afdccd 100644 --- a/app/Http/Middleware/VerifyCsrfToken.php +++ b/app/Http/Middleware/VerifyCsrfToken.php @@ -1,4 +1,5 @@ 'numeric|nullable|max:1000000000', 'currency_id' => 'exists:transaction_currencies,id', 'account_number' => 'between:1,255|uniqueAccountNumberForUser|nullable', - 'account_role' => 'in:' . $accountRoles, + 'account_role' => 'in:'.$accountRoles, 'active' => 'boolean', - 'cc_type' => 'in:' . $ccPaymentTypes, + 'cc_type' => 'in:'.$ccPaymentTypes, 'amount_currency_id_opening_balance' => 'exists:transaction_currencies,id', 'amount_currency_id_virtual_balance' => 'exists:transaction_currencies,id', - 'what' => 'in:' . $types, + 'what' => 'in:'.$types, 'interest_period' => 'in:daily,monthly,yearly', ]; $rules = Location::requestRules($rules); @@ -120,7 +123,7 @@ class AccountFormRequest extends FormRequest if (null !== $account) { // add rules: $rules['id'] = 'belongsToUser:accounts'; - $rules['name'] = 'required|min:1|uniqueAccountForUser:' . $account->id; + $rules['name'] = 'required|min:1|uniqueAccountForUser:'.$account->id; $rules['iban'] = ['iban', 'nullable', new UniqueIban($account, $account->accountType->type)]; } diff --git a/app/Http/Requests/AttachmentFormRequest.php b/app/Http/Requests/AttachmentFormRequest.php index dd03ba124b..c02d58d1ca 100644 --- a/app/Http/Requests/AttachmentFormRequest.php +++ b/app/Http/Requests/AttachmentFormRequest.php @@ -1,4 +1,5 @@ route()->parameter('budget'); if (null !== $budget) { - $nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,' . $budget->id; + $nameRule = 'required|between:1,100|uniqueObjectForUser:budgets,name,'.$budget->id; } return [ @@ -83,7 +86,7 @@ class BudgetFormUpdateRequest extends FormRequest /** * Configure the validator instance with special rules for after the basic validation rules. * - * @param Validator $validator + * @param Validator $validator * * @return void */ diff --git a/app/Http/Requests/BudgetIncomeRequest.php b/app/Http/Requests/BudgetIncomeRequest.php index aa99bf336a..bc500c7e8b 100644 --- a/app/Http/Requests/BudgetIncomeRequest.php +++ b/app/Http/Requests/BudgetIncomeRequest.php @@ -1,4 +1,5 @@ 'required|belongsToUser:transaction_journals,id', diff --git a/app/Http/Requests/CategoryFormRequest.php b/app/Http/Requests/CategoryFormRequest.php index 9ce60cbb11..476140da26 100644 --- a/app/Http/Requests/CategoryFormRequest.php +++ b/app/Http/Requests/CategoryFormRequest.php @@ -1,4 +1,5 @@ route()->parameter('category'); if (null !== $category) { - $nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,' . $category->id; + $nameRule = 'required|between:1,100|uniqueObjectForUser:categories,name,'.$category->id; } // fixed diff --git a/app/Http/Requests/ConfigurationRequest.php b/app/Http/Requests/ConfigurationRequest.php index 41dc970169..14b7267ad0 100644 --- a/app/Http/Requests/ConfigurationRequest.php +++ b/app/Http/Requests/ConfigurationRequest.php @@ -1,4 +1,5 @@ . + */ + +declare(strict_types=1); + +namespace FireflyIII\Http\Requests; + +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Foundation\Http\FormRequest; + +class InviteUserFormRequest extends FormRequest +{ + use ConvertsDataTypes; + use ChecksLogin; + + /** + * Rules for this request. + * + * @return array + */ + public function rules(): array + { + return [ + 'invited_user' => 'required|email|unique:invited_users,email', + ]; + } +} diff --git a/app/Http/Requests/JournalLinkRequest.php b/app/Http/Requests/JournalLinkRequest.php index 2886cbb4d8..7eb14cbee6 100644 --- a/app/Http/Requests/JournalLinkRequest.php +++ b/app/Http/Requests/JournalLinkRequest.php @@ -1,4 +1,5 @@ get('link_type'); $parts = explode('_', $linkType); - $return['link_type_id'] = (int) $parts[0]; + $return['link_type_id'] = (int)$parts[0]; $return['transaction_journal_id'] = $this->convertInteger('opposing'); $return['notes'] = $this->convertString('notes'); $return['direction'] = $parts[1]; diff --git a/app/Http/Requests/LinkTypeFormRequest.php b/app/Http/Requests/LinkTypeFormRequest.php index b9ad77ff8d..d8864ba15e 100644 --- a/app/Http/Requests/LinkTypeFormRequest.php +++ b/app/Http/Requests/LinkTypeFormRequest.php @@ -1,4 +1,5 @@ 'numeric|max:1000000000', 'endBalance' => 'numeric|max:1000000000', 'difference' => 'required|numeric|max:1000000000', - 'journals' => [new ValidJournals], + 'journals' => [new ValidJournals()], 'reconcile' => 'required|in:create,nothing', ]; } diff --git a/app/Http/Requests/RecurrenceFormRequest.php b/app/Http/Requests/RecurrenceFormRequest.php index c90ee927ae..16076efd43 100644 --- a/app/Http/Requests/RecurrenceFormRequest.php +++ b/app/Http/Requests/RecurrenceFormRequest.php @@ -42,7 +42,8 @@ use Log; */ class RecurrenceFormRequest extends FormRequest { - use ConvertsDataTypes, ChecksLogin; + use ConvertsDataTypes; + use ChecksLogin; /** * Get the data required by the controller. @@ -108,27 +109,34 @@ class RecurrenceFormRequest extends FormRequest $return['transactions'][0]['source_name'] = null; $return['transactions'][0]['destination_id'] = null; $return['transactions'][0]['destination_name'] = null; - // fill in source and destination account data - switch ($this->convertString('transaction_type')) { - default: - throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->convertString('transaction_type'))); - case 'withdrawal': - $return['transactions'][0]['source_id'] = $this->convertInteger('source_id'); - $return['transactions'][0]['destination_id'] = $this->convertInteger('withdrawal_destination_id'); - break; - case 'deposit': - $return['transactions'][0]['source_id'] = $this->convertInteger('deposit_source_id'); - $return['transactions'][0]['destination_id'] = $this->convertInteger('destination_id'); - break; - case 'transfer': - $return['transactions'][0]['source_id'] = $this->convertInteger('source_id'); - $return['transactions'][0]['destination_id'] = $this->convertInteger('destination_id'); - break; + $throwError = true; + $type = $this->convertString('transaction_type'); + if ('withdrawal' === $type) { + $throwError = false; + $return['transactions'][0]['source_id'] = $this->convertInteger('source_id'); + $return['transactions'][0]['destination_id'] = $this->convertInteger('withdrawal_destination_id'); + } + if ('deposit' === $type) { + $throwError = false; + $return['transactions'][0]['source_id'] = $this->convertInteger('deposit_source_id'); + $return['transactions'][0]['destination_id'] = $this->convertInteger('destination_id'); + } + if ('transfer' === $type) { + $throwError = false; + $return['transactions'][0]['source_id'] = $this->convertInteger('source_id'); + $return['transactions'][0]['destination_id'] = $this->convertInteger('destination_id'); + } + if (true === $throwError) { + throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->convertString('transaction_type'))); } // replace category name with a new category: $factory = app(CategoryFactory::class); $factory->setUser(auth()->user()); + /** + * @var int $index + * @var array $transaction + */ foreach ($return['transactions'] as $index => $transaction) { $categoryName = $transaction['category_name'] ?? null; if (null !== $categoryName) { @@ -160,7 +168,7 @@ class RecurrenceFormRequest extends FormRequest } //monthly,17 //ndom,3,7 - if (in_array(substr($value, 0, 6), ['yearly', 'weekly'])) { + if (in_array(substr($value, 0, 6), ['yearly', 'weekly'], true)) { $return['type'] = substr($value, 0, 6); $return['moment'] = substr($value, 7); } @@ -190,8 +198,8 @@ class RecurrenceFormRequest extends FormRequest $rules = [ // mandatory info for recurrence. 'title' => 'required|between:1,255|uniqueObjectForUser:recurrences,title', - 'first_date' => 'required|date|after:' . $today->format('Y-m-d'), - 'repetition_type' => ['required', new ValidRecurrenceRepetitionValue, new ValidRecurrenceRepetitionType, 'between:1,20'], + 'first_date' => 'required|date|after:'.$today->format('Y-m-d'), + 'repetition_type' => ['required', new ValidRecurrenceRepetitionValue(), new ValidRecurrenceRepetitionType(), 'between:1,20'], 'skip' => 'required|numeric|integer|gte:0|lte:31', // optional for recurrence: @@ -234,27 +242,23 @@ class RecurrenceFormRequest extends FormRequest // if ends at date X, set another rule. if ('until_date' === $this->convertString('repetition_end')) { - $rules['repeat_until'] = 'required|date|after:' . $tomorrow->format('Y-m-d'); + $rules['repeat_until'] = 'required|date|after:'.$tomorrow->format('Y-m-d'); } // switch on type to expand rules for source and destination accounts: - switch ($this->convertString('transaction_type')) { - case strtolower(TransactionType::WITHDRAWAL): - $rules['source_id'] = 'required|exists:accounts,id|belongsToUser:accounts'; - $rules['destination_name'] = 'between:1,255|nullable'; - break; - case strtolower(TransactionType::DEPOSIT): - $rules['source_name'] = 'between:1,255|nullable'; - $rules['destination_id'] = 'required|exists:accounts,id|belongsToUser:accounts'; - break; - case strtolower(TransactionType::TRANSFER): - // this may not work: - $rules['source_id'] = 'required|exists:accounts,id|belongsToUser:accounts|different:destination_id'; - $rules['destination_id'] = 'required|exists:accounts,id|belongsToUser:accounts|different:source_id'; - - break; - default: - throw new FireflyException(sprintf('Cannot handle transaction type of type "%s"', $this->convertString('transaction_type'))); + $type = strtolower($this->convertString('transaction_type')); + if (strtolower(TransactionType::WITHDRAWAL) === $type) { + $rules['source_id'] = 'required|exists:accounts,id|belongsToUser:accounts'; + $rules['destination_name'] = 'between:1,255|nullable'; + } + if (strtolower(TransactionType::DEPOSIT) === $type) { + $rules['source_name'] = 'between:1,255|nullable'; + $rules['destination_id'] = 'required|exists:accounts,id|belongsToUser:accounts'; + } + if (strtolower(TransactionType::TRANSFER) === $type) { + // this may not work: + $rules['source_id'] = 'required|exists:accounts,id|belongsToUser:accounts|different:destination_id'; + $rules['destination_id'] = 'required|exists:accounts,id|belongsToUser:accounts|different:source_id'; } // update some rules in case the user is editing a post: @@ -262,7 +266,7 @@ class RecurrenceFormRequest extends FormRequest $recurrence = $this->route()->parameter('recurrence'); if ($recurrence instanceof Recurrence) { $rules['id'] = 'required|numeric|exists:recurrences,id'; - $rules['title'] = 'required|between:1,255|uniqueObjectForUser:recurrences,title,' . $recurrence->id; + $rules['title'] = 'required|between:1,255|uniqueObjectForUser:recurrences,title,'.$recurrence->id; $rules['first_date'] = 'required|date'; } @@ -272,7 +276,7 @@ class RecurrenceFormRequest extends FormRequest /** * Configure the validator instance with special rules for after the basic validation rules. * - * @param Validator $validator + * @param Validator $validator * * @return void */ @@ -289,7 +293,7 @@ class RecurrenceFormRequest extends FormRequest /** * Validates the given account information. Switches on given transaction type. * - * @param Validator $validator + * @param Validator $validator * * @throws FireflyException */ @@ -307,30 +311,35 @@ class RecurrenceFormRequest extends FormRequest $sourceId = null; $destinationId = null; - // See reference nr. 45 - - switch ($this->convertString('transaction_type')) { - default: - throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->convertString('transaction_type'))); - case 'withdrawal': - $sourceId = (int) $data['source_id']; - $destinationId = (int) $data['withdrawal_destination_id']; - break; - case 'deposit': - $sourceId = (int) $data['deposit_source_id']; - $destinationId = (int) $data['destination_id']; - break; - case 'transfer': - $sourceId = (int) $data['source_id']; - $destinationId = (int) $data['destination_id']; - break; + // TODO typeOverrule: the account validator may have another opinion the transaction type. + // TODO either use 'withdrawal' or the strtolower() variant, not both. + $type = $this->convertString('transaction_type'); + $throwError = true; + if ('withdrawal' === $type) { + $throwError = false; + $sourceId = (int)$data['source_id']; + $destinationId = (int)$data['withdrawal_destination_id']; } + if ('deposit' === $type) { + $throwError = false; + $sourceId = (int)$data['deposit_source_id']; + $destinationId = (int)$data['destination_id']; + } + if ('transfer' === $type) { + $throwError = false; + $sourceId = (int)$data['source_id']; + $destinationId = (int)$data['destination_id']; + } + if (true === $throwError) { + throw new FireflyException(sprintf('Cannot handle transaction type "%s"', $this->convertString('transaction_type'))); + } + // validate source account. $validSource = $accountValidator->validateSource(['id' => $sourceId,]); // do something with result: if (false === $validSource) { - $message = (string) trans('validation.generic_invalid_source'); + $message = (string)trans('validation.generic_invalid_source'); $validator->errors()->add('source_id', $message); $validator->errors()->add('deposit_source_id', $message); @@ -341,7 +350,7 @@ class RecurrenceFormRequest extends FormRequest $validDestination = $accountValidator->validateDestination(['id' => $destinationId,]); // do something with result: if (false === $validDestination) { - $message = (string) trans('validation.generic_invalid_destination'); + $message = (string)trans('validation.generic_invalid_destination'); $validator->errors()->add('destination_id', $message); $validator->errors()->add('withdrawal_destination_id', $message); } diff --git a/app/Http/Requests/ReportFormRequest.php b/app/Http/Requests/ReportFormRequest.php index 01ad7ff42a..16f21d0da0 100644 --- a/app/Http/Requests/ReportFormRequest.php +++ b/app/Http/Requests/ReportFormRequest.php @@ -1,4 +1,5 @@ get('accounts'); - $collection = new Collection; + $collection = new Collection(); if (is_array($set)) { foreach ($set as $accountId) { - $account = $repository->find((int) $accountId); + $account = $repository->find((int)$accountId); if (null !== $account) { $collection->push($account); } @@ -75,10 +76,10 @@ class ReportFormRequest extends FormRequest /** @var BudgetRepositoryInterface $repository */ $repository = app(BudgetRepositoryInterface::class); $set = $this->get('budget'); - $collection = new Collection; + $collection = new Collection(); if (is_array($set)) { foreach ($set as $budgetId) { - $budget = $repository->find((int) $budgetId); + $budget = $repository->find((int)$budgetId); if (null !== $budget) { $collection->push($budget); } @@ -98,10 +99,10 @@ class ReportFormRequest extends FormRequest /** @var CategoryRepositoryInterface $repository */ $repository = app(CategoryRepositoryInterface::class); $set = $this->get('category'); - $collection = new Collection; + $collection = new Collection(); if (is_array($set)) { foreach ($set as $categoryId) { - $category = $repository->find((int) $categoryId); + $category = $repository->find((int)$categoryId); if (null !== $category) { $collection->push($category); } @@ -121,10 +122,10 @@ class ReportFormRequest extends FormRequest /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $set = $this->get('double'); - $collection = new Collection; + $collection = new Collection(); if (is_array($set)) { foreach ($set as $accountId) { - $account = $repository->find((int) $accountId); + $account = $repository->find((int)$accountId); if (null !== $account) { $collection->push($account); } @@ -145,7 +146,7 @@ class ReportFormRequest extends FormRequest { $date = today(config('app.timezone')); $range = $this->get('daterange'); - $parts = explode(' - ', (string) $range); + $parts = explode(' - ', (string)$range); if (2 === count($parts)) { $string = $parts[1]; // validate as date @@ -154,7 +155,7 @@ class ReportFormRequest extends FormRequest if (preg_match($pattern, $string)) { try { $date = new Carbon($parts[1]); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception $error = sprintf('"%s" is not a valid date range: %s', $range, $e->getMessage()); Log::error($error); throw new FireflyException($error, 0, $e); @@ -179,7 +180,7 @@ class ReportFormRequest extends FormRequest { $date = today(config('app.timezone')); $range = $this->get('daterange'); - $parts = explode(' - ', (string) $range); + $parts = explode(' - ', (string)$range); if (2 === count($parts)) { $string = $parts[0]; // validate as date @@ -188,7 +189,7 @@ class ReportFormRequest extends FormRequest if (preg_match($pattern, $string)) { try { $date = new Carbon($parts[0]); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception $error = sprintf('"%s" is not a valid date range: %s', $range, $e->getMessage()); Log::error($error); throw new FireflyException($error, 0, $e); @@ -213,7 +214,7 @@ class ReportFormRequest extends FormRequest /** @var TagRepositoryInterface $repository */ $repository = app(TagRepositoryInterface::class); $set = $this->get('tag'); - $collection = new Collection; + $collection = new Collection(); Log::debug('Set is:', $set ?? []); if (is_array($set)) { foreach ($set as $tagTag) { @@ -223,7 +224,7 @@ class ReportFormRequest extends FormRequest $collection->push($tag); continue; } - $tag = $repository->find((int) $tagTag); + $tag = $repository->find((int)$tagTag); if (null !== $tag) { $collection->push($tag); } diff --git a/app/Http/Requests/RuleFormRequest.php b/app/Http/Requests/RuleFormRequest.php index 7f283807bc..152f9da4d3 100644 --- a/app/Http/Requests/RuleFormRequest.php +++ b/app/Http/Requests/RuleFormRequest.php @@ -34,7 +34,9 @@ use Illuminate\Foundation\Http\FormRequest; */ class RuleFormRequest extends FormRequest { - use ConvertsDataTypes, GetRuleConfiguration, ChecksLogin; + use ConvertsDataTypes; + use GetRuleConfiguration; + use ChecksLogin; /** * Get all data for controller. @@ -67,14 +69,15 @@ class RuleFormRequest extends FormRequest if (is_array($triggerData)) { foreach ($triggerData as $trigger) { $stopProcessing = $trigger['stop_processing'] ?? '0'; - $current = [ + $prohibited = $trigger['prohibited'] ?? '0'; + $set = [ 'type' => $trigger['type'] ?? 'invalid', 'value' => $trigger['value'] ?? '', 'stop_processing' => 1 === (int)$stopProcessing, + 'prohibited' => 1 === (int)$prohibited, ]; - $current = self::replaceAmountTrigger($current); - - $return[] = $current; + $set = self::replaceAmountTrigger($set); + $return[] = $set; } } diff --git a/app/Http/Requests/RuleGroupFormRequest.php b/app/Http/Requests/RuleGroupFormRequest.php index 5cb9b2c9be..3b23ecc0f7 100644 --- a/app/Http/Requests/RuleGroupFormRequest.php +++ b/app/Http/Requests/RuleGroupFormRequest.php @@ -1,4 +1,5 @@ route()->parameter('ruleGroup'); if (null !== $ruleGroup) { - $titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,' . $ruleGroup->id; + $titleRule = 'required|between:1,100|uniqueObjectForUser:rule_groups,title,'.$ruleGroup->id; } return [ 'title' => $titleRule, 'description' => 'between:1,5000|nullable', - 'active' => [new IsBoolean], + 'active' => [new IsBoolean()], ]; } } diff --git a/app/Http/Requests/SelectTransactionsRequest.php b/app/Http/Requests/SelectTransactionsRequest.php index e52c1d3cfd..c7a84cd23a 100644 --- a/app/Http/Requests/SelectTransactionsRequest.php +++ b/app/Http/Requests/SelectTransactionsRequest.php @@ -1,4 +1,5 @@ addDay()->format('Y-m-d'); return [ - 'start' => 'required|date|after:' . $first, - 'end' => 'required|date|before:' . $today, + 'start' => 'required|date|after:'.$first, + 'end' => 'required|date|before:'.$today, 'accounts' => 'required', 'accounts.*' => 'required|exists:accounts,id|belongsToUser:accounts', ]; diff --git a/app/Http/Requests/TagFormRequest.php b/app/Http/Requests/TagFormRequest.php index 61255d00ed..25adcd9450 100644 --- a/app/Http/Requests/TagFormRequest.php +++ b/app/Http/Requests/TagFormRequest.php @@ -1,4 +1,5 @@ appendLocationData($data, 'location'); - } /** @@ -67,7 +69,7 @@ class TagFormRequest extends FormRequest $tagRule = 'required|min:1|uniqueObjectForUser:tags,tag'; if (null !== $tag) { $idRule = 'belongsToUser:tags'; - $tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,' . $tag->id; + $tagRule = 'required|min:1|uniqueObjectForUser:tags,tag,'.$tag->id; } $rules = [ diff --git a/app/Http/Requests/TestRuleFormRequest.php b/app/Http/Requests/TestRuleFormRequest.php index 5c7b7d920b..3c6d7bdf37 100644 --- a/app/Http/Requests/TestRuleFormRequest.php +++ b/app/Http/Requests/TestRuleFormRequest.php @@ -1,4 +1,5 @@ getTriggers(); return [ - 'rule-trigger.*' => 'required|min:1|in:' . implode(',', $validTriggers), + 'rule-trigger.*' => 'required|min:1|in:'.implode(',', $validTriggers), 'rule-trigger-value.*' => 'required|min:1|ruleTriggerValue', ]; } diff --git a/app/Http/Requests/TokenFormRequest.php b/app/Http/Requests/TokenFormRequest.php index e7c45ad2cc..8245fafa37 100644 --- a/app/Http/Requests/TokenFormRequest.php +++ b/app/Http/Requests/TokenFormRequest.php @@ -1,4 +1,5 @@ . + */ + +namespace FireflyIII\Http\Requests; + +use FireflyIII\Support\Request\ChecksLogin; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Foundation\Http\FormRequest; + +class TriggerRecurrenceRequest extends FormRequest +{ + use ConvertsDataTypes; + use ChecksLogin; + + /** + * Returns the data required by the controller. + * + * @return array + */ + public function getAll(): array + { + return [ + 'date' => $this->getCarbonDate('date'), + ]; + } + + /** + * Rules for this request. + * + * @return array + */ + public function rules(): array + { + return [ + 'date' => 'required|date', + ]; + } +} diff --git a/app/Http/Requests/UserFormRequest.php b/app/Http/Requests/UserFormRequest.php index a10ef457b7..ceea33a1a9 100644 --- a/app/Http/Requests/UserFormRequest.php +++ b/app/Http/Requests/UserFormRequest.php @@ -1,4 +1,5 @@ findBudgetLimit($autoBudget->budget, $start, $end); - if (null === $budgetLimit && AutoBudget::AUTO_BUDGET_RESET === (int) $autoBudget->auto_budget_type) { + if (null === $budgetLimit && AutoBudget::AUTO_BUDGET_RESET === (int)$autoBudget->auto_budget_type) { // that's easy: create one. // do nothing else. $this->createBudgetLimit($autoBudget, $start, $end); @@ -139,7 +142,7 @@ class CreateAutoBudgetLimits implements ShouldQueue return; } - if (null === $budgetLimit && AutoBudget::AUTO_BUDGET_ROLLOVER === (int) $autoBudget->auto_budget_type) { + if (null === $budgetLimit && AutoBudget::AUTO_BUDGET_ROLLOVER === (int)$autoBudget->auto_budget_type) { // budget limit exists already, $this->createRollover($autoBudget); Log::debug(sprintf('Done with auto budget #%d', $autoBudget->id)); @@ -150,46 +153,49 @@ class CreateAutoBudgetLimits implements ShouldQueue } /** - * @param AutoBudget $autoBudget + * @param AutoBudget $autoBudget * * @return bool * @throws FireflyException */ private function isMagicDay(AutoBudget $autoBudget): bool { - switch ($autoBudget->period) { - default: - throw new FireflyException(sprintf('isMagicDay() can\'t handle period "%s"', $autoBudget->period)); - case 'daily': - // every day is magic! - return true; - case 'weekly': - // fire on Monday. - return $this->date->isMonday(); - case 'monthly': - return 1 === $this->date->day; - case 'quarterly': - $format = 'm-d'; - $value = $this->date->format($format); - - return in_array($value, ['01-01', '04-01', '07-01', '10-01'], true); - case 'half_year': - $format = 'm-d'; - $value = $this->date->format($format); - - return in_array($value, ['01-01', '07-01'], true); - case 'yearly': - $format = 'm-d'; - $value = $this->date->format($format); - - return '01-01' === $value; + if ('daily' === $autoBudget->period) { + return true; } + + if ('weekly' === $autoBudget->period) { + return $this->date->isMonday(); + } + + if ('monthly' === $autoBudget->period) { + return 1 === $this->date->day; + } + if ('quarterly' === $autoBudget->period) { + $format = 'm-d'; + $value = $this->date->format($format); + + return in_array($value, ['01-01', '04-01', '07-01', '10-01'], true); + } + if ('half_year' === $autoBudget->period) { + $format = 'm-d'; + $value = $this->date->format($format); + + return in_array($value, ['01-01', '07-01'], true); + } + if ('yearly' === $autoBudget->period) { + $format = 'm-d'; + $value = $this->date->format($format); + + return '01-01' === $value; + } + throw new FireflyException(sprintf('isMagicDay() can\'t handle period "%s"', $autoBudget->period)); } /** - * @param Budget $budget - * @param Carbon $start - * @param Carbon $end + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end * * @return BudgetLimit|null */ @@ -211,10 +217,10 @@ class CreateAutoBudgetLimits implements ShouldQueue } /** - * @param AutoBudget $autoBudget - * @param Carbon $start - * @param Carbon $end - * @param string|null $amount + * @param AutoBudget $autoBudget + * @param Carbon $start + * @param Carbon $end + * @param string|null $amount */ private function createBudgetLimit(AutoBudget $autoBudget, Carbon $start, Carbon $end, ?string $amount = null) { @@ -222,7 +228,7 @@ class CreateAutoBudgetLimits implements ShouldQueue if (null !== $amount) { Log::debug(sprintf('Amount is overruled and will be set to %s', $amount)); } - $budgetLimit = new BudgetLimit; + $budgetLimit = new BudgetLimit(); $budgetLimit->budget()->associate($autoBudget->budget); $budgetLimit->transactionCurrency()->associate($autoBudget->transactionCurrency); $budgetLimit->start_date = $start; @@ -236,7 +242,7 @@ class CreateAutoBudgetLimits implements ShouldQueue } /** - * @param AutoBudget $autoBudget + * @param AutoBudget $autoBudget * * @throws FireflyException */ @@ -277,17 +283,22 @@ class CreateAutoBudgetLimits implements ShouldQueue $repository = app(OperationsRepositoryInterface::class); $repository->setUser($autoBudget->budget->user); $spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection([$autoBudget->budget]), $autoBudget->transactionCurrency); - $currencyId = (int) $autoBudget->transaction_currency_id; + $currencyId = (int)$autoBudget->transaction_currency_id; $spentAmount = $spent[$currencyId]['sum'] ?? '0'; Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount)); - // previous budget limit + this period + spent - $totalAmount = bcadd(bcadd($budgetLimit->amount, $autoBudget->amount), $spentAmount); - Log::debug(sprintf('Total amount for current budget period will be %s', $totalAmount)); + // if you spent more in previous budget period, than whatever you had previous budget period, the amount resets + // previous budget limit + spent + $budgetLeft = bcadd($budgetLimit->amount, $spentAmount); + $totalAmount = $autoBudget->amount; + Log::debug(sprintf('Total amount left for previous budget period is %s', $budgetLeft)); - if (1 !== bccomp($totalAmount, '0')) { - Log::info(sprintf('The total amount is negative, so it will be reset to %s.', $totalAmount)); - $totalAmount = $autoBudget->amount; + if (-1 !== bccomp('0', $budgetLeft)) { + Log::info(sprintf('The amount left is negative, so it will be reset to %s.', $totalAmount)); + } + if (1 !== bccomp('0', $budgetLeft)) { + $totalAmount = bcadd($budgetLeft, $budgetLimit->amount); + Log::info(sprintf('The amount left is positive, so the new amount will be %s.', $totalAmount)); } // create budget limit: @@ -296,7 +307,7 @@ class CreateAutoBudgetLimits implements ShouldQueue } /** - * @param Carbon $date + * @param Carbon $date */ public function setDate(Carbon $date): void { diff --git a/app/Jobs/CreateRecurringTransactions.php b/app/Jobs/CreateRecurringTransactions.php index f9ea125eab..8d7baff791 100644 --- a/app/Jobs/CreateRecurringTransactions.php +++ b/app/Jobs/CreateRecurringTransactions.php @@ -50,7 +50,10 @@ use Log; */ class CreateRecurringTransactions implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; public int $created; public int $executed; @@ -58,7 +61,9 @@ class CreateRecurringTransactions implements ShouldQueue private Carbon $date; private bool $force; private TransactionGroupRepositoryInterface $groupRepository; + private Collection $groups; private JournalRepositoryInterface $journalRepository; + private Collection $recurrences; private RecurringRepositoryInterface $repository; /** @@ -66,20 +71,19 @@ class CreateRecurringTransactions implements ShouldQueue * * @codeCoverageIgnore * - * @param Carbon|null $date + * @param Carbon|null $date */ public function __construct(?Carbon $date) { + $newDate = new Carbon(); + $newDate->startOfDay(); + $this->date = $newDate; + if (null !== $date) { $newDate = clone $date; $newDate->startOfDay(); $this->date = $newDate; } - if (null === $date) { - $newDate = new Carbon; - $newDate->startOfDay(); - $this->date = $newDate; - } $this->repository = app(RecurringRepositoryInterface::class); $this->journalRepository = app(JournalRepositoryInterface::class); $this->groupRepository = app(TransactionGroupRepositoryInterface::class); @@ -87,29 +91,48 @@ class CreateRecurringTransactions implements ShouldQueue $this->submitted = 0; $this->executed = 0; $this->created = 0; + $this->recurrences = new Collection(); + $this->groups = new Collection(); Log::debug(sprintf('Created new CreateRecurringTransactions("%s")', $this->date->format('Y-m-d'))); } + /** + * @return Collection + */ + public function getGroups(): Collection + { + return $this->groups; + } + /** * Execute the job. */ public function handle(): void { Log::debug(sprintf('Now at start of CreateRecurringTransactions() job for %s.', $this->date->format('D d M Y'))); - $recurrences = $this->repository->getAll(); + + // only use recurrences from database if there is no collection submitted. + if (0 !== count($this->recurrences)) { + Log::debug('Using predetermined set of recurrences.'); + } + if (0 === count($this->recurrences)) { + Log::debug('Grab all recurrences from the database.'); + $this->recurrences = $this->repository->getAll(); + } + $result = []; - $count = $recurrences->count(); + $count = $this->recurrences->count(); $this->submitted = $count; Log::debug(sprintf('Count of collection is %d', $count)); // filter recurrences: - $filtered = $this->filterRecurrences($recurrences); + $filtered = $this->filterRecurrences($this->recurrences); Log::debug(sprintf('Left after filtering is %d', $filtered->count())); /** @var Recurrence $recurrence */ foreach ($filtered as $recurrence) { if (!array_key_exists($recurrence->user_id, $result)) { - $result[$recurrence->user_id] = new Collection; + $result[$recurrence->user_id] = new Collection(); } $this->repository->setUser($recurrence->user); $this->journalRepository->setUser($recurrence->user); @@ -138,7 +161,7 @@ class CreateRecurringTransactions implements ShouldQueue } /** - * @param Collection $recurrences + * @param Collection $recurrences * * @return Collection */ @@ -154,7 +177,7 @@ class CreateRecurringTransactions implements ShouldQueue /** * Is the info in the recurrence valid? * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return bool * @@ -176,6 +199,7 @@ class CreateRecurringTransactions implements ShouldQueue return false; } + // is no longer running if ($this->repeatUntilHasPassed($recurrence)) { Log::info( @@ -218,7 +242,7 @@ class CreateRecurringTransactions implements ShouldQueue /** * Return recurring transaction is active. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return bool */ @@ -230,7 +254,7 @@ class CreateRecurringTransactions implements ShouldQueue /** * Return true if the $repeat_until date is in the past. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return bool */ @@ -243,7 +267,7 @@ class CreateRecurringTransactions implements ShouldQueue /** * Has the recurrence started yet? * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return bool */ @@ -258,7 +282,7 @@ class CreateRecurringTransactions implements ShouldQueue /** * Get the start date of a recurrence. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return Carbon */ @@ -275,7 +299,7 @@ class CreateRecurringTransactions implements ShouldQueue /** * Has the recurrence fired today. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return bool */ @@ -288,7 +312,7 @@ class CreateRecurringTransactions implements ShouldQueue * Separate method that will loop all repetitions and do something with it. Will return * all created transaction journals. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return Collection * @throws DuplicateTransactionException @@ -296,7 +320,7 @@ class CreateRecurringTransactions implements ShouldQueue */ private function handleRepetitions(Recurrence $recurrence): Collection { - $collection = new Collection; + $collection = new Collection(); /** @var RecurrenceRepetition $repetition */ foreach ($recurrence->recurrenceRepetitions as $repetition) { Log::debug( @@ -309,7 +333,7 @@ class CreateRecurringTransactions implements ShouldQueue ); // start looping from $startDate to today perhaps we have a hit? - // add two days to $this->date so we always include the weekend. + // add two days to $this->date, so we always include the weekend. $includeWeekend = clone $this->date; $includeWeekend->addDays(2); $occurrences = $this->repository->getOccurrencesInRange($repetition, $recurrence->first_date, $includeWeekend); @@ -326,9 +350,9 @@ class CreateRecurringTransactions implements ShouldQueue /** * Check if the occurences should be executed. * - * @param Recurrence $recurrence - * @param RecurrenceRepetition $repetition - * @param array $occurrences + * @param Recurrence $recurrence + * @param RecurrenceRepetition $repetition + * @param array $occurrences * * @return Collection * @throws DuplicateTransactionException @@ -336,7 +360,7 @@ class CreateRecurringTransactions implements ShouldQueue */ private function handleOccurrences(Recurrence $recurrence, RecurrenceRepetition $repetition, array $occurrences): Collection { - $collection = new Collection; + $collection = new Collection(); /** @var Carbon $date */ foreach ($occurrences as $date) { $result = $this->handleOccurrence($recurrence, $repetition, $date); @@ -349,9 +373,9 @@ class CreateRecurringTransactions implements ShouldQueue } /** - * @param Recurrence $recurrence - * @param RecurrenceRepetition $repetition - * @param Carbon $date + * @param Recurrence $recurrence + * @param RecurrenceRepetition $repetition + * @param Carbon $date * * @return TransactionGroup|null * @throws DuplicateTransactionException @@ -361,7 +385,6 @@ class CreateRecurringTransactions implements ShouldQueue { $date->startOfDay(); if ($date->ne($this->date)) { - return null; } Log::debug(sprintf('%s IS today (%s)', $date->format('Y-m-d'), $this->date->format('Y-m-d'))); @@ -374,18 +397,30 @@ class CreateRecurringTransactions implements ShouldQueue return null; } + if ($this->repository->createdPreviously($recurrence, $date) && false === $this->force) { + Log::info('There is a transaction already made for this date, so will not be created now'); + + return null; + } + + if ($journalCount > 0 && true === $this->force) { - Log::warning(sprintf('Already created %d groups for date %s but FORCED to continue.', $journalCount, $date->format('Y-m-d'))); + app('log')->warning(sprintf('Already created %d groups for date %s but FORCED to continue.', $journalCount, $date->format('Y-m-d'))); } // create transaction array and send to factory. $groupTitle = null; - if ($recurrence->recurrenceTransactions->count() > 1) { + $count = $recurrence->recurrenceTransactions->count(); + if ($count > 1) { /** @var RecurrenceTransaction $first */ $first = $recurrence->recurrenceTransactions()->first(); $groupTitle = $first->description; + } + if (0 === $count) { + Log::error('No transactions to be created in this recurrence. Cannot continue.'); + return null; } $array = [ @@ -400,7 +435,8 @@ class CreateRecurringTransactions implements ShouldQueue Log::info(sprintf('Created new transaction group #%d', $group->id)); // trigger event: - event(new StoredTransactionGroup($group, $recurrence->apply_rules)); + event(new StoredTransactionGroup($group, $recurrence->apply_rules, true)); + $this->groups->push($group); // update recurring thing: $recurrence->latest_date = $date; @@ -412,9 +448,9 @@ class CreateRecurringTransactions implements ShouldQueue /** * Get transaction information from a recurring transaction. * - * @param Recurrence $recurrence - * @param RecurrenceRepetition $repetition - * @param Carbon $date + * @param Recurrence $recurrence + * @param RecurrenceRepetition $repetition + * @param Carbon $date * * @return array * @@ -432,7 +468,7 @@ class CreateRecurringTransactions implements ShouldQueue 'type' => strtolower($recurrence->transactionType->type), 'date' => $date, 'user' => $recurrence->user_id, - 'currency_id' => (int) $transaction->transaction_currency_id, + 'currency_id' => (int)$transaction->transaction_currency_id, 'currency_code' => null, 'description' => $transactions->first()->description, 'amount' => $transaction->amount, @@ -449,9 +485,9 @@ class CreateRecurringTransactions implements ShouldQueue 'foreign_amount' => $transaction->foreign_amount, 'reconciled' => false, 'identifier' => $index, - 'recurrence_id' => (int) $recurrence->id, + 'recurrence_id' => (int)$recurrence->id, 'order' => $index, - 'notes' => (string) trans('firefly.created_from_recurrence', ['id' => $recurrence->id, 'title' => $recurrence->title]), + 'notes' => (string)trans('firefly.created_from_recurrence', ['id' => $recurrence->id, 'title' => $recurrence->title]), 'tags' => $this->repository->getTags($transaction), 'piggy_bank_id' => $this->repository->getPiggyBank($transaction), 'piggy_bank_name' => null, @@ -459,6 +495,7 @@ class CreateRecurringTransactions implements ShouldQueue 'bill_name' => null, 'recurrence_total' => $total, 'recurrence_count' => $count, + 'recurrence_date' => $date, ]; $return[] = $single; } @@ -467,7 +504,7 @@ class CreateRecurringTransactions implements ShouldQueue } /** - * @param Carbon $date + * @param Carbon $date */ public function setDate(Carbon $date): void { @@ -477,10 +514,18 @@ class CreateRecurringTransactions implements ShouldQueue } /** - * @param bool $force + * @param bool $force */ public function setForce(bool $force): void { $this->force = $force; } + + /** + * @param Collection $recurrences + */ + public function setRecurrences(Collection $recurrences): void + { + $this->recurrences = $recurrences; + } } diff --git a/app/Jobs/DownloadExchangeRates.php b/app/Jobs/DownloadExchangeRates.php new file mode 100644 index 0000000000..3e47c4e045 --- /dev/null +++ b/app/Jobs/DownloadExchangeRates.php @@ -0,0 +1,188 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Jobs; + +use Carbon\Carbon; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use FireflyIII\Repositories\User\UserRepositoryInterface; +use GuzzleHttp\Client; +use Illuminate\Bus\Queueable; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Bus\Dispatchable; +use Illuminate\Queue\InteractsWithQueue; +use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Collection; +use Log; + +/** + * Class DownloadExchangeRates + */ +class DownloadExchangeRates implements ShouldQueue +{ + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; + + private array $active; + private Carbon $date; + private CurrencyRepositoryInterface $repository; + private Collection $users; + + /** + * Create a new job instance. + * + * @codeCoverageIgnore + * + * @param Carbon|null $date + */ + public function __construct(?Carbon $date) + { + $this->active = []; + $this->repository = app(CurrencyRepositoryInterface::class); + + // get all users: + /** @var UserRepositoryInterface $userRepository */ + $userRepository = app(UserRepositoryInterface::class); + $this->users = $userRepository->all(); + + if (null !== $date) { + $newDate = clone $date; + $newDate->startOfDay(); + $this->date = $newDate; + Log::debug(sprintf('Created new DownloadExchangeRates("%s")', $this->date->format('Y-m-d'))); + } + } + + /** + * Execute the job. + */ + public function handle(): void + { + Log::debug('Now in handle()'); + $currencies = $this->repository->get(); + + /** @var TransactionCurrency $currency */ + foreach ($currencies as $currency) { + $this->downloadRates($currency); + } + } + + /** + * @param TransactionCurrency $currency + * @return void + */ + private function downloadRates(TransactionCurrency $currency): void + { + Log::debug(sprintf('Now downloading new exchange rates for currency %s.', $currency->code)); + $base = sprintf('%s/%s/%s', (string)config('cer.url'), $this->date->year, $this->date->isoWeek); + $client = new Client(); + $url = sprintf('%s/%s.json', $base, $currency->code); + $res = $client->get($url); + $statusCode = $res->getStatusCode(); + if (200 !== $statusCode) { + app('log')->warning(sprintf('Trying to grab "%s" resulted in status code %d.', $url, $statusCode)); + return; + } + $body = (string)$res->getBody(); + $json = json_decode($body, true); + if (false === $json || null === $json) { + app('log')->warning(sprintf('Trying to grab "%s" resulted in bad JSON.', $url)); + return; + } + $date = Carbon::createFromFormat('Y-m-d', $json['date']); + $this->saveRates($currency, $date, $json['rates']); + } + + /** + * @param TransactionCurrency $currency + * @param array $rates + * @return void + */ + private function saveRates(TransactionCurrency $currency, Carbon $date, array $rates): void + { + foreach ($rates as $code => $rate) { + $to = $this->getCurrency($code); + if (null === $to) { + Log::debug(sprintf('Currency %s is not in use, do not save rate.', $code)); + continue; + } + Log::debug(sprintf('Currency %s is in use.', $code)); + $this->saveRate($currency, $to, $date, $rate); + } + } + + /** + * @param string $code + * @return TransactionCurrency|null + */ + private function getCurrency(string $code): ?TransactionCurrency + { + // if we have it already, don't bother searching for it again. + if (array_key_exists($code, $this->active)) { + Log::debug(sprintf('Already know what the result is of searching for %s', $code)); + return $this->active[$code]; + } + // find it in the database. + $currency = $this->repository->findByCode($code); + if (null === $currency) { + Log::debug(sprintf('Did not find currency %s.', $code)); + $this->active[$code] = null; + return null; + } + if (false === $currency->enabled) { + Log::debug(sprintf('Currency %s is not enabled.', $code)); + $this->active[$code] = null; + return null; + } + Log::debug(sprintf('Currency %s is enabled.', $code)); + $this->active[$code] = $currency; + + return $currency; + } + + private function saveRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date, float $rate): void + { + foreach ($this->users as $user) { + $this->repository->setUser($user); + $existing = $this->repository->getExchangeRate($from, $to, $date); + if (null === $existing) { + Log::debug(sprintf('Saved rate from %s to %s for user #%d.', $from->code, $to->code, $user->id)); + $this->repository->setExchangeRate($from, $to, $date, $rate); + } + } + } + + /** + * @param Carbon $date + */ + public function setDate(Carbon $date): void + { + $newDate = clone $date; + $newDate->startOfDay(); + $this->date = $newDate; + } +} diff --git a/app/Jobs/Job.php b/app/Jobs/Job.php index 7562dbfa3c..05b4952226 100644 --- a/app/Jobs/Job.php +++ b/app/Jobs/Job.php @@ -1,4 +1,5 @@ exception; $args['loggedIn'] = $this->userData['id'] > 0; $args['user'] = $this->userData; @@ -82,12 +86,12 @@ class MailError extends Job implements ShouldQueue $args, function (Message $message) use ($email) { if ('mail@example.com' !== $email) { - $message->to($email, $email)->subject((string) trans('email.error_subject')); + $message->to($email, $email)->subject((string)trans('email.error_subject')); } } ); - } catch (Exception $e) { // @phpstan-ignore-line - Log::error('Exception when mailing: ' . $e->getMessage()); + } catch (Exception $e) { // intentional generic exception + throw new FireflyException($e->getMessage(), 0, $e); } } } diff --git a/app/Jobs/SendWebhookMessage.php b/app/Jobs/SendWebhookMessage.php index 26923829da..05efaeb8a2 100644 --- a/app/Jobs/SendWebhookMessage.php +++ b/app/Jobs/SendWebhookMessage.php @@ -38,14 +38,17 @@ use Log; */ class SendWebhookMessage implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; private WebhookMessage $message; /** * Create a new job instance. * - * @param WebhookMessage $message + * @param WebhookMessage $message */ public function __construct(WebhookMessage $message) { diff --git a/app/Jobs/WarnAboutBills.php b/app/Jobs/WarnAboutBills.php index 36ce43ab3b..647e3d0372 100644 --- a/app/Jobs/WarnAboutBills.php +++ b/app/Jobs/WarnAboutBills.php @@ -39,31 +39,33 @@ use Log; */ class WarnAboutBills implements ShouldQueue { - use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; + use Dispatchable; + use InteractsWithQueue; + use Queueable; + use SerializesModels; private Carbon $date; private bool $force; - /** * Create a new job instance. * * @codeCoverageIgnore * - * @param Carbon|null $date + * @param Carbon|null $date */ public function __construct(?Carbon $date) { + $newDate = new Carbon(); + $newDate->startOfDay(); + $this->date = $newDate; + if (null !== $date) { $newDate = clone $date; $newDate->startOfDay(); $this->date = $newDate; } - if (null === $date) { - $newDate = new Carbon; - $newDate->startOfDay(); - $this->date = $newDate; - } + $this->force = false; Log::debug(sprintf('Created new WarnAboutBills("%s")', $this->date->format('Y-m-d'))); @@ -95,7 +97,7 @@ class WarnAboutBills implements ShouldQueue } /** - * @param Bill $bill + * @param Bill $bill * @return bool */ private function hasDateFields(Bill $bill): bool @@ -112,8 +114,8 @@ class WarnAboutBills implements ShouldQueue } /** - * @param Bill $bill - * @param string $field + * @param Bill $bill + * @param string $field * @return bool */ private function needsWarning(Bill $bill, string $field): bool @@ -131,8 +133,8 @@ class WarnAboutBills implements ShouldQueue } /** - * @param Bill $bill - * @param string $field + * @param Bill $bill + * @param string $field * @return int */ private function getDiff(Bill $bill, string $field): int @@ -143,8 +145,8 @@ class WarnAboutBills implements ShouldQueue } /** - * @param Bill $bill - * @param string $field + * @param Bill $bill + * @param string $field * @return void */ private function sendWarning(Bill $bill, string $field): void @@ -155,7 +157,7 @@ class WarnAboutBills implements ShouldQueue } /** - * @param Carbon $date + * @param Carbon $date */ public function setDate(Carbon $date): void { @@ -165,7 +167,7 @@ class WarnAboutBills implements ShouldQueue } /** - * @param bool $force + * @param bool $force */ public function setForce(bool $force): void { diff --git a/app/Mail/AccessTokenCreatedMail.php b/app/Mail/AccessTokenCreatedMail.php index 8450f76298..40dbbe2c27 100644 --- a/app/Mail/AccessTokenCreatedMail.php +++ b/app/Mail/AccessTokenCreatedMail.php @@ -34,8 +34,8 @@ use Illuminate\Queue\SerializesModels; */ class AccessTokenCreatedMail extends Mailable { - - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; /** * AccessTokenCreatedMail constructor. @@ -53,6 +53,6 @@ class AccessTokenCreatedMail extends Mailable { return $this ->markdown('emails.token-created') - ->subject((string) trans('email.access_token_created_subject')); + ->subject((string)trans('email.access_token_created_subject')); } } diff --git a/app/Mail/AdminTestMail.php b/app/Mail/AdminTestMail.php index 023a57adc2..bcef6cda6e 100644 --- a/app/Mail/AdminTestMail.php +++ b/app/Mail/AdminTestMail.php @@ -1,4 +1,5 @@ email = $email; } /** @@ -58,6 +57,6 @@ class AdminTestMail extends Mailable { return $this ->markdown('emails.admin-test') - ->subject((string) trans('email.admin_test_subject')); + ->subject((string)trans('email.admin_test_subject')); } } diff --git a/app/Mail/BillWarningMail.php b/app/Mail/BillWarningMail.php index de7e413066..308d86c706 100644 --- a/app/Mail/BillWarningMail.php +++ b/app/Mail/BillWarningMail.php @@ -31,7 +31,8 @@ use Illuminate\Queue\SerializesModels; class BillWarningMail extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; public Bill $bill; public int $diff; @@ -40,9 +41,9 @@ class BillWarningMail extends Mailable /** * ConfirmEmailChangeMail constructor. * - * @param Bill $bill - * @param string $field - * @param int $diff + * @param Bill $bill + * @param string $field + * @param int $diff */ public function __construct(Bill $bill, string $field, int $diff) { @@ -58,9 +59,9 @@ class BillWarningMail extends Mailable */ public function build(): self { - $subject = (string) trans(sprintf('email.bill_warning_subject_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]); + $subject = (string)trans(sprintf('email.bill_warning_subject_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]); if (0 === $this->diff) { - $subject = (string) trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]); + $subject = (string)trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]); } return $this diff --git a/app/Mail/ConfirmEmailChangeMail.php b/app/Mail/ConfirmEmailChangeMail.php index bdd6110ff7..7ad5fe34ac 100644 --- a/app/Mail/ConfirmEmailChangeMail.php +++ b/app/Mail/ConfirmEmailChangeMail.php @@ -1,4 +1,5 @@ view('emails.confirm-email-change-html') //->text('emails.confirm-email-change-text') ->markdown('emails.confirm-email-change') - ->subject((string) trans('email.email_change_subject')); + ->subject((string)trans('email.email_change_subject')); } } diff --git a/app/Mail/InvitationMail.php b/app/Mail/InvitationMail.php new file mode 100644 index 0000000000..9f82a8f6f3 --- /dev/null +++ b/app/Mail/InvitationMail.php @@ -0,0 +1,67 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Mail; + +use Illuminate\Bus\Queueable; +use Illuminate\Mail\Mailable; +use Illuminate\Queue\SerializesModels; + +class InvitationMail extends Mailable +{ + use Queueable; + use SerializesModels; + + public string $admin; + public string $host; + public string $invitee; + public string $url; + + /** + * OAuthTokenCreatedMail constructor. + * + * @param string $invitee + * @param string $admin + * @param string $url + */ + public function __construct(string $invitee, string $admin, string $url) + { + $this->invitee = $invitee; + $this->admin = $admin; + $this->url = $url; + $this->host = parse_url($url, PHP_URL_HOST); + } + + /** + * Build the message. + * + * @return $this + */ + public function build(): self + { + return $this + ->markdown('emails.invitation') + ->subject((string)trans('email.invite_user_subject')); + } +} diff --git a/app/Mail/NewIPAddressWarningMail.php b/app/Mail/NewIPAddressWarningMail.php index f387f1c84d..c40eed2d28 100644 --- a/app/Mail/NewIPAddressWarningMail.php +++ b/app/Mail/NewIPAddressWarningMail.php @@ -24,17 +24,19 @@ declare(strict_types=1); namespace FireflyIII\Mail; -use Exception; +use FireflyIII\Exceptions\FireflyException; use Illuminate\Bus\Queueable; use Illuminate\Mail\Mailable; use Illuminate\Queue\SerializesModels; +use Log; /** * Class NewIPAddressWarningMail */ class NewIPAddressWarningMail extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; public string $host; public string $ipAddress; @@ -43,7 +45,7 @@ class NewIPAddressWarningMail extends Mailable /** * OAuthTokenCreatedMail constructor. * - * @param string $ipAddress + * @param string $ipAddress */ public function __construct(string $ipAddress) { @@ -57,11 +59,12 @@ class NewIPAddressWarningMail extends Mailable */ public function build(): self { - $this->time = now(config('app.timezone'))->isoFormat((string) trans('config.date_time_js')); + $this->time = now(config('app.timezone'))->isoFormat((string)trans('config.date_time_js')); $this->host = ''; try { - $hostName = gethostbyaddr($this->ipAddress); - } catch (Exception $e) { + $hostName = app('steam')->getHostName($this->ipAddress); + } catch (FireflyException $e) { + Log::error($e->getMessage()); $hostName = $this->ipAddress; } if ($hostName !== $this->ipAddress) { @@ -70,6 +73,6 @@ class NewIPAddressWarningMail extends Mailable return $this ->markdown('emails.new-ip') - ->subject((string) trans('email.login_from_new_ip')); + ->subject((string)trans('email.login_from_new_ip')); } } diff --git a/app/Mail/OAuthTokenCreatedMail.php b/app/Mail/OAuthTokenCreatedMail.php index 796f980fc4..69bc8cf471 100644 --- a/app/Mail/OAuthTokenCreatedMail.php +++ b/app/Mail/OAuthTokenCreatedMail.php @@ -35,14 +35,15 @@ use Laravel\Passport\Client; */ class OAuthTokenCreatedMail extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; public Client $client; /** * OAuthTokenCreatedMail constructor. * - * @param Client $client + * @param Client $client */ public function __construct(Client $client) { @@ -58,6 +59,6 @@ class OAuthTokenCreatedMail extends Mailable { return $this ->markdown('emails.oauth-client-created') - ->subject((string) trans('email.oauth_created_subject')); + ->subject((string)trans('email.oauth_created_subject')); } } diff --git a/app/Mail/RegisteredUser.php b/app/Mail/RegisteredUser.php index 1ab61c951f..b68e2449b7 100644 --- a/app/Mail/RegisteredUser.php +++ b/app/Mail/RegisteredUser.php @@ -36,14 +36,15 @@ use Illuminate\Queue\SerializesModels; */ class RegisteredUser extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; public string $address; /** * Create a new message instance. * - * @param string $address + * @param string $address */ public function __construct(string $address) { @@ -59,6 +60,6 @@ class RegisteredUser extends Mailable { return $this ->markdown('emails.registered') - ->subject((string) trans('email.registered_subject')); + ->subject((string)trans('email.registered_subject')); } } diff --git a/app/Mail/ReportNewJournalsMail.php b/app/Mail/ReportNewJournalsMail.php index feff32bdea..2b0154ce8d 100644 --- a/app/Mail/ReportNewJournalsMail.php +++ b/app/Mail/ReportNewJournalsMail.php @@ -1,4 +1,5 @@ markdown('emails.report-new-journals') - ->subject((string) trans_choice('email.new_journals_subject', $this->groups->count())); + ->subject((string)trans_choice('email.new_journals_subject', $this->groups->count())); } private function transform(): void diff --git a/app/Mail/RequestedNewPassword.php b/app/Mail/RequestedNewPassword.php index 2aedd0aa4a..865280d00d 100644 --- a/app/Mail/RequestedNewPassword.php +++ b/app/Mail/RequestedNewPassword.php @@ -35,14 +35,15 @@ use Illuminate\Queue\SerializesModels; */ class RequestedNewPassword extends Mailable { - use Queueable, SerializesModels; + use Queueable; + use SerializesModels; public string $url; /** * RequestedNewPassword constructor. * - * @param string $url + * @param string $url */ public function __construct(string $url) { @@ -58,6 +59,6 @@ class RequestedNewPassword extends Mailable { return $this ->markdown('emails.password') - ->subject((string) trans('email.reset_pw_subject')); + ->subject((string)trans('email.reset_pw_subject')); } } diff --git a/app/Mail/UndoEmailChangeMail.php b/app/Mail/UndoEmailChangeMail.php index c4247fd8af..df4a5df620 100644 --- a/app/Mail/UndoEmailChangeMail.php +++ b/app/Mail/UndoEmailChangeMail.php @@ -1,4 +1,5 @@ markdown('emails.undo-email-change') - ->subject((string) trans('email.email_change_subject')); + ->subject((string)trans('email.email_change_subject')); } } diff --git a/app/Models/Account.php b/app/Models/Account.php index 5575ab5631..ba49d190ec 100644 --- a/app/Models/Account.php +++ b/app/Models/Account.php @@ -1,4 +1,5 @@ check()) { - $accountId = (int) $value; + $accountId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Account $account */ - $account = $user->accounts()->find($accountId); + $account = $user->accounts()->with(['accountType'])->find($accountId); if (null !== $account) { return $account; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @return BelongsTo + * @codeCoverageIgnore + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -246,12 +256,12 @@ class Account extends Model /** * @codeCoverageIgnore * - * @param EloquentBuilder $query - * @param array $types + * @param EloquentBuilder $query + * @param array $types */ public function scopeAccountTypeIn(EloquentBuilder $query, array $types): void { - if (null === $this->joinedAccountTypes) { + if (false === $this->joinedAccountTypes) { $query->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id'); $this->joinedAccountTypes = true; } @@ -261,13 +271,13 @@ class Account extends Model /** * @codeCoverageIgnore * - * @param mixed $value + * @param mixed $value * * @codeCoverageIgnore */ public function setVirtualBalanceAttribute($value): void { - $value = (string) $value; + $value = (string)$value; if ('' === $value) { $value = null; } @@ -283,15 +293,6 @@ class Account extends Model return $this->hasMany(Transaction::class); } - /** - * @return BelongsTo - * @codeCoverageIgnore - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } - /** * Get the virtual balance * @@ -300,7 +301,7 @@ class Account extends Model protected function virtualBalance(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string) $value, ); } } diff --git a/app/Models/AccountMeta.php b/app/Models/AccountMeta.php index 4f41f9aaf9..1047fa1a72 100644 --- a/app/Models/AccountMeta.php +++ b/app/Models/AccountMeta.php @@ -1,4 +1,5 @@ check()) { - $attachmentId = (int) $value; + $attachmentId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Attachment $attachment */ @@ -120,7 +121,16 @@ class Attachment extends Model return $attachment; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -143,7 +153,7 @@ class Attachment extends Model */ public function fileName(): string { - return sprintf('at-%s.data', (string) $this->id); + return sprintf('at-%s.data', (string)$this->id); } /** @@ -154,13 +164,4 @@ class Attachment extends Model { return $this->morphMany(Note::class, 'noteable'); } - - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } } diff --git a/app/Models/AuditLogEntry.php b/app/Models/AuditLogEntry.php new file mode 100644 index 0000000000..86f2a94283 --- /dev/null +++ b/app/Models/AuditLogEntry.php @@ -0,0 +1,96 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Models; + +use Eloquent; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\MorphTo; +use Illuminate\Database\Eloquent\SoftDeletes; +use Illuminate\Support\Carbon; + +/** + * Class AuditLogEntry + * + * @property-read Model|Eloquent $auditable + * @property-read Model|Eloquent $changer + * @method static Builder|AuditLogEntry newModelQuery() + * @method static Builder|AuditLogEntry newQuery() + * @method static \Illuminate\Database\Query\Builder|AuditLogEntry onlyTrashed() + * @method static Builder|AuditLogEntry query() + * @method static \Illuminate\Database\Query\Builder|AuditLogEntry withTrashed() + * @method static \Illuminate\Database\Query\Builder|AuditLogEntry withoutTrashed() + * @mixin Eloquent + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $auditable_id + * @property string $auditable_type + * @property int $changer_id + * @property string $changer_type + * @property string $action + * @property array|null $before + * @property array|null $after + * @method static Builder|AuditLogEntry whereAction($value) + * @method static Builder|AuditLogEntry whereAfter($value) + * @method static Builder|AuditLogEntry whereAuditableId($value) + * @method static Builder|AuditLogEntry whereAuditableType($value) + * @method static Builder|AuditLogEntry whereBefore($value) + * @method static Builder|AuditLogEntry whereChangerId($value) + * @method static Builder|AuditLogEntry whereChangerType($value) + * @method static Builder|AuditLogEntry whereCreatedAt($value) + * @method static Builder|AuditLogEntry whereDeletedAt($value) + * @method static Builder|AuditLogEntry whereId($value) + * @method static Builder|AuditLogEntry whereUpdatedAt($value) + */ +class AuditLogEntry extends Model +{ + use SoftDeletes; + + protected $casts = [ + 'before' => 'array', + 'after' => 'array', + 'created_at' => 'datetime', + 'updated_at' => 'datetime', + 'deleted_at' => 'datetime', + ]; + + /** + * @codeCoverageIgnore + */ + public function auditable(): MorphTo + { + return $this->morphTo(); + } + + /** + * @codeCoverageIgnore + */ + public function changer(): MorphTo + { + return $this->morphTo(); + } +} diff --git a/app/Models/AutoBudget.php b/app/Models/AutoBudget.php index 432471dc33..ef6f4b41fc 100644 --- a/app/Models/AutoBudget.php +++ b/app/Models/AutoBudget.php @@ -35,16 +35,16 @@ use Illuminate\Support\Carbon; /** * FireflyIII\Models\AutoBudget * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $budget_id - * @property int $transaction_currency_id - * @property int $auto_budget_type - * @property string $amount - * @property string $period - * @property-read Budget $budget + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $budget_id + * @property int $transaction_currency_id + * @property int $auto_budget_type + * @property string $amount + * @property string $period + * @property-read Budget $budget * @property-read TransactionCurrency $transactionCurrency * @method static \Illuminate\Database\Eloquent\Builder|AutoBudget newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|AutoBudget newQuery() @@ -65,13 +65,11 @@ use Illuminate\Support\Carbon; */ class AutoBudget extends Model { - /** @var int When the auto-budget resets every period automatically. */ - public const AUTO_BUDGET_RESET = 1; - /** @var int When the auto-budget adds an amount every period automatically */ - public const AUTO_BUDGET_ROLLOVER = 2; - use SoftDeletes; + public const AUTO_BUDGET_RESET = 1; + public const AUTO_BUDGET_ROLLOVER = 2; + /** * @codeCoverageIgnore * @return BelongsTo @@ -96,7 +94,7 @@ class AutoBudget extends Model protected function amount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string) $value, ); } } diff --git a/app/Models/AvailableBudget.php b/app/Models/AvailableBudget.php index 8d82bf9069..3dbb68df3f 100644 --- a/app/Models/AvailableBudget.php +++ b/app/Models/AvailableBudget.php @@ -107,16 +107,7 @@ class AvailableBudget extends Model return $availableBudget; } } - throw new NotFoundHttpException; - } - - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function transactionCurrency(): BelongsTo - { - return $this->belongsTo(TransactionCurrency::class); + throw new NotFoundHttpException(); } /** @@ -129,8 +120,14 @@ class AvailableBudget extends Model } /** - * @return Attribute + * @codeCoverageIgnore + * @return BelongsTo */ + public function transactionCurrency(): BelongsTo + { + return $this->belongsTo(TransactionCurrency::class); + } + protected function amount(): Attribute { return Attribute::make( diff --git a/app/Models/Bill.php b/app/Models/Bill.php index 3d76819c94..4d5ad3c687 100644 --- a/app/Models/Bill.php +++ b/app/Models/Bill.php @@ -1,4 +1,5 @@ check()) { - $billId = (int) $value; + $billId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Bill $bill */ @@ -149,7 +163,16 @@ class Bill extends Model return $bill; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -181,21 +204,21 @@ class Bill extends Model /** * @codeCoverageIgnore * - * @param mixed $value + * @param mixed $value */ public function setAmountMaxAttribute($value): void { - $this->attributes['amount_max'] = (string) $value; + $this->attributes['amount_max'] = (string)$value; } /** - * @param mixed $value + * @param mixed $value * * @codeCoverageIgnore */ public function setAmountMinAttribute($value): void { - $this->attributes['amount_min'] = (string) $value; + $this->attributes['amount_min'] = (string)$value; } /** @@ -216,15 +239,6 @@ class Bill extends Model return $this->hasMany(TransactionJournal::class); } - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } - /** * Get the max amount * @@ -233,7 +247,7 @@ class Bill extends Model protected function amountMax(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string)$value, ); } @@ -245,7 +259,7 @@ class Bill extends Model protected function amountMin(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string)$value, ); } } diff --git a/app/Models/Budget.php b/app/Models/Budget.php index 96a7dce142..6b260adb25 100644 --- a/app/Models/Budget.php +++ b/app/Models/Budget.php @@ -1,4 +1,5 @@ check()) { - $budgetId = (int) $value; + $budgetId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Budget $budget */ @@ -122,7 +123,16 @@ class Budget extends Model return $budget; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -178,13 +188,4 @@ class Budget extends Model { return $this->belongsToMany(Transaction::class, 'budget_transaction', 'budget_id'); } - - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } } diff --git a/app/Models/BudgetLimit.php b/app/Models/BudgetLimit.php index aff5ed5157..fdb0c43cac 100644 --- a/app/Models/BudgetLimit.php +++ b/app/Models/BudgetLimit.php @@ -1,4 +1,5 @@ check()) { - $budgetLimitId = (int) $value; + $budgetLimitId = (int)$value; $budgetLimit = self::where('budget_limits.id', $budgetLimitId) ->leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id') ->where('budgets.user_id', auth()->user()->id) @@ -100,7 +101,7 @@ class BudgetLimit extends Model return $budgetLimit; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** @@ -129,7 +130,7 @@ class BudgetLimit extends Model protected function amount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string)$value, ); } } diff --git a/app/Models/Category.php b/app/Models/Category.php index 369ded30b0..24a9e2038f 100644 --- a/app/Models/Category.php +++ b/app/Models/Category.php @@ -38,23 +38,23 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * FireflyIII\Models\Category * - * @property int $id - * @property \Illuminate\Support\Carbon|null $created_at - * @property \Illuminate\Support\Carbon|null $updated_at - * @property \Illuminate\Support\Carbon|null $deleted_at - * @property int $user_id - * @property string $name - * @property Carbon $lastActivity - * @property bool $encrypted - * @property-read Collection|Attachment[] $attachments - * @property-read int|null $attachments_count - * @property-read Collection|Note[] $notes - * @property-read int|null $notes_count + * @property int $id + * @property \Illuminate\Support\Carbon|null $created_at + * @property \Illuminate\Support\Carbon|null $updated_at + * @property \Illuminate\Support\Carbon|null $deleted_at + * @property int $user_id + * @property string $name + * @property Carbon $lastActivity + * @property bool $encrypted + * @property-read Collection|Attachment[] $attachments + * @property-read int|null $attachments_count + * @property-read Collection|Note[] $notes + * @property-read int|null $notes_count * @property-read Collection|TransactionJournal[] $transactionJournals - * @property-read int|null $transaction_journals_count - * @property-read Collection|Transaction[] $transactions - * @property-read int|null $transactions_count - * @property-read User $user + * @property-read int|null $transaction_journals_count + * @property-read Collection|Transaction[] $transactions + * @property-read int|null $transactions_count + * @property-read User $user * @method static \Illuminate\Database\Eloquent\Builder|Category newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Category newQuery() * @method static Builder|Category onlyTrashed() @@ -69,7 +69,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @method static Builder|Category withTrashed() * @method static Builder|Category withoutTrashed() * @mixin Eloquent - * @property int|null $user_group_id + * @property int|null $user_group_id * @method static \Illuminate\Database\Eloquent\Builder|Category whereUserGroupId($value) */ class Category extends Model @@ -96,7 +96,7 @@ class Category extends Model /** * Route binder. Converts the key in the URL to the specified object (or throw 404). * - * @param string $value + * @param string $value * * @return Category * @throws NotFoundHttpException @@ -104,7 +104,7 @@ class Category extends Model public static function routeBinder(string $value): Category { if (auth()->check()) { - $categoryId = (int) $value; + $categoryId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Category $category */ @@ -113,7 +113,16 @@ class Category extends Model return $category; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -151,13 +160,4 @@ class Category extends Model { return $this->belongsToMany(Transaction::class, 'category_transaction', 'category_id'); } - - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } } diff --git a/app/Models/Configuration.php b/app/Models/Configuration.php index e3b19b6bec..ec88f81842 100644 --- a/app/Models/Configuration.php +++ b/app/Models/Configuration.php @@ -1,4 +1,5 @@ 'datetime', 'updated_at' => 'datetime', 'user_id' => 'int', @@ -73,6 +76,7 @@ class CurrencyExchangeRate extends Model 'to_currency_id' => 'int', 'date' => 'datetime', ]; + protected $fillable = ['user_id', 'from_currency_id', 'to_currency_id', 'date', 'rate']; /** * @codeCoverageIgnore @@ -107,7 +111,7 @@ class CurrencyExchangeRate extends Model protected function rate(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string) $value, ); } @@ -117,7 +121,7 @@ class CurrencyExchangeRate extends Model protected function userRate(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string) $value, ); } } diff --git a/app/Models/GroupMembership.php b/app/Models/GroupMembership.php index 1af5447862..e872ad78f0 100644 --- a/app/Models/GroupMembership.php +++ b/app/Models/GroupMembership.php @@ -34,16 +34,16 @@ use Illuminate\Support\Carbon; /** * Class GroupMembership * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property string|null $deleted_at - * @property int $user_id - * @property int $user_group_id - * @property int $user_role_id - * @property-read User $user + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property string|null $deleted_at + * @property int $user_id + * @property int $user_group_id + * @property int $user_role_id + * @property-read User $user * @property-read UserGroup $userGroup - * @property-read UserRole $userRole + * @property-read UserRole $userRole * @method static Builder|GroupMembership newModelQuery() * @method static Builder|GroupMembership newQuery() * @method static Builder|GroupMembership query() diff --git a/app/Models/InvitedUser.php b/app/Models/InvitedUser.php new file mode 100644 index 0000000000..366e93ea2f --- /dev/null +++ b/app/Models/InvitedUser.php @@ -0,0 +1,76 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Models; + +use Eloquent; +use FireflyIII\User; +use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Carbon\Carbon; + +/** + * Class InvitedUser + * + * @property-read User $user + * @method static Builder|InvitedUser newModelQuery() + * @method static Builder|InvitedUser newQuery() + * @method static Builder|InvitedUser query() + * @mixin Eloquent + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property int $user_id + * @property string $email + * @property string $invite_code + * @property Carbon $expires + * @property bool $redeemed + * @method static Builder|InvitedUser whereCreatedAt($value) + * @method static Builder|InvitedUser whereEmail($value) + * @method static Builder|InvitedUser whereExpires($value) + * @method static Builder|InvitedUser whereId($value) + * @method static Builder|InvitedUser whereInviteCode($value) + * @method static Builder|InvitedUser whereRedeemed($value) + * @method static Builder|InvitedUser whereUpdatedAt($value) + * @method static Builder|InvitedUser whereUserId($value) + */ +class InvitedUser extends Model +{ + protected $casts + = [ + 'expires' => 'datetime', + 'redeemed' => 'boolean', + ]; + protected $fillable = ['user_id', 'email', 'invite_code', 'expires', 'redeemed']; + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); + } +} diff --git a/app/Models/LinkType.php b/app/Models/LinkType.php index 8f1d0f1ce7..e05e7d8263 100644 --- a/app/Models/LinkType.php +++ b/app/Models/LinkType.php @@ -1,4 +1,5 @@ check()) { - $linkTypeId = (int) $value; + $linkTypeId = (int)$value; $linkType = self::find($linkTypeId); if (null !== $linkType) { return $linkType; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** diff --git a/app/Models/Location.php b/app/Models/Location.php index 7dbc62105b..47520351cf 100644 --- a/app/Models/Location.php +++ b/app/Models/Location.php @@ -35,18 +35,18 @@ use Illuminate\Support\Carbon; /** * FireflyIII\Models\Location * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $locatable_id - * @property string $locatable_type - * @property float|null $latitude - * @property float|null $longitude - * @property int|null $zoom_level + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $locatable_id + * @property string $locatable_type + * @property float|null $latitude + * @property float|null $longitude + * @property int|null $zoom_level * @property-read Collection|Account[] $accounts - * @property-read int|null $accounts_count - * @property-read Model|Eloquent $locatable + * @property-read int|null $accounts_count + * @property-read Model|Eloquent $locatable * @method static Builder|Location newModelQuery() * @method static Builder|Location newQuery() * @method static Builder|Location query() @@ -63,7 +63,6 @@ use Illuminate\Support\Carbon; */ class Location extends Model { - /** * The attributes that should be casted to native types. * @@ -84,7 +83,7 @@ class Location extends Model /** * Add rules for locations. * - * @param array $rules + * @param array $rules * * @return array */ @@ -117,5 +116,4 @@ class Location extends Model { return $this->morphTo(); } - } diff --git a/app/Models/Note.php b/app/Models/Note.php index 2090715d3b..92c83528ec 100644 --- a/app/Models/Note.php +++ b/app/Models/Note.php @@ -1,4 +1,5 @@ check()) { - $objectGroupId = (int) $value; + $objectGroupId = (int)$value; /** @var ObjectGroup $objectGroup */ $objectGroup = self::where('object_groups.id', $objectGroupId) ->where('object_groups.user_id', auth()->user()->id)->first(); @@ -98,7 +98,16 @@ class ObjectGroup extends Model return $objectGroup; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @return BelongsTo + * @codeCoverageIgnore + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -124,13 +133,4 @@ class ObjectGroup extends Model { return $this->morphedByMany(PiggyBank::class, 'object_groupable'); } - - /** - * @return BelongsTo - * @codeCoverageIgnore - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } } diff --git a/app/Models/PiggyBank.php b/app/Models/PiggyBank.php index 75f15272b7..b497fd1791 100644 --- a/app/Models/PiggyBank.php +++ b/app/Models/PiggyBank.php @@ -1,4 +1,5 @@ check()) { - $piggyBankId = (int) $value; + $piggyBankId = (int)$value; $piggyBank = self::where('piggy_banks.id', $piggyBankId) ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('accounts.user_id', auth()->user()->id)->first(['piggy_banks.*']); @@ -124,7 +125,7 @@ class PiggyBank extends Model return $piggyBank; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** @@ -183,11 +184,11 @@ class PiggyBank extends Model /** * @codeCoverageIgnore * - * @param mixed $value + * @param mixed $value */ public function setTargetamountAttribute($value): void { - $this->attributes['targetamount'] = (string) $value; + $this->attributes['targetamount'] = (string)$value; } /** @@ -198,7 +199,7 @@ class PiggyBank extends Model protected function targetamount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string)$value, ); } } diff --git a/app/Models/PiggyBankEvent.php b/app/Models/PiggyBankEvent.php index 94d28acc35..592810edcf 100644 --- a/app/Models/PiggyBankEvent.php +++ b/app/Models/PiggyBankEvent.php @@ -1,4 +1,5 @@ attributes['amount'] = (string) $value; + $this->attributes['amount'] = (string)$value; } /** @@ -107,7 +108,7 @@ class PiggyBankEvent extends Model protected function amount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string)$value, ); } } diff --git a/app/Models/PiggyBankRepetition.php b/app/Models/PiggyBankRepetition.php index 1cfe9c788e..f7394bbf90 100644 --- a/app/Models/PiggyBankRepetition.php +++ b/app/Models/PiggyBankRepetition.php @@ -1,4 +1,5 @@ attributes['currentamount'] = (string) $value; + $this->attributes['currentamount'] = (string)$value; } /** @@ -136,7 +137,7 @@ class PiggyBankRepetition extends Model protected function currentamount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string)$value, ); } } diff --git a/app/Models/Preference.php b/app/Models/Preference.php index d743f360ad..daf12690a7 100644 --- a/app/Models/Preference.php +++ b/app/Models/Preference.php @@ -1,4 +1,5 @@ user(); /** @var Preference|null $preference */ $preference = $user->preferences()->where('name', $value)->first(); + if (null === $preference) { + $preference = $user->preferences()->where('id', (int)$value)->first(); + } if (null !== $preference) { return $preference; } $default = config('firefly.default_preferences'); if (array_key_exists($value, $default)) { - $preference = new Preference; + $preference = new Preference(); $preference->name = $value; $preference->data = $default[$value]; $preference->user_id = $user->id; @@ -97,7 +101,7 @@ class Preference extends Model return $preference; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** diff --git a/app/Models/Recurrence.php b/app/Models/Recurrence.php index 6a723f3b78..b1415f8333 100644 --- a/app/Models/Recurrence.php +++ b/app/Models/Recurrence.php @@ -38,33 +38,33 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * FireflyIII\Models\Recurrence * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $user_id - * @property int $transaction_type_id - * @property string $title - * @property string $description - * @property Carbon $first_date - * @property Carbon|null $repeat_until - * @property Carbon|null $latest_date - * @property int $repetitions - * @property bool $apply_rules - * @property bool $active - * @property-read Collection|Attachment[] $attachments - * @property-read int|null $attachments_count - * @property-read Collection|Note[] $notes - * @property-read int|null $notes_count - * @property-read Collection|RecurrenceMeta[] $recurrenceMeta - * @property-read int|null $recurrence_meta_count - * @property-read Collection|RecurrenceRepetition[] $recurrenceRepetitions - * @property-read int|null $recurrence_repetitions_count + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $user_id + * @property int $transaction_type_id + * @property string $title + * @property string $description + * @property Carbon $first_date + * @property Carbon|null $repeat_until + * @property Carbon|null $latest_date + * @property int $repetitions + * @property bool $apply_rules + * @property bool $active + * @property-read Collection|Attachment[] $attachments + * @property-read int|null $attachments_count + * @property-read Collection|Note[] $notes + * @property-read int|null $notes_count + * @property-read Collection|RecurrenceMeta[] $recurrenceMeta + * @property-read int|null $recurrence_meta_count + * @property-read Collection|RecurrenceRepetition[] $recurrenceRepetitions + * @property-read int|null $recurrence_repetitions_count * @property-read Collection|RecurrenceTransaction[] $recurrenceTransactions - * @property-read int|null $recurrence_transactions_count - * @property-read TransactionCurrency $transactionCurrency - * @property-read TransactionType $transactionType - * @property-read User $user + * @property-read int|null $recurrence_transactions_count + * @property-read TransactionCurrency $transactionCurrency + * @property-read TransactionType $transactionType + * @property-read User $user * @method static \Illuminate\Database\Eloquent\Builder|Recurrence newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|Recurrence newQuery() * @method static Builder|Recurrence onlyTrashed() @@ -86,7 +86,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @method static Builder|Recurrence withTrashed() * @method static Builder|Recurrence withoutTrashed() * @mixin Eloquent - * @property int|null $user_group_id + * @property int|null $user_group_id * @method static \Illuminate\Database\Eloquent\Builder|Recurrence whereUserGroupId($value) */ class Recurrence extends Model @@ -122,7 +122,7 @@ class Recurrence extends Model /** * Route binder. Converts the key in the URL to the specified object (or throw 404). * - * @param string $value + * @param string $value * * @return Recurrence * @throws NotFoundHttpException @@ -130,7 +130,7 @@ class Recurrence extends Model public static function routeBinder(string $value): Recurrence { if (auth()->check()) { - $recurrenceId = (int) $value; + $recurrenceId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Recurrence $recurrence */ @@ -139,7 +139,16 @@ class Recurrence extends Model return $recurrence; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -153,7 +162,7 @@ class Recurrence extends Model /** * @codeCoverageIgnore - * Get all of the notes. + * Get all the notes. */ public function notes(): MorphMany { @@ -204,14 +213,4 @@ class Recurrence extends Model { return $this->belongsTo(TransactionType::class); } - - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } - } diff --git a/app/Models/RecurrenceMeta.php b/app/Models/RecurrenceMeta.php index 5b40c521f8..516ff62ed5 100644 --- a/app/Models/RecurrenceMeta.php +++ b/app/Models/RecurrenceMeta.php @@ -33,13 +33,13 @@ use Illuminate\Support\Carbon; /** * FireflyIII\Models\RecurrenceMeta * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $recurrence_id - * @property string $name - * @property mixed $value + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $recurrence_id + * @property string $name + * @property mixed $value * @property-read Recurrence $recurrence * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceMeta newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceMeta newQuery() @@ -86,5 +86,4 @@ class RecurrenceMeta extends Model { return $this->belongsTo(Recurrence::class); } - } diff --git a/app/Models/RecurrenceRepetition.php b/app/Models/RecurrenceRepetition.php index c5374980b4..156dbaf01a 100644 --- a/app/Models/RecurrenceRepetition.php +++ b/app/Models/RecurrenceRepetition.php @@ -33,15 +33,15 @@ use Illuminate\Support\Carbon; /** * FireflyIII\Models\RecurrenceRepetition * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $recurrence_id - * @property string $repetition_type - * @property string $repetition_moment - * @property int $repetition_skip - * @property int $weekend + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $recurrence_id + * @property string $repetition_type + * @property string $repetition_moment + * @property int $repetition_skip + * @property int $weekend * @property-read Recurrence $recurrence * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceRepetition newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceRepetition newQuery() @@ -62,16 +62,13 @@ use Illuminate\Support\Carbon; */ class RecurrenceRepetition extends Model { - /** @var int */ - public const WEEKEND_DO_NOTHING = 1; - /** @var int */ - public const WEEKEND_SKIP_CREATION = 2; - /** @var int */ - public const WEEKEND_TO_FRIDAY = 3; - /** @var int */ - public const WEEKEND_TO_MONDAY = 4; use SoftDeletes; + public const WEEKEND_DO_NOTHING = 1; + public const WEEKEND_SKIP_CREATION = 2; + public const WEEKEND_TO_FRIDAY = 3; + public const WEEKEND_TO_MONDAY = 4; + /** * The attributes that should be casted to native types. * diff --git a/app/Models/RecurrenceTransaction.php b/app/Models/RecurrenceTransaction.php index 28670826ea..ebe4933d01 100644 --- a/app/Models/RecurrenceTransaction.php +++ b/app/Models/RecurrenceTransaction.php @@ -36,25 +36,25 @@ use Illuminate\Support\Carbon; /** * FireflyIII\Models\RecurrenceTransaction * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $recurrence_id - * @property int $transaction_currency_id - * @property int|null $foreign_currency_id - * @property int $source_id - * @property int $destination_id - * @property string $amount - * @property string|null $foreign_amount - * @property string $description - * @property-read Account $destinationAccount - * @property-read TransactionCurrency|null $foreignCurrency - * @property-read Recurrence $recurrence + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $recurrence_id + * @property int $transaction_currency_id + * @property int|null $foreign_currency_id + * @property int $source_id + * @property int $destination_id + * @property string $amount + * @property string|null $foreign_amount + * @property string $description + * @property-read Account $destinationAccount + * @property-read TransactionCurrency|null $foreignCurrency + * @property-read Recurrence $recurrence * @property-read Collection|RecurrenceTransactionMeta[] $recurrenceTransactionMeta - * @property-read int|null $recurrence_transaction_meta_count - * @property-read Account $sourceAccount - * @property-read TransactionCurrency $transactionCurrency + * @property-read int|null $recurrence_transaction_meta_count + * @property-read Account $sourceAccount + * @property-read TransactionCurrency $transactionCurrency * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransaction newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransaction newQuery() * @method static Builder|RecurrenceTransaction onlyTrashed() @@ -74,9 +74,9 @@ use Illuminate\Support\Carbon; * @method static Builder|RecurrenceTransaction withTrashed() * @method static Builder|RecurrenceTransaction withoutTrashed() * @mixin Eloquent - * @property int|null $transaction_type_id + * @property int|null $transaction_type_id * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransaction whereTransactionTypeId($value) - * @property-read TransactionType|null $transactionType + * @property-read TransactionType|null $transactionType */ class RecurrenceTransaction extends Model { @@ -98,8 +98,16 @@ class RecurrenceTransaction extends Model ]; /** @var array Fields that can be filled */ protected $fillable - = ['recurrence_id', 'transaction_currency_id', 'foreign_currency_id', 'source_id', 'destination_id', 'amount', 'foreign_amount', - 'description']; + = [ + 'recurrence_id', + 'transaction_currency_id', + 'foreign_currency_id', + 'source_id', + 'destination_id', + 'amount', + 'foreign_amount', + 'description', + ]; /** @var string The table to store the data in */ protected $table = 'recurrences_transactions'; @@ -172,7 +180,7 @@ class RecurrenceTransaction extends Model protected function amount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string) $value, ); } @@ -182,7 +190,7 @@ class RecurrenceTransaction extends Model protected function foreignAmount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string) $value, ); } } diff --git a/app/Models/RecurrenceTransactionMeta.php b/app/Models/RecurrenceTransactionMeta.php index df7846f4ed..a5e1bd9fc0 100644 --- a/app/Models/RecurrenceTransactionMeta.php +++ b/app/Models/RecurrenceTransactionMeta.php @@ -33,13 +33,13 @@ use Illuminate\Support\Carbon; /** * FireflyIII\Models\RecurrenceTransactionMeta * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $rt_id - * @property string $name - * @property mixed $value + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $rt_id + * @property string $name + * @property mixed $value * @property-read RecurrenceTransaction $recurrenceTransaction * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransactionMeta newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransactionMeta newQuery() @@ -86,5 +86,4 @@ class RecurrenceTransactionMeta extends Model { return $this->belongsTo(RecurrenceTransaction::class, 'rt_id'); } - } diff --git a/app/Models/Role.php b/app/Models/Role.php index 1462fb2e30..75befaabe5 100644 --- a/app/Models/Role.php +++ b/app/Models/Role.php @@ -1,4 +1,5 @@ check()) { - $ruleId = (int) $value; + $ruleId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Rule $rule */ @@ -120,7 +121,16 @@ class Rule extends Model return $rule; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -151,7 +161,7 @@ class Rule extends Model } /** - * @param mixed $value + * @param mixed $value * * @codeCoverageIgnore */ @@ -159,13 +169,4 @@ class Rule extends Model { $this->attributes['description'] = e($value); } - - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } } diff --git a/app/Models/RuleAction.php b/app/Models/RuleAction.php index 922c4445c1..a80ccb1523 100644 --- a/app/Models/RuleAction.php +++ b/app/Models/RuleAction.php @@ -1,4 +1,5 @@ check()) { - $ruleGroupId = (int) $value; + $ruleGroupId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var RuleGroup $ruleGroup */ @@ -111,16 +112,7 @@ class RuleGroup extends Model return $ruleGroup; } } - throw new NotFoundHttpException; - } - - /** - * @codeCoverageIgnore - * @return HasMany - */ - public function rules(): HasMany - { - return $this->hasMany(Rule::class); + throw new NotFoundHttpException(); } /** @@ -131,4 +123,13 @@ class RuleGroup extends Model { return $this->belongsTo(User::class); } + + /** + * @codeCoverageIgnore + * @return HasMany + */ + public function rules(): HasMany + { + return $this->hasMany(Rule::class); + } } diff --git a/app/Models/RuleTrigger.php b/app/Models/RuleTrigger.php index 234e1feefa..2e0fb6543a 100644 --- a/app/Models/RuleTrigger.php +++ b/app/Models/RuleTrigger.php @@ -1,4 +1,5 @@ check()) { - $tagId = (int) $value; + $tagId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Tag $tag */ @@ -122,7 +123,16 @@ class Tag extends Model return $tag; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -151,13 +161,4 @@ class Tag extends Model { return $this->belongsToMany(TransactionJournal::class); } - - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } } diff --git a/app/Models/Transaction.php b/app/Models/Transaction.php index 346a521db7..03e90a0203 100644 --- a/app/Models/Transaction.php +++ b/app/Models/Transaction.php @@ -1,4 +1,5 @@ attributes['amount'] = (string) $value; + $this->attributes['amount'] = (string)$value; } /** @@ -266,7 +277,7 @@ class Transaction extends Model protected function amount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string)$value, ); } @@ -278,7 +289,7 @@ class Transaction extends Model protected function foreignAmount(): Attribute { return Attribute::make( - get: fn($value) => (string) $value, + get: fn ($value) => (string)$value, ); } } diff --git a/app/Models/TransactionCurrency.php b/app/Models/TransactionCurrency.php index 3af5058281..1196f7a8e3 100644 --- a/app/Models/TransactionCurrency.php +++ b/app/Models/TransactionCurrency.php @@ -1,4 +1,5 @@ check()) { - $currencyId = (int) $value; + $currencyId = (int)$value; $currency = self::find($currencyId); if (null !== $currency) { return $currency; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** diff --git a/app/Models/TransactionGroup.php b/app/Models/TransactionGroup.php index aac8eac199..627f5c756d 100644 --- a/app/Models/TransactionGroup.php +++ b/app/Models/TransactionGroup.php @@ -1,4 +1,5 @@ check()) { - $groupId = (int) $value; + $groupId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var TransactionGroup $group */ @@ -106,16 +107,7 @@ class TransactionGroup extends Model } } - throw new NotFoundHttpException; - } - - /** - * @codeCoverageIgnore - * @return HasMany - */ - public function transactionJournals(): HasMany - { - return $this->hasMany(TransactionJournal::class); + throw new NotFoundHttpException(); } /** @@ -127,4 +119,12 @@ class TransactionGroup extends Model return $this->belongsTo(User::class); } + /** + * @codeCoverageIgnore + * @return HasMany + */ + public function transactionJournals(): HasMany + { + return $this->hasMany(TransactionJournal::class); + } } diff --git a/app/Models/TransactionJournal.php b/app/Models/TransactionJournal.php index b39283b1af..03fe540362 100644 --- a/app/Models/TransactionJournal.php +++ b/app/Models/TransactionJournal.php @@ -1,4 +1,5 @@ check()) { - $journalId = (int) $value; + $journalId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var TransactionJournal $journal */ @@ -170,7 +181,16 @@ class TransactionJournal extends Model } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); + } + + /** + * @codeCoverageIgnore + * @return BelongsTo + */ + public function user(): BelongsTo + { + return $this->belongsTo(User::class); } /** @@ -261,8 +281,8 @@ class TransactionJournal extends Model /** * @codeCoverageIgnore * - * @param EloquentBuilder $query - * @param Carbon $date + * @param EloquentBuilder $query + * @param Carbon $date * * @return EloquentBuilder */ @@ -274,8 +294,8 @@ class TransactionJournal extends Model /** * @codeCoverageIgnore * - * @param EloquentBuilder $query - * @param Carbon $date + * @param EloquentBuilder $query + * @param Carbon $date * * @return EloquentBuilder */ @@ -287,15 +307,15 @@ class TransactionJournal extends Model /** * @codeCoverageIgnore * - * @param EloquentBuilder $query - * @param array $types + * @param EloquentBuilder $query + * @param array $types */ public function scopeTransactionTypes(EloquentBuilder $query, array $types): void { if (!self::isJoined($query, 'transaction_types')) { $query->leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id'); } - if (!empty($types)) { + if (0 !== count($types)) { $query->whereIn('transaction_types.type', $types); } } @@ -305,8 +325,8 @@ class TransactionJournal extends Model * * @codeCoverageIgnore * - * @param Builder $query - * @param string $table + * @param Builder $query + * @param string $table * * @return bool */ @@ -387,13 +407,4 @@ class TransactionJournal extends Model { return $this->hasMany(Transaction::class); } - - /** - * @codeCoverageIgnore - * @return BelongsTo - */ - public function user(): BelongsTo - { - return $this->belongsTo(User::class); - } } diff --git a/app/Models/TransactionJournalLink.php b/app/Models/TransactionJournalLink.php index c37dbcdb4b..937acf1713 100644 --- a/app/Models/TransactionJournalLink.php +++ b/app/Models/TransactionJournalLink.php @@ -1,4 +1,5 @@ check()) { - $linkId = (int) $value; + $linkId = (int)$value; $link = self::where('journal_links.id', $linkId) ->leftJoin('transaction_journals as t_a', 't_a.id', '=', 'source_id') ->leftJoin('transaction_journals as t_b', 't_b.id', '=', 'destination_id') @@ -98,7 +99,7 @@ class TransactionJournalLink extends Model return $link; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** diff --git a/app/Models/TransactionJournalMeta.php b/app/Models/TransactionJournalMeta.php index 94a9feba64..823bcb01a6 100644 --- a/app/Models/TransactionJournalMeta.php +++ b/app/Models/TransactionJournalMeta.php @@ -1,4 +1,5 @@ 'datetime', 'updated_at' => 'datetime', 'deleted_at' => 'datetime', ]; - /** @var string[] */ protected $fillable = ['type']; /** * Route binder. Converts the key in the URL to the specified object (or throw 404). * - * @param string $type + * @param string $type * * @return TransactionType * @throws NotFoundHttpException diff --git a/app/Models/UserGroup.php b/app/Models/UserGroup.php index 4ebc662242..f5bbe869f8 100644 --- a/app/Models/UserGroup.php +++ b/app/Models/UserGroup.php @@ -34,13 +34,13 @@ use Illuminate\Support\Carbon; /** * Class UserGroup * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property string|null $deleted_at - * @property string $title + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property string|null $deleted_at + * @property string $title * @property-read Collection|GroupMembership[] $groupMemberships - * @property-read int|null $group_memberships_count + * @property-read int|null $group_memberships_count * @method static Builder|UserGroup newModelQuery() * @method static Builder|UserGroup newQuery() * @method static Builder|UserGroup query() diff --git a/app/Models/UserRole.php b/app/Models/UserRole.php index ce16b69013..0247c4ca58 100644 --- a/app/Models/UserRole.php +++ b/app/Models/UserRole.php @@ -34,13 +34,13 @@ use Illuminate\Support\Carbon; /** * Class UserRole * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property string|null $deleted_at - * @property string $title + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property string|null $deleted_at + * @property string $title * @property-read Collection|GroupMembership[] $groupMemberships - * @property-read int|null $group_memberships_count + * @property-read int|null $group_memberships_count * @method static Builder|UserRole newModelQuery() * @method static Builder|UserRole newQuery() * @method static Builder|UserRole query() @@ -58,9 +58,13 @@ class UserRole extends Model public const CHANGE_RULES = 'change_rules'; public const CHANGE_TRANSACTIONS = 'change_tx'; public const FULL = 'full'; + public const MANAGE_CURRENCIES = 'manage_currencies'; + public const MANAGE_WEBHOOKS = 'manage_webhooks'; public const OWNER = 'owner'; public const READ_ONLY = 'ro'; public const VIEW_REPORTS = 'view_reports'; + + protected $fillable = ['title']; /** diff --git a/app/Models/Webhook.php b/app/Models/Webhook.php index f036fb3abe..bf38d394b7 100644 --- a/app/Models/Webhook.php +++ b/app/Models/Webhook.php @@ -24,6 +24,9 @@ declare(strict_types=1); namespace FireflyIII\Models; use Eloquent; +use FireflyIII\Enums\WebhookDelivery; +use FireflyIII\Enums\WebhookResponse; +use FireflyIII\Enums\WebhookTrigger; use FireflyIII\User; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; @@ -37,19 +40,19 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * FireflyIII\Models\Webhook * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property Carbon|null $deleted_at - * @property int $user_id - * @property bool $active - * @property int $trigger - * @property int $response - * @property int $delivery - * @property string $url - * @property-read User $user + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property Carbon|null $deleted_at + * @property int $user_id + * @property bool $active + * @property int $trigger + * @property int $response + * @property int $delivery + * @property string $url + * @property-read User $user * @property-read Collection|WebhookMessage[] $webhookMessages - * @property-read int|null $webhook_messages_count + * @property-read int|null $webhook_messages_count * @method static Builder|Webhook newModelQuery() * @method static Builder|Webhook newQuery() * @method static \Illuminate\Database\Query\Builder|Webhook onlyTrashed() @@ -67,30 +70,17 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @method static \Illuminate\Database\Query\Builder|Webhook withTrashed() * @method static \Illuminate\Database\Query\Builder|Webhook withoutTrashed() * @mixin Eloquent - * @property string $title - * @property string $secret + * @property string $title + * @property string $secret * @method static Builder|Webhook whereSecret($value) * @method static Builder|Webhook whereTitle($value) - * @property int|null $user_group_id + * @property int|null $user_group_id * @method static Builder|Webhook whereUserGroupId($value) */ class Webhook extends Model { use SoftDeletes; - // dont forget to update the config in firefly.php - // triggers - public const DELIVERY_JSON = 300; - public const RESPONSE_ACCOUNTS = 210; - public const RESPONSE_NONE = 220; - - // actions - public const RESPONSE_TRANSACTIONS = 200; - public const TRIGGER_DESTROY_TRANSACTION = 120; - public const TRIGGER_STORE_TRANSACTION = 100; - - // delivery - public const TRIGGER_UPDATE_TRANSACTION = 110; protected $casts = [ 'active' => 'boolean', @@ -100,10 +90,91 @@ class Webhook extends Model ]; protected $fillable = ['active', 'trigger', 'response', 'delivery', 'user_id', 'url', 'title', 'secret']; + /** + * @return array + */ + public static function getDeliveries(): array + { + $array = []; + $set = WebhookDelivery::cases(); + foreach ($set as $item) { + $array[$item->value] = $item->name; + } + return $array; + } + + /** + * @return array + */ + public static function getDeliveriesForValidation(): array + { + $array = []; + $set = WebhookDelivery::cases(); + foreach ($set as $item) { + $array[$item->name] = $item->value; + $array[$item->value] = $item->value; + } + return $array; + } + + /** + * @return array + */ + public static function getResponses(): array + { + $array = []; + $set = WebhookResponse::cases(); + foreach ($set as $item) { + $array[$item->value] = $item->name; + } + return $array; + } + + /** + * @return array + */ + public static function getResponsesForValidation(): array + { + $array = []; + $set = WebhookResponse::cases(); + foreach ($set as $item) { + $array[$item->name] = $item->value; + $array[$item->value] = $item->value; + } + return $array; + } + + /** + * @return array + */ + public static function getTriggers(): array + { + $array = []; + $set = WebhookTrigger::cases(); + foreach ($set as $item) { + $array[$item->value] = $item->name; + } + return $array; + } + + /** + * @return array + */ + public static function getTriggersForValidation(): array + { + $array = []; + $set = WebhookTrigger::cases(); + foreach ($set as $item) { + $array[$item->name] = $item->value; + $array[$item->value] = $item->value; + } + return $array; + } + /** * Route binder. Converts the key in the URL to the specified object (or throw 404). * - * @param string $value + * @param string $value * * @return Webhook * @throws NotFoundHttpException @@ -111,7 +182,7 @@ class Webhook extends Model public static function routeBinder(string $value): Webhook { if (auth()->check()) { - $webhookId = (int) $value; + $webhookId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var Webhook $webhook */ @@ -120,7 +191,7 @@ class Webhook extends Model return $webhook; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** diff --git a/app/Models/WebhookAttempt.php b/app/Models/WebhookAttempt.php index 112c5bb468..9d1c296626 100644 --- a/app/Models/WebhookAttempt.php +++ b/app/Models/WebhookAttempt.php @@ -35,14 +35,14 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class WebhookAttempt * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property string|null $deleted_at - * @property int $webhook_message_id - * @property int $status_code - * @property string|null $logs - * @property string|null $response + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property string|null $deleted_at + * @property int $webhook_message_id + * @property int $status_code + * @property string|null $logs + * @property string|null $response * @property-read WebhookMessage $webhookMessage * @method static \Illuminate\Database\Eloquent\Builder|WebhookAttempt newModelQuery() * @method static \Illuminate\Database\Eloquent\Builder|WebhookAttempt newQuery() @@ -67,7 +67,7 @@ class WebhookAttempt extends Model /** * Route binder. Converts the key in the URL to the specified object (or throw 404). * - * @param string $value + * @param string $value * * @return WebhookAttempt * @throws NotFoundHttpException @@ -75,7 +75,7 @@ class WebhookAttempt extends Model public static function routeBinder(string $value): WebhookAttempt { if (auth()->check()) { - $attemptId = (int) $value; + $attemptId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var WebhookAttempt $attempt */ @@ -84,7 +84,7 @@ class WebhookAttempt extends Model return $attempt; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** diff --git a/app/Models/WebhookMessage.php b/app/Models/WebhookMessage.php index 83e3e5da3f..e74dcc1582 100644 --- a/app/Models/WebhookMessage.php +++ b/app/Models/WebhookMessage.php @@ -26,6 +26,7 @@ namespace FireflyIII\Models; use Eloquent; use FireflyIII\User; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Collection; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; @@ -36,18 +37,18 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * FireflyIII\Models\WebhookMessage * - * @property int $id - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property string|null $deleted_at - * @property int $webhook_id - * @property bool $sent - * @property bool $errored - * @property int $attempts - * @property string $uuid - * @property array $message - * @property array|null $logs - * @property-read Webhook $webhook + * @property int $id + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property string|null $deleted_at + * @property int $webhook_id + * @property bool $sent + * @property bool $errored + * @property int $attempts + * @property string $uuid + * @property array $message + * @property array|null $logs + * @property-read Webhook $webhook * @method static Builder|WebhookMessage newModelQuery() * @method static Builder|WebhookMessage newQuery() * @method static Builder|WebhookMessage query() @@ -64,11 +65,10 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @method static Builder|WebhookMessage whereWebhookId($value) * @mixin Eloquent * @property-read Collection|WebhookAttempt[] $webhookAttempts - * @property-read int|null $webhook_attempts_count + * @property-read int|null $webhook_attempts_count */ class WebhookMessage extends Model { - protected $casts = [ 'sent' => 'boolean', @@ -81,7 +81,7 @@ class WebhookMessage extends Model /** * Route binder. Converts the key in the URL to the specified object (or throw 404). * - * @param string $value + * @param string $value * * @return WebhookMessage * @throws NotFoundHttpException @@ -89,7 +89,7 @@ class WebhookMessage extends Model public static function routeBinder(string $value): WebhookMessage { if (auth()->check()) { - $messageId = (int) $value; + $messageId = (int)$value; /** @var User $user */ $user = auth()->user(); /** @var WebhookMessage $message */ @@ -98,7 +98,7 @@ class WebhookMessage extends Model return $message; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** @@ -118,4 +118,15 @@ class WebhookMessage extends Model { return $this->hasMany(WebhookAttempt::class); } + /** + * Get the amount + * + * @return Attribute + */ + protected function sent(): Attribute + { + return Attribute::make( + get: fn ($value) => (bool)$value, + ); + } } diff --git a/app/Notifications/Admin/TestNotification.php b/app/Notifications/Admin/TestNotification.php new file mode 100644 index 0000000000..ad21a8d2d7 --- /dev/null +++ b/app/Notifications/Admin/TestNotification.php @@ -0,0 +1,98 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\Admin; + +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; + +/** + * Class TestNotification + */ +class TestNotification extends Notification +{ + use Queueable; + + private string $address; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(string $address) + { + $this->address = $address; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->markdown('emails.admin-test', ['email' => $this->address]) + ->subject((string)trans('email.admin_test_subject')); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * @return SlackMessage + */ + public function toSlack($notifiable) + { + return (new SlackMessage())->content((string)trans('email.admin_test_subject')); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail', 'slack']; + } +} diff --git a/app/Notifications/Admin/UserInvitation.php b/app/Notifications/Admin/UserInvitation.php new file mode 100644 index 0000000000..5b17c60412 --- /dev/null +++ b/app/Notifications/Admin/UserInvitation.php @@ -0,0 +1,101 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\Admin; + +use FireflyIII\Models\InvitedUser; +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; + +/** + * Class UserInvitation + */ +class UserInvitation extends Notification +{ + use Queueable; + + private InvitedUser $invitee; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(InvitedUser $invitee) + { + $this->invitee = $invitee; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->markdown('emails.invitation-created', ['email' => $this->invitee->user->email, 'invitee' => $this->invitee->email]) + ->subject((string)trans('email.invitation_created_subject')); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * @return SlackMessage + */ + public function toSlack($notifiable) + { + return (new SlackMessage())->content( + (string)trans('email.invitation_created_body', ['email' => $this->invitee->user->email, 'invitee' => $this->invitee->email]) + ); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail', 'slack']; + } +} diff --git a/app/Notifications/Admin/UserRegistration.php b/app/Notifications/Admin/UserRegistration.php new file mode 100644 index 0000000000..a9636020a9 --- /dev/null +++ b/app/Notifications/Admin/UserRegistration.php @@ -0,0 +1,99 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\Admin; + +use FireflyIII\User; +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; + +/** + * Class UserRegistration + */ +class UserRegistration extends Notification +{ + use Queueable; + + private User $user; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(User $user) + { + $this->user = $user; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->markdown('emails.registered-admin', ['email' => $this->user->email, 'id' => $this->user->id]) + ->subject((string)trans('email.registered_subject_admin')); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * @return SlackMessage + */ + public function toSlack($notifiable) + { + return (new SlackMessage())->content((string)trans('email.admin_new_user_registered', ['email' => $this->user->email, 'id' => $this->user->id])); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail', 'slack']; + } +} diff --git a/app/Notifications/Admin/VersionCheckResult.php b/app/Notifications/Admin/VersionCheckResult.php new file mode 100644 index 0000000000..a8d3ce7f1a --- /dev/null +++ b/app/Notifications/Admin/VersionCheckResult.php @@ -0,0 +1,102 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\Admin; + +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; + +/** + * Class VersionCheckResult + * + */ +class VersionCheckResult extends Notification +{ + use Queueable; + + private string $message; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(string $message) + { + $this->message = $message; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->markdown('emails.new-version', ['message' => $this->message]) + ->subject((string)trans('email.new_version_email_subject')); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * @return SlackMessage + */ + public function toSlack($notifiable) + { + return (new SlackMessage())->content($this->message) + ->attachment(function ($attachment) { + $attachment->title('Firefly III @ GitHub', 'https://github.com/firefly-iii/firefly-iii/releases'); + }); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail', 'slack']; + } +} diff --git a/app/Notifications/User/BillReminder.php b/app/Notifications/User/BillReminder.php new file mode 100644 index 0000000000..677dd6fa47 --- /dev/null +++ b/app/Notifications/User/BillReminder.php @@ -0,0 +1,119 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\User; + +use FireflyIII\Models\Bill; +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; + +/** + * Class BillReminder + */ +class BillReminder extends Notification +{ + use Queueable; + + private Bill $bill; + private int $diff; + private string $field; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(Bill $bill, string $field, int $diff) + { + $this->bill = $bill; + $this->field = $field; + $this->diff = $diff; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + $subject = (string)trans(sprintf('email.bill_warning_subject_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]); + if (0 === $this->diff) { + $subject = (string)trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]); + } + + return (new MailMessage()) + ->markdown('emails.bill-warning', ['field' => $this->field, 'diff' => $this->diff, 'bill' => $this->bill]) + ->subject($subject); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * @return SlackMessage + */ + public function toSlack($notifiable) + { + $message = (string)trans(sprintf('email.bill_warning_subject_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]); + if (0 === $this->diff) { + $message = (string)trans(sprintf('email.bill_warning_subject_now_%s', $this->field), ['diff' => $this->diff, 'name' => $this->bill->name]); + } + $bill = $this->bill; + $url = route('bills.show', [$bill->id]); + return (new SlackMessage()) + ->warning() + ->attachment(function ($attachment) use ($bill, $url) { + $attachment->title((string)trans('firefly.visit_bill', ['name' => $bill->name]), $url); + }) + ->content($message); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail', 'slack']; + } +} diff --git a/app/Notifications/User/NewAccessToken.php b/app/Notifications/User/NewAccessToken.php new file mode 100644 index 0000000000..867c3fd4b9 --- /dev/null +++ b/app/Notifications/User/NewAccessToken.php @@ -0,0 +1,92 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\User; + +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; + +class NewAccessToken extends Notification +{ + use Queueable; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct() + { + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->markdown('emails.token-created') + ->subject((string)trans('email.access_token_created_subject')); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * @return SlackMessage + */ + public function toSlack($notifiable) + { + return (new SlackMessage())->content((string)trans('email.access_token_created_body')); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail', 'slack']; + } +} diff --git a/app/Notifications/User/TransactionCreation.php b/app/Notifications/User/TransactionCreation.php new file mode 100644 index 0000000000..102ab79087 --- /dev/null +++ b/app/Notifications/User/TransactionCreation.php @@ -0,0 +1,83 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\User; + +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Notification; + +class TransactionCreation extends Notification +{ + use Queueable; + + private array $collection; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(array $collection) + { + $this->collection = $collection; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->markdown('emails.report-new-journals', ['transformed' => $this->collection]) + ->subject((string)trans_choice('email.new_journals_subject', count($this->collection))); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail']; + } +} diff --git a/app/Notifications/User/UserLogin.php b/app/Notifications/User/UserLogin.php new file mode 100644 index 0000000000..80de3eae66 --- /dev/null +++ b/app/Notifications/User/UserLogin.php @@ -0,0 +1,121 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\User; + +use Exception; +use FireflyIII\Exceptions\FireflyException; +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; +use Illuminate\Support\Facades\Log; + +class UserLogin extends Notification +{ + use Queueable; + + private string $ip; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(string $ip) + { + $this->ip = $ip; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + $time = now(config('app.timezone'))->isoFormat((string)trans('config.date_time_js')); + $host = ''; + try { + $hostName = app('steam')->getHostName($this->ip); + } catch (FireflyException $e) { + Log::error($e->getMessage()); + $hostName = $this->ip; + } + if ($hostName !== $this->ip) { + $host = $hostName; + } + + return (new MailMessage()) + ->markdown('emails.new-ip', ['time' => $time, 'ipAddress' => $this->ip, 'host' => $host]) + ->subject((string)trans('email.login_from_new_ip')); + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * @return SlackMessage + */ + public function toSlack($notifiable) + { + $host = ''; + try { + $hostName = app('steam')->getHostName($this->ip); + } catch (FireflyException $e) { + Log::error($e->getMessage()); + $hostName = $this->ip; + } + if ($hostName !== $this->ip) { + $host = $hostName; + } + + return (new SlackMessage())->content((string)trans('email.slack_login_from_new_ip', ['host' => $host, 'ip' => $this->ip])); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail', 'slack']; + } +} diff --git a/app/Notifications/User/UserNewPassword.php b/app/Notifications/User/UserNewPassword.php new file mode 100644 index 0000000000..48f14421b1 --- /dev/null +++ b/app/Notifications/User/UserNewPassword.php @@ -0,0 +1,83 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\User; + +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Notification; + +class UserNewPassword extends Notification +{ + use Queueable; + + private string $url; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(string $url) + { + $this->url = $url; + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->markdown('emails.password', ['url' => $this->url]) + ->subject((string)trans('email.reset_pw_subject')); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail']; + } +} diff --git a/app/Notifications/User/UserRegistration.php b/app/Notifications/User/UserRegistration.php new file mode 100644 index 0000000000..ba5e39348a --- /dev/null +++ b/app/Notifications/User/UserRegistration.php @@ -0,0 +1,80 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\User; + +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\MailMessage; +use Illuminate\Notifications\Notification; + +class UserRegistration extends Notification +{ + use Queueable; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct() + { + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the mail representation of the notification. + * + * @param mixed $notifiable + * @return MailMessage + */ + public function toMail($notifiable) + { + return (new MailMessage()) + ->markdown('emails.registered', ['address' => route('index')]) + ->subject((string)trans('email.registered_subject')); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * @return array + */ + public function via($notifiable) + { + return ['mail']; + } +} diff --git a/app/Providers/AccountServiceProvider.php b/app/Providers/AccountServiceProvider.php index c6fae4af38..a58e62ad67 100644 --- a/app/Providers/AccountServiceProvider.php +++ b/app/Providers/AccountServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line $repository->setUser(auth()->user()); } @@ -78,6 +80,7 @@ class AccountServiceProvider extends ServiceProvider /** @var OperationsRepository $repository */ $repository = app(OperationsRepository::class); + // phpstan thinks auth does not exist. if ($app->auth->check()) { // @phpstan-ignore-line $repository->setUser(auth()->user()); } @@ -98,6 +101,7 @@ class AccountServiceProvider extends ServiceProvider /** @var AccountTaskerInterface $tasker */ $tasker = app(AccountTasker::class); + // phpstan thinks auth does not exist. if ($app->auth->check()) { // @phpstan-ignore-line $tasker->setUser(auth()->user()); } diff --git a/app/Providers/AdminServiceProvider.php b/app/Providers/AdminServiceProvider.php index 41b2c87f8e..b68b55657b 100644 --- a/app/Providers/AdminServiceProvider.php +++ b/app/Providers/AdminServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line $repository->setUser(auth()->user()); } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 0f5a22b381..d622e55553 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -1,4 +1,5 @@ 'no-store', + ]; + $uuid = (string)request()->header('X-Trace-Id'); + if ('' !== trim($uuid) && (preg_match('/^[a-f\d]{8}(-[a-f\d]{4}){4}[a-f\d]{8}$/i', trim($uuid)) === 1)) { + $headers['X-Trace-Id'] = $uuid; + } + return response() + ->json($value) + ->withHeaders($headers); + }); } /** diff --git a/app/Providers/AttachmentServiceProvider.php b/app/Providers/AttachmentServiceProvider.php index adf299f740..4d65930e4f 100644 --- a/app/Providers/AttachmentServiceProvider.php +++ b/app/Providers/AttachmentServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line $repository->setUser(auth()->user()); } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index ebe20226df..09dddfdcf2 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -1,4 +1,5 @@ registerPolicies(); diff --git a/app/Providers/BillServiceProvider.php b/app/Providers/BillServiceProvider.php index ecaefa8edc..0b55493126 100644 --- a/app/Providers/BillServiceProvider.php +++ b/app/Providers/BillServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line $repository->setUser(auth()->user()); } diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php index 99b4a17e1f..58e9475c01 100644 --- a/app/Providers/BroadcastServiceProvider.php +++ b/app/Providers/BroadcastServiceProvider.php @@ -1,4 +1,5 @@ app->bind( BudgetRepositoryInterface::class, static function (Application $app) { @@ -121,6 +124,5 @@ class BudgetServiceProvider extends ServiceProvider return $repository; } ); - } } diff --git a/app/Providers/CategoryServiceProvider.php b/app/Providers/CategoryServiceProvider.php index 0df0767cd1..f84a151241 100644 --- a/app/Providers/CategoryServiceProvider.php +++ b/app/Providers/CategoryServiceProvider.php @@ -1,4 +1,5 @@ app->bind( CategoryRepositoryInterface::class, static function (Application $app) { diff --git a/app/Providers/CurrencyServiceProvider.php b/app/Providers/CurrencyServiceProvider.php index ae527f4026..99397399d7 100644 --- a/app/Providers/CurrencyServiceProvider.php +++ b/app/Providers/CurrencyServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line $repository->setUser(auth()->user()); } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 04f7084e0b..e76b2af4e9 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -1,4 +1,5 @@ [ 'FireflyIII\Handlers\Events\UserEventHandler@sendRegistrationMail', + 'FireflyIII\Handlers\Events\UserEventHandler@sendAdminRegistrationNotification', 'FireflyIII\Handlers\Events\UserEventHandler@attachUserRole', 'FireflyIII\Handlers\Events\UserEventHandler@createGroupMembership', + 'FireflyIII\Handlers\Events\UserEventHandler@createExchangeRates', ], // is a User related event. Login::class => [ @@ -103,6 +105,14 @@ class EventServiceProvider extends ServiceProvider AdminRequestedTestMessage::class => [ 'FireflyIII\Handlers\Events\AdminEventHandler@sendTestMessage', ], + NewVersionAvailable::class => [ + 'FireflyIII\Handlers\Events\AdminEventHandler@sendNewVersion', + ], + InvitationCreated::class => [ + 'FireflyIII\Handlers\Events\AdminEventHandler@sendInvitationNotification', + 'FireflyIII\Handlers\Events\UserEventHandler@sendRegistrationInvite', + ], + // is a Transaction Journal related event. StoredTransactionGroup::class => [ 'FireflyIII\Handlers\Events\StoredGroupEventHandler@processRules', @@ -142,8 +152,12 @@ class EventServiceProvider extends ServiceProvider 'FireflyIII\Handlers\Events\BillEventHandler@warnAboutBill', ], + // audit log events: + TriggeredAuditLog::class => [ + 'FireflyIII\Handlers\Events\AuditEventHandler@storeAuditEvent', + ], // piggy bank related events: - ChangedPiggyBankAmount::class => [ + ChangedPiggyBankAmount::class => [ 'FireflyIII\Handlers\Events\PiggyBankEventHandler@changePiggyAmount', ], ]; @@ -155,17 +169,17 @@ class EventServiceProvider extends ServiceProvider { parent::boot(); $this->registerCreateEvents(); + $this->registerBudgetEvents(); } /** - * + * TODO needs a dedicated (static) method. */ protected function registerCreateEvents(): void { - // in case of repeated piggy banks and/or other problems. PiggyBank::created( static function (PiggyBank $piggyBank) { - $repetition = new PiggyBankRepetition; + $repetition = new PiggyBankRepetition(); $repetition->piggyBank()->associate($piggyBank); $repetition->startdate = $piggyBank->startdate; $repetition->targetdate = $piggyBank->targetdate; @@ -173,38 +187,58 @@ class EventServiceProvider extends ServiceProvider $repetition->save(); } ); - Client::created( - static function (Client $oauthClient) { - /** @var UserRepositoryInterface $repository */ - $repository = app(UserRepositoryInterface::class); - $user = $repository->find((int) $oauthClient->user_id); - if (null === $user) { - Log::info('OAuth client generated but no user associated.'); - - return; - } - - $email = $user->email; - - // see if user has alternative email address: - $pref = app('preferences')->getForUser($user, 'remote_guard_alt_email'); - if (null !== $pref) { - $email = $pref->data; - } - - Log::debug(sprintf('Now in EventServiceProvider::registerCreateEvents. Email is %s', $email)); - try { - Log::debug('Trying to send message...'); - Mail::to($email)->send(new OAuthTokenCreatedMail($oauthClient)); - } catch (TypeError|Exception $e) { // @phpstan-ignore-line - 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.'); - } - ); } + /** + * TODO needs a dedicated method. + */ + protected function registerBudgetEvents(): void + { + $func = static function (BudgetLimit $limit) { + Log::debug('Trigger budget limit event.'); + // find available budget with same period and same currency or create it. + // then set it or add money: + $user = $limit->budget->user; + $availableBudget = $user + ->availableBudgets() + ->where('start_date', $limit->start_date->format('Y-m-d')) + ->where('end_date', $limit->end_date->format('Y-m-d')) + ->where('transaction_currency_id', $limit->transaction_currency_id) + ->first(); + // update! + if (null !== $availableBudget) { + $repository = app(BudgetLimitRepositoryInterface::class); + $repository->setUser($user); + $set = $repository->getAllBudgetLimitsByCurrency($limit->transactionCurrency, $limit->start_date, $limit->end_date); + $sum = (string)$set->sum('amount'); + + + Log::debug( + sprintf( + 'Because budget limit #%d had its amount changed to %s, available budget limit #%d will be updated.', + $limit->id, + $limit->amount, + $availableBudget->id + ) + ); + $availableBudget->amount = $sum; + $availableBudget->save(); + return; + } + Log::debug('Does not exist, create it.'); + // create it. + $data = [ + 'amount' => $limit->amount, + 'start' => $limit->start_date, + 'end' => $limit->end_date, + 'currency_id' => $limit->transaction_currency_id, + ]; + $repository = app(AvailableBudgetRepositoryInterface::class); + $repository->setUser($user); + $repository->store($data); + }; + + BudgetLimit::created($func); + BudgetLimit::updated($func); + } } diff --git a/app/Providers/FireflyServiceProvider.php b/app/Providers/FireflyServiceProvider.php index fcd2200ca6..d8f32f46e9 100644 --- a/app/Providers/FireflyServiceProvider.php +++ b/app/Providers/FireflyServiceProvider.php @@ -1,4 +1,5 @@ app->bind( 'preferences', static function () { - return new Preferences; + return new Preferences(); } ); $this->app->bind( 'fireflyconfig', static function () { - return new FireflyConfig; + return new FireflyConfig(); } ); $this->app->bind( 'navigation', static function () { - return new Navigation; + return new Navigation(); } ); $this->app->bind( 'amount', static function () { - return new Amount; + return new Amount(); } ); $this->app->bind( 'steam', static function () { - return new Steam; + return new Steam(); } ); $this->app->bind( 'expandedform', static function () { - return new ExpandedForm; + return new ExpandedForm(); } ); $this->app->bind( 'accountform', static function () { - return new AccountForm; + return new AccountForm(); } ); $this->app->bind( 'currencyform', static function () { - return new CurrencyForm; + return new CurrencyForm(); } ); $this->app->bind( 'piggybankform', static function () { - return new PiggyBankForm; + return new PiggyBankForm(); } ); $this->app->bind( 'ruleform', static function () { - return new RuleForm; + return new RuleForm(); } ); @@ -171,12 +172,14 @@ class FireflyServiceProvider extends ServiceProvider $this->app->bind(TransactionTypeRepositoryInterface::class, TransactionTypeRepository::class); $this->app->bind(AttachmentHelperInterface::class, AttachmentHelper::class); + $this->app->bind(ALERepositoryInterface::class, ALERepository::class); + $this->app->bind( ObjectGroupRepositoryInterface::class, static function (Application $app) { /** @var ObjectGroupRepository $repository */ $repository = app(ObjectGroupRepository::class); - if ($app->auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } @@ -189,7 +192,7 @@ class FireflyServiceProvider extends ServiceProvider static function (Application $app) { /** @var WebhookRepository $repository */ $repository = app(WebhookRepository::class); - if ($app->auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } @@ -202,7 +205,7 @@ class FireflyServiceProvider extends ServiceProvider static function (Application $app) { /** @var SearchRuleEngine $engine */ $engine = app(SearchRuleEngine::class); - if ($app->auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $engine->setUser(auth()->user()); } @@ -212,7 +215,6 @@ class FireflyServiceProvider extends ServiceProvider // more generators: $this->app->bind(PopupReportInterface::class, PopupReport::class); - $this->app->bind(HelpInterface::class, Help::class); $this->app->bind(ReportHelperInterface::class, ReportHelper::class); $this->app->bind(FiscalHelperInterface::class, FiscalHelper::class); $this->app->bind(UpdateRequestInterface::class, UpdateRequest::class); diff --git a/app/Providers/FireflySessionProvider.php b/app/Providers/FireflySessionProvider.php index 6021e5d9ba..2d95dc0181 100644 --- a/app/Providers/FireflySessionProvider.php +++ b/app/Providers/FireflySessionProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } @@ -82,7 +83,7 @@ class JournalServiceProvider extends ServiceProvider static function (Application $app) { /** @var JournalAPIRepositoryInterface $repository */ $repository = app(JournalAPIRepository::class); - if ($app->auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } @@ -96,7 +97,7 @@ class JournalServiceProvider extends ServiceProvider static function (Application $app) { /** @var JournalCLIRepositoryInterface $repository */ $repository = app(JournalCLIRepository::class); - if ($app->auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } @@ -115,7 +116,7 @@ class JournalServiceProvider extends ServiceProvider static function (Application $app) { /** @var TransactionGroupRepositoryInterface $repository */ $repository = app(TransactionGroupRepository::class); - if ($app->auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } @@ -134,7 +135,7 @@ class JournalServiceProvider extends ServiceProvider static function (Application $app) { /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollector::class); - if ($app->auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $collector->setUser(auth()->user()); } diff --git a/app/Providers/PiggyBankServiceProvider.php b/app/Providers/PiggyBankServiceProvider.php index 59501483f7..bbf34d26c7 100644 --- a/app/Providers/PiggyBankServiceProvider.php +++ b/app/Providers/PiggyBankServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } diff --git a/app/Providers/RecurringServiceProvider.php b/app/Providers/RecurringServiceProvider.php index ca247c9cae..137d58e408 100644 --- a/app/Providers/RecurringServiceProvider.php +++ b/app/Providers/RecurringServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } @@ -59,5 +60,4 @@ class RecurringServiceProvider extends ServiceProvider } ); } - } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index cf1d311aa4..c281dfb409 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -1,4 +1,5 @@ routes(function () { - Route::prefix('api/v1') + Route::prefix('api') ->middleware('api') ->namespace($this->namespace) ->group(base_path('routes/api.php')); @@ -65,9 +66,6 @@ class RouteServiceProvider extends ServiceProvider Route::middleware('web') ->namespace($this->namespace) ->group(base_path('routes/web.php')); - }); } - - } diff --git a/app/Providers/RuleGroupServiceProvider.php b/app/Providers/RuleGroupServiceProvider.php index 8c4f96374b..9145a1faa4 100644 --- a/app/Providers/RuleGroupServiceProvider.php +++ b/app/Providers/RuleGroupServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } diff --git a/app/Providers/RuleServiceProvider.php b/app/Providers/RuleServiceProvider.php index 41bc572893..ab766531bb 100644 --- a/app/Providers/RuleServiceProvider.php +++ b/app/Providers/RuleServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } diff --git a/app/Providers/SearchServiceProvider.php b/app/Providers/SearchServiceProvider.php index 5e49a10c5a..fed6e8718b 100644 --- a/app/Providers/SearchServiceProvider.php +++ b/app/Providers/SearchServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $search->setUser(auth()->user()); } diff --git a/app/Providers/SessionServiceProvider.php b/app/Providers/SessionServiceProvider.php index 183b4a48e5..e02f8eda08 100644 --- a/app/Providers/SessionServiceProvider.php +++ b/app/Providers/SessionServiceProvider.php @@ -1,4 +1,5 @@ auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } @@ -67,7 +68,7 @@ class TagServiceProvider extends ServiceProvider /** @var OperationsRepository $repository */ $repository = app(OperationsRepository::class); - if ($app->auth->check()) { // @phpstan-ignore-line + if ($app->auth->check()) { // @phpstan-ignore-line (phpstan does not understand the reference to auth) $repository->setUser(auth()->user()); } diff --git a/app/Repositories/Account/AccountRepository.php b/app/Repositories/Account/AccountRepository.php index 40f28a9b43..caf53bfffb 100644 --- a/app/Repositories/Account/AccountRepository.php +++ b/app/Repositories/Account/AccountRepository.php @@ -1,4 +1,5 @@ user->accounts()->accountTypeIn($types)->count(); - } - /** * Moved here from account CRUD. * - * @param Account $account - * @param Account|null $moveTo + * @param Account $account + * @param Account|null $moveTo * * @return bool * @@ -84,13 +75,13 @@ class AccountRepository implements AccountRepositoryInterface /** * Find account with same name OR same IBAN or both, but not the same type or ID. * - * @param Collection $accounts + * @param Collection $accounts * * @return Collection */ public function expandWithDoubles(Collection $accounts): Collection { - $result = new Collection; + $result = new Collection(); /** @var Account $account */ foreach ($accounts as $account) { $byName = $this->user->accounts()->where('name', $account->name) @@ -113,17 +104,6 @@ class AccountRepository implements AccountRepositoryInterface } return $result; - - } - - /** - * @param int $accountId - * - * @return Account|null - */ - public function find(int $accountId): ?Account - { - return $this->user->accounts()->find($accountId); } /** @@ -143,7 +123,7 @@ class AccountRepository implements AccountRepositoryInterface } ); - if (!empty($types)) { + if (0 !== count($types)) { $dbQuery->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); $dbQuery->whereIn('account_types.type', $types); } @@ -152,8 +132,8 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param string $iban - * @param array $types + * @param string $iban + * @param array $types * * @return Account|null */ @@ -161,7 +141,7 @@ class AccountRepository implements AccountRepositoryInterface { $query = $this->user->accounts()->where('iban', '!=', '')->whereNotNull('iban'); - if (!empty($types)) { + if (0 !== count($types)) { $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); $query->whereIn('account_types.type', $types); } @@ -170,8 +150,8 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param string $name - * @param array $types + * @param string $name + * @param array $types * * @return Account|null */ @@ -179,7 +159,7 @@ class AccountRepository implements AccountRepositoryInterface { $query = $this->user->accounts(); - if (!empty($types)) { + if (0 !== count($types)) { $query->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); $query->whereIn('account_types.type', $types); } @@ -201,7 +181,7 @@ class AccountRepository implements AccountRepositoryInterface /** * Return account type or null if not found. * - * @param string $type + * @param string $type * * @return AccountType|null */ @@ -211,7 +191,7 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param array $accountIds + * @param array $accountIds * * @return Collection */ @@ -219,7 +199,7 @@ class AccountRepository implements AccountRepositoryInterface { $query = $this->user->accounts(); - if (!empty($accountIds)) { + if (0 !== count($accountIds)) { $query->whereIn('accounts.id', $accountIds); } $query->orderBy('accounts.order', 'ASC'); @@ -230,18 +210,21 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param array $types + * @param array $types * * @return Collection */ public function getActiveAccountsByType(array $types): Collection { $query = $this->user->accounts()->with( - ['accountmeta' => function (HasMany $query) { - $query->where('name', 'account_role'); - }, 'attachments'] + [ + 'accountmeta' => function (HasMany $query) { + $query->where('name', 'account_role'); + }, + 'attachments', + ] ); - if (!empty($types)) { + if (0 !== count($types)) { $query->accountTypeIn($types); } $query->where('active', true); @@ -289,16 +272,23 @@ class AccountRepository implements AccountRepositoryInterface return $factory->findOrCreate('Cash account', $type->type); } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + /** * @inheritDoc */ public function getCreditTransactionGroup(Account $account): ?TransactionGroup { - $journal = TransactionJournal - ::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transactions.account_id', $account->id) - ->transactionTypes([TransactionType::LIABILITY_CREDIT]) - ->first(['transaction_journals.*']); + $journal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transactions.account_id', $account->id) + ->transactionTypes([TransactionType::LIABILITY_CREDIT]) + ->first(['transaction_journals.*']); if (null === $journal) { return null; } @@ -307,18 +297,20 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param array $types + * @param array $types * * @return Collection */ public function getInactiveAccountsByType(array $types): Collection { $query = $this->user->accounts()->with( - ['accountmeta' => function (HasMany $query) { - $query->where('name', 'account_role'); - }] + [ + 'accountmeta' => function (HasMany $query) { + $query->where('name', 'account_role'); + }, + ] ); - if (!empty($types)) { + if (0 !== count($types)) { $query->accountTypeIn($types); } $query->where('active', 0); @@ -340,7 +332,7 @@ class AccountRepository implements AccountRepositoryInterface /** * Get note text or null. * - * @param Account $account + * @param Account $account * * @return null|string */ @@ -358,16 +350,15 @@ class AccountRepository implements AccountRepositoryInterface /** * Returns the amount of the opening balance for this account. * - * @param Account $account + * @param Account $account * * @return string|null */ public function getOpeningBalanceAmount(Account $account): ?string { - $journal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->where('transactions.account_id', $account->id) - ->transactionTypes([TransactionType::OPENING_BALANCE]) + ->transactionTypes([TransactionType::OPENING_BALANCE, TransactionType::LIABILITY_CREDIT]) ->first(['transaction_journals.*']); if (null === $journal) { return null; @@ -377,13 +368,13 @@ class AccountRepository implements AccountRepositoryInterface return null; } - return (string) $transaction->amount; + return (string)$transaction->amount; } /** * Return date of opening balance as string or null. * - * @param Account $account + * @param Account $account * * @return null|string */ @@ -391,7 +382,7 @@ class AccountRepository implements AccountRepositoryInterface { $journal = TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') ->where('transactions.account_id', $account->id) - ->transactionTypes([TransactionType::OPENING_BALANCE]) + ->transactionTypes([TransactionType::OPENING_BALANCE, TransactionType::LIABILITY_CREDIT]) ->first(['transaction_journals.*']); if (null === $journal) { return null; @@ -401,7 +392,7 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param Account $account + * @param Account $account * * @return TransactionGroup|null */ @@ -413,21 +404,20 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param Account $account + * @param Account $account * * @return TransactionJournal|null */ public function getOpeningBalance(Account $account): ?TransactionJournal { - return TransactionJournal - ::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transactions.account_id', $account->id) - ->transactionTypes([TransactionType::OPENING_BALANCE]) - ->first(['transaction_journals.*']); + return TransactionJournal::leftJoin('transactions', 'transactions.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transactions.account_id', $account->id) + ->transactionTypes([TransactionType::OPENING_BALANCE]) + ->first(['transaction_journals.*']); } /** - * @param Account $account + * @param Account $account * * @return Collection */ @@ -437,7 +427,7 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param Account $account + * @param Account $account * * @return Account|null * @@ -480,7 +470,7 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param Account $account + * @param Account $account * * @return TransactionCurrency|null */ @@ -490,10 +480,10 @@ class AccountRepository implements AccountRepositoryInterface $list = config('firefly.valid_currency_account_types'); // return null if not in this list. - if(!in_array($type, $list, true)) { + if (!in_array($type, $list, true)) { return null; } - $currencyId = (int) $this->getMetaValue($account, 'currency_id'); + $currencyId = (int)$this->getMetaValue($account, 'currency_id'); if ($currencyId > 0) { return TransactionCurrency::find($currencyId); } @@ -504,8 +494,8 @@ class AccountRepository implements AccountRepositoryInterface /** * Return meta value for account. Null if not found. * - * @param Account $account - * @param string $field + * @param Account $account + * @param string $field * * @return null|string */ @@ -520,12 +510,32 @@ class AccountRepository implements AccountRepositoryInterface return null; } if (1 === $result->count()) { - return (string) $result->first()->data; + return (string)$result->first()->data; } return null; } + /** + * @param array $types + * + * @return int + */ + public function count(array $types): int + { + return $this->user->accounts()->accountTypeIn($types)->count(); + } + + /** + * @param int $accountId + * + * @return Account|null + */ + public function find(int $accountId): ?Account + { + return $this->user->accounts()->find($accountId); + } + /** * @inheritDoc */ @@ -534,8 +544,8 @@ class AccountRepository implements AccountRepositoryInterface $info = $account->transactions()->get(['transaction_currency_id', 'foreign_currency_id'])->toArray(); $currencyIds = []; foreach ($info as $entry) { - $currencyIds[] = (int) $entry['transaction_currency_id']; - $currencyIds[] = (int) $entry['foreign_currency_id']; + $currencyIds[] = (int)$entry['transaction_currency_id']; + $currencyIds[] = (int)$entry['foreign_currency_id']; } $currencyIds = array_unique($currencyIds); @@ -543,7 +553,7 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param Account $account + * @param Account $account * * @return bool */ @@ -566,22 +576,22 @@ class AccountRepository implements AccountRepositoryInterface AccountType::MORTGAGE => [AccountType::LOAN, AccountType::DEBT, AccountType::CREDITCARD, AccountType::MORTGAGE], ]; if (array_key_exists(ucfirst($type), $sets)) { - $order = (int) $this->getAccountsByType($sets[ucfirst($type)])->max('order'); + $order = (int)$this->getAccountsByType($sets[ucfirst($type)])->max('order'); Log::debug(sprintf('Return max order of "%s" set: %d', $type, $order)); return $order; } $specials = [AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::IMPORT, AccountType::RECONCILIATION]; - $order = (int) $this->getAccountsByType($specials)->max('order'); + $order = (int)$this->getAccountsByType($specials)->max('order'); Log::debug(sprintf('Return max order of "%s" set (specials!): %d', $type, $order)); return $order; } /** - * @param array $types - * @param array|null $sort + * @param array $types + * @param array|null $sort * * @return Collection */ @@ -589,19 +599,19 @@ class AccountRepository implements AccountRepositoryInterface { $res = array_intersect([AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT], $types); $query = $this->user->accounts(); - if (!empty($types)) { + if (0 !== count($types)) { $query->accountTypeIn($types); } // add sort parameters. At this point they're filtered to allowed fields to sort by: - if (!empty($sort)) { + if (0 !== count($sort)) { foreach ($sort as $param) { $query->orderBy($param[0], $param[1]); } } - if (empty($sort)) { - if (!empty($res)) { + if (0 === count($sort)) { + if (0 !== count($res)) { $query->orderBy('accounts.order', 'ASC'); } $query->orderBy('accounts.active', 'DESC'); @@ -614,7 +624,7 @@ class AccountRepository implements AccountRepositoryInterface /** * Returns the date of the very first transaction in this account. * - * @param Account $account + * @param Account $account * * @return Carbon|null */ @@ -628,7 +638,7 @@ class AccountRepository implements AccountRepositoryInterface /** * Returns the date of the very first transaction in this account. * - * @param Account $account + * @param Account $account * * @return TransactionJournal|null */ @@ -642,7 +652,7 @@ class AccountRepository implements AccountRepositoryInterface ->orderBy('transaction_journals.id', 'ASC') ->first(['transaction_journals.id']); if (null !== $first) { - return TransactionJournal::find((int) $first->id); + return TransactionJournal::find((int)$first->id); } return null; @@ -669,7 +679,7 @@ class AccountRepository implements AccountRepositoryInterface $account->order = 0; continue; } - if ($index !== (int) $account->order) { + if ($index !== (int)$account->order) { Log::debug(sprintf('Account #%d ("%s"): order should %d be but is %d.', $account->id, $account->name, $index, $account->order)); $account->order = $index; $account->save(); @@ -680,9 +690,9 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param string $query - * @param array $types - * @param int $limit + * @param string $query + * @param array $types + * @param int $limit * * @return Collection */ @@ -701,9 +711,8 @@ class AccountRepository implements AccountRepositoryInterface $search = sprintf('%%%s%%', $part); $dbQuery->where('name', 'LIKE', $search); } - } - if (!empty($types)) { + if (0 !== count($types)) { $dbQuery->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); $dbQuery->whereIn('account_types.type', $types); } @@ -741,7 +750,7 @@ class AccountRepository implements AccountRepositoryInterface ); } } - if (!empty($types)) { + if (0 !== count($types)) { $dbQuery->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id'); $dbQuery->whereIn('account_types.type', $types); } @@ -750,15 +759,7 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param array $data + * @param array $data * * @return Account * @throws FireflyException @@ -774,8 +775,8 @@ class AccountRepository implements AccountRepositoryInterface } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @return Account * @throws FireflyException @@ -787,5 +788,4 @@ class AccountRepository implements AccountRepositoryInterface return $service->update($account, $data); } - } diff --git a/app/Repositories/Account/AccountRepositoryInterface.php b/app/Repositories/Account/AccountRepositoryInterface.php index 8f585ad173..85b26128aa 100644 --- a/app/Repositories/Account/AccountRepositoryInterface.php +++ b/app/Repositories/Account/AccountRepositoryInterface.php @@ -1,4 +1,5 @@ id; $currency = $repository->getAccountCurrency($account) ?? $defaultCurrency; $return['sums'][$currency->id] = $return['sums'][$currency->id] ?? [ - 'start' => '0', - 'end' => '0', - 'difference' => '0', - 'currency_id' => $currency->id, - 'currency_code' => $currency->code, - 'currency_symbol' => $currency->symbol, - 'currency_name' => $currency->name, - 'currency_decimal_places' => $currency->decimal_places,]; + 'start' => '0', + 'end' => '0', + 'difference' => '0', + 'currency_id' => $currency->id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_name' => $currency->name, + 'currency_decimal_places' => $currency->decimal_places, + ]; $entry = [ 'name' => $account->name, 'id' => $account->id, @@ -114,9 +118,9 @@ class AccountTasker implements AccountTaskerInterface } /** - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts * * @return array */ @@ -140,7 +144,7 @@ class AccountTasker implements AccountTaskerInterface // Obtain a list of columns $sum = []; foreach ($report['accounts'] as $accountId => $row) { - $sum[$accountId] = (float) $row['sum']; // intentional float + $sum[$accountId] = (float)$row['sum']; // intentional float } array_multisort($sum, SORT_ASC, $report['accounts']); @@ -149,11 +153,11 @@ class AccountTasker implements AccountTaskerInterface } /** - * @param array $array + * @param array $array * * @return array - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException + * @throws FireflyException + * @throws JsonException */ private function groupExpenseByDestination(array $array): array { @@ -168,22 +172,22 @@ class AccountTasker implements AccountTaskerInterface /** @var array $journal */ foreach ($array as $journal) { - $sourceId = (int) $journal['destination_account_id']; - $currencyId = (int) $journal['currency_id']; + $sourceId = (int)$journal['destination_account_id']; + $currencyId = (int)$journal['currency_id']; $key = sprintf('%s-%s', $sourceId, $currencyId); $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepos->find($currencyId); $report['accounts'][$key] = $report['accounts'][$key] ?? [ - 'id' => $sourceId, - 'name' => $journal['destination_account_name'], - 'sum' => '0', - 'average' => '0', - 'count' => 0, - 'currency_id' => $currencies[$currencyId]->id, - 'currency_name' => $currencies[$currencyId]->name, - 'currency_symbol' => $currencies[$currencyId]->symbol, - 'currency_code' => $currencies[$currencyId]->code, - 'currency_decimal_places' => $currencies[$currencyId]->decimal_places, - ]; + 'id' => $sourceId, + 'name' => $journal['destination_account_name'], + 'sum' => '0', + 'average' => '0', + 'count' => 0, + 'currency_id' => $currencies[$currencyId]->id, + 'currency_name' => $currencies[$currencyId]->name, + 'currency_symbol' => $currencies[$currencyId]->symbol, + 'currency_code' => $currencies[$currencyId]->code, + 'currency_decimal_places' => $currencies[$currencyId]->decimal_places, + ]; $report['accounts'][$key]['sum'] = bcadd($report['accounts'][$key]['sum'], $journal['amount']); Log::debug(sprintf('Sum for %s is now %s', $journal['destination_account_name'], $report['accounts'][$key]['sum'])); @@ -194,17 +198,17 @@ class AccountTasker implements AccountTaskerInterface // do averages and sums. foreach (array_keys($report['accounts']) as $key) { if ($report['accounts'][$key]['count'] > 1) { - $report['accounts'][$key]['average'] = bcdiv($report['accounts'][$key]['sum'], (string) $report['accounts'][$key]['count']); + $report['accounts'][$key]['average'] = bcdiv($report['accounts'][$key]['sum'], (string)$report['accounts'][$key]['count']); } $currencyId = $report['accounts'][$key]['currency_id']; $report['sums'][$currencyId] = $report['sums'][$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $report['accounts'][$key]['currency_id'], - 'currency_name' => $report['accounts'][$key]['currency_name'], - 'currency_symbol' => $report['accounts'][$key]['currency_symbol'], - 'currency_code' => $report['accounts'][$key]['currency_code'], - 'currency_decimal_places' => $report['accounts'][$key]['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $report['accounts'][$key]['currency_id'], + 'currency_name' => $report['accounts'][$key]['currency_name'], + 'currency_symbol' => $report['accounts'][$key]['currency_symbol'], + 'currency_code' => $report['accounts'][$key]['currency_code'], + 'currency_decimal_places' => $report['accounts'][$key]['currency_decimal_places'], + ]; $report['sums'][$currencyId]['sum'] = bcadd($report['sums'][$currencyId]['sum'], $report['accounts'][$key]['sum']); } @@ -212,9 +216,9 @@ class AccountTasker implements AccountTaskerInterface } /** - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts * * @return array */ @@ -235,7 +239,7 @@ class AccountTasker implements AccountTaskerInterface // Obtain a list of columns $sum = []; foreach ($report['accounts'] as $accountId => $row) { - $sum[$accountId] = (float) $row['sum']; // intentional float + $sum[$accountId] = (float)$row['sum']; // intentional float } array_multisort($sum, SORT_DESC, $report['accounts']); @@ -244,11 +248,11 @@ class AccountTasker implements AccountTaskerInterface } /** - * @param array $array + * @param array $array * * @return array - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException + * @throws FireflyException + * @throws JsonException */ private function groupIncomeBySource(array $array): array { @@ -263,8 +267,8 @@ class AccountTasker implements AccountTaskerInterface /** @var array $journal */ foreach ($array as $journal) { - $sourceId = (int) $journal['source_account_id']; - $currencyId = (int) $journal['currency_id']; + $sourceId = (int)$journal['source_account_id']; + $currencyId = (int)$journal['currency_id']; $key = sprintf('%s-%s', $sourceId, $currencyId); if (!array_key_exists($key, $report['accounts'])) { $currencies[$currencyId] = $currencies[$currencyId] ?? $currencyRepos->find($currencyId); @@ -288,17 +292,17 @@ class AccountTasker implements AccountTaskerInterface // do averages and sums. foreach (array_keys($report['accounts']) as $key) { if ($report['accounts'][$key]['count'] > 1) { - $report['accounts'][$key]['average'] = bcdiv($report['accounts'][$key]['sum'], (string) $report['accounts'][$key]['count']); + $report['accounts'][$key]['average'] = bcdiv($report['accounts'][$key]['sum'], (string)$report['accounts'][$key]['count']); } $currencyId = $report['accounts'][$key]['currency_id']; $report['sums'][$currencyId] = $report['sums'][$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $report['accounts'][$key]['currency_id'], - 'currency_name' => $report['accounts'][$key]['currency_name'], - 'currency_symbol' => $report['accounts'][$key]['currency_symbol'], - 'currency_code' => $report['accounts'][$key]['currency_code'], - 'currency_decimal_places' => $report['accounts'][$key]['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $report['accounts'][$key]['currency_id'], + 'currency_name' => $report['accounts'][$key]['currency_name'], + 'currency_symbol' => $report['accounts'][$key]['currency_symbol'], + 'currency_code' => $report['accounts'][$key]['currency_code'], + 'currency_decimal_places' => $report['accounts'][$key]['currency_decimal_places'], + ]; $report['sums'][$currencyId]['sum'] = bcadd($report['sums'][$currencyId]['sum'], $report['accounts'][$key]['sum']); } @@ -306,7 +310,7 @@ class AccountTasker implements AccountTaskerInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { diff --git a/app/Repositories/Account/AccountTaskerInterface.php b/app/Repositories/Account/AccountTaskerInterface.php index cc6f68eed7..d7ff2c184d 100644 --- a/app/Repositories/Account/AccountTaskerInterface.php +++ b/app/Repositories/Account/AccountTaskerInterface.php @@ -1,4 +1,5 @@ user = $user; + } + + /** + * @param array $journals + * @param string $direction * * @return array */ @@ -87,20 +95,20 @@ class OperationsRepository implements OperationsRepositoryInterface { $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $journalId = (int) $journal['transaction_journal_id']; + $currencyId = (int)$journal['currency_id']; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'currency_id' => $journal['currency_id'], - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - 'transaction_journals' => [], - ]; + 'currency_id' => $journal['currency_id'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + 'transaction_journals' => [], + ]; $array[$currencyId]['transaction_journals'][$journalId] = [ - 'amount' => app('steam')->$direction((string) $journal['amount']), + 'amount' => app('steam')->$direction((string)$journal['amount']), 'date' => $journal['date'], 'transaction_journal_id' => $journalId, 'budget_name' => $journal['budget_name'], @@ -125,9 +133,9 @@ class OperationsRepository implements OperationsRepositoryInterface * which have the specified accounts. It's grouped per currency, with as few details in the array * as possible. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ @@ -136,44 +144,41 @@ class OperationsRepository implements OperationsRepositoryInterface $journals = $this->getTransactions($start, $end, $accounts, TransactionType::DEPOSIT); return $this->sortByCurrency($journals, 'positive'); - - } - - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; } /** * @inheritDoc */ - public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null - ): array - { + public function sumExpenses( + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $expense = null, + ?TransactionCurrency $currency = null + ): array { $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); return $this->groupByCurrency($journals, 'negative'); - } /** - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $opposing - * @param TransactionCurrency|null $currency - * @param string $type + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $opposing + * @param TransactionCurrency|null $currency + * @param string $type * * @return array */ private function getTransactionsForSum( - string $type, Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $opposing = null, ?TransactionCurrency $currency = null - - ): array - { + string $type, + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $opposing = null, + ?TransactionCurrency $currency = null + ): array { $start->startOfDay(); $end->endOfDay(); @@ -241,8 +246,8 @@ class OperationsRepository implements OperationsRepositoryInterface } /** - * @param array $journals - * @param string $direction + * @param array $journals + * @param string $direction * * @return array */ @@ -251,28 +256,28 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->$direction($journal['amount'])); // also do foreign amount: - $foreignId = (int) $journal['foreign_currency_id']; + $foreignId = (int)$journal['foreign_currency_id']; if (0 !== $foreignId) { $array[$foreignId] = $array[$foreignId] ?? [ - 'sum' => '0', - 'currency_id' => $foreignId, - 'currency_name' => $journal['foreign_currency_name'], - 'currency_symbol' => $journal['foreign_currency_symbol'], - 'currency_code' => $journal['foreign_currency_code'], - 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $foreignId, + 'currency_name' => $journal['foreign_currency_name'], + 'currency_symbol' => $journal['foreign_currency_symbol'], + 'currency_code' => $journal['foreign_currency_code'], + 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], + ]; $array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->$direction($journal['foreign_amount'])); } } @@ -284,18 +289,21 @@ class OperationsRepository implements OperationsRepositoryInterface * @inheritDoc */ public function sumExpensesByDestination( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null - ): array - { + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $expense = null, + ?TransactionCurrency $currency = null + ): array { $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); return $this->groupByDirection($journals, 'destination', 'negative'); } /** - * @param array $journals - * @param string $direction - * @param string $method + * @param array $journals + * @param string $direction + * @param string $method * * @return array */ @@ -308,31 +316,31 @@ class OperationsRepository implements OperationsRepositoryInterface foreach ($journals as $journal) { $key = sprintf('%s-%s', $journal[$idKey], $journal['currency_id']); $array[$key] = $array[$key] ?? [ + 'id' => $journal[$idKey], + 'name' => $journal[$nameKey], + 'sum' => '0', + 'currency_id' => $journal['currency_id'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->$method((string)$journal['amount'])); + + // also do foreign amount: + if (0 !== (int)$journal['foreign_currency_id']) { + $key = sprintf('%s-%s', $journal[$idKey], $journal['foreign_currency_id']); + $array[$key] = $array[$key] ?? [ 'id' => $journal[$idKey], 'name' => $journal[$nameKey], 'sum' => '0', - 'currency_id' => $journal['currency_id'], - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], + 'currency_id' => $journal['foreign_currency_id'], + 'currency_name' => $journal['foreign_currency_name'], + 'currency_symbol' => $journal['foreign_currency_symbol'], + 'currency_code' => $journal['foreign_currency_code'], + 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], ]; - $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->$method((string) $journal['amount'])); - - // also do foreign amount: - if (0 !== (int) $journal['foreign_currency_id']) { - $key = sprintf('%s-%s', $journal[$idKey], $journal['foreign_currency_id']); - $array[$key] = $array[$key] ?? [ - 'id' => $journal[$idKey], - 'name' => $journal[$nameKey], - 'sum' => '0', - 'currency_id' => $journal['foreign_currency_id'], - 'currency_name' => $journal['foreign_currency_name'], - 'currency_symbol' => $journal['foreign_currency_symbol'], - 'currency_code' => $journal['foreign_currency_code'], - 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], - ]; - $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->$method((string) $journal['foreign_amount'])); + $array[$key]['sum'] = bcadd($array[$key]['sum'], app('steam')->$method((string)$journal['foreign_amount'])); } } @@ -343,9 +351,12 @@ class OperationsRepository implements OperationsRepositoryInterface * @inheritDoc */ public function sumExpensesBySource( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null - ): array - { + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $expense = null, + ?TransactionCurrency $currency = null + ): array { $journals = $this->getTransactionsForSum(TransactionType::WITHDRAWAL, $start, $end, $accounts, $expense, $currency); return $this->groupByDirection($journals, 'source', 'negative'); @@ -354,9 +365,13 @@ class OperationsRepository implements OperationsRepositoryInterface /** * @inheritDoc */ - public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null - ): array - { + public function sumIncome( + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $revenue = null, + ?TransactionCurrency $currency = null + ): array { $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); return $this->groupByCurrency($journals, 'positive'); @@ -366,9 +381,12 @@ class OperationsRepository implements OperationsRepositoryInterface * @inheritDoc */ public function sumIncomeByDestination( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null - ): array - { + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $revenue = null, + ?TransactionCurrency $currency = null + ): array { $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); return $this->groupByDirection($journals, 'destination', 'positive'); @@ -378,9 +396,12 @@ class OperationsRepository implements OperationsRepositoryInterface * @inheritDoc */ public function sumIncomeBySource( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null - ): array - { + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $revenue = null, + ?TransactionCurrency $currency = null + ): array { $journals = $this->getTransactionsForSum(TransactionType::DEPOSIT, $start, $end, $accounts, $revenue, $currency); return $this->groupByDirection($journals, 'source', 'positive'); @@ -397,7 +418,7 @@ class OperationsRepository implements OperationsRepositoryInterface } /** - * @param array $journals + * @param array $journals * * @return array */ @@ -410,9 +431,9 @@ class OperationsRepository implements OperationsRepositoryInterface } $final = []; foreach ($return as $array) { - $array['difference_float'] = (float) $array['difference']; - $array['in_float'] = (float) $array['in']; - $array['out_float'] = (float) $array['out']; + $array['difference_float'] = (float)$array['difference']; + $array['in_float'] = (float)$array['in']; + $array['out_float'] = (float)$array['out']; $final[] = $array; } @@ -420,8 +441,8 @@ class OperationsRepository implements OperationsRepositoryInterface } /** - * @param array $return - * @param array $journal + * @param array $return + * @param array $journal * * @return array */ @@ -436,31 +457,31 @@ class OperationsRepository implements OperationsRepositoryInterface // source first $return[$sourceKey] = $return[$sourceKey] ?? [ - 'id' => (string) $sourceId, - 'name' => $journal['source_account_name'], - 'difference' => '0', - 'difference_float' => 0, - 'in' => '0', - 'in_float' => 0, - 'out' => '0', - 'out_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'id' => (string)$sourceId, + 'name' => $journal['source_account_name'], + 'difference' => '0', + 'difference_float' => 0, + 'in' => '0', + 'in_float' => 0, + 'out' => '0', + 'out_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; // dest next: $return[$destKey] = $return[$destKey] ?? [ - 'id' => (string) $destinationId, - 'name' => $journal['destination_account_name'], - 'difference' => '0', - 'difference_float' => 0, - 'in' => '0', - 'in_float' => 0, - 'out' => '0', - 'out_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['currency_code'], - ]; + 'id' => (string)$destinationId, + 'name' => $journal['destination_account_name'], + 'difference' => '0', + 'difference_float' => 0, + 'in' => '0', + 'in_float' => 0, + 'out' => '0', + 'out_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['currency_code'], + ]; // source account? money goes out! $return[$sourceKey]['out'] = bcadd($return[$sourceKey]['out'], app('steam')->negative($amount)); @@ -480,31 +501,31 @@ class OperationsRepository implements OperationsRepositoryInterface // same as above: // source first $return[$sourceKey] = $return[$sourceKey] ?? [ - 'id' => (string) $sourceId, - 'name' => $journal['source_account_name'], - 'difference' => '0', - 'difference_float' => 0, - 'in' => '0', - 'in_float' => 0, - 'out' => '0', - 'out_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'id' => (string)$sourceId, + 'name' => $journal['source_account_name'], + 'difference' => '0', + 'difference_float' => 0, + 'in' => '0', + 'in_float' => 0, + 'out' => '0', + 'out_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; // dest next: $return[$destKey] = $return[$destKey] ?? [ - 'id' => (string) $destinationId, - 'name' => $journal['destination_account_name'], - 'difference' => '0', - 'difference_float' => 0, - 'in' => '0', - 'in_float' => 0, - 'out' => '0', - 'out_float' => 0, - 'currency_id' => (string) $currencyId, - 'currency_code' => $journal['foreign_currency_code'], - ]; + 'id' => (string)$destinationId, + 'name' => $journal['destination_account_name'], + 'difference' => '0', + 'difference_float' => 0, + 'in' => '0', + 'in_float' => 0, + 'out' => '0', + 'out_float' => 0, + 'currency_id' => (string)$currencyId, + 'currency_code' => $journal['foreign_currency_code'], + ]; // source account? money goes out! (same as above) $return[$sourceKey]['out'] = bcadd($return[$sourceKey]['out'], app('steam')->negative($amount)); $return[$sourceKey]['difference'] = bcadd($return[$sourceKey]['out'], $return[$sourceKey]['in']); @@ -512,7 +533,6 @@ class OperationsRepository implements OperationsRepositoryInterface // destination account? money comes in: $return[$destKey]['in'] = bcadd($return[$destKey]['in'], $amount); $return[$destKey]['difference'] = bcadd($return[$destKey]['out'], $return[$destKey]['in']); - } return $return; diff --git a/app/Repositories/Account/OperationsRepositoryInterface.php b/app/Repositories/Account/OperationsRepositoryInterface.php index a8cc6db89b..e70e27f4a4 100644 --- a/app/Repositories/Account/OperationsRepositoryInterface.php +++ b/app/Repositories/Account/OperationsRepositoryInterface.php @@ -38,9 +38,9 @@ interface OperationsRepositoryInterface * which have the specified accounts. It's grouped per currency, with as few details in the array * as possible. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts * * @return array */ @@ -51,114 +51,140 @@ interface OperationsRepositoryInterface * which have the specified accounts. It's grouped per currency, with as few details in the array * as possible. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ public function listIncome(Carbon $start, Carbon $end, ?Collection $accounts = null): array; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** * Sum of withdrawal journals in period for a set of accounts, grouped per currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $expense - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $expense + * @param TransactionCurrency|null $currency * * @return array */ - public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + public function sumExpenses( + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $expense = null, + ?TransactionCurrency $currency = null ): array; /** * Sum of withdrawal journals in period for a set of accounts, grouped per destination / currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $expense - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $expense + * @param TransactionCurrency|null $currency * * @return array */ public function sumExpensesByDestination( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $expense = null, + ?TransactionCurrency $currency = null ): array; /** * Sum of withdrawal journals in period for a set of accounts, grouped per source / currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $expense - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $expense + * @param TransactionCurrency|null $currency * * @return array */ public function sumExpensesBySource( - Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $expense = null, ?TransactionCurrency $currency = null + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $expense = null, + ?TransactionCurrency $currency = null ): array; /** * Sum of income journals in period for a set of accounts, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $revenue - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $revenue + * @param TransactionCurrency|null $currency * * @return array */ - public function sumIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, ?TransactionCurrency $currency = null + public function sumIncome( + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $revenue = null, + ?TransactionCurrency $currency = null ): array; /** * Sum of income journals in period for a set of accounts, grouped per destination + currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $revenue - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $revenue + * @param TransactionCurrency|null $currency * * @return array */ - public function sumIncomeByDestination(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, - ?TransactionCurrency $currency = null + public function sumIncomeByDestination( + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $revenue = null, + ?TransactionCurrency $currency = null ): array; /** * Sum of income journals in period for a set of accounts, grouped per source + currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $revenue - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $revenue + * @param TransactionCurrency|null $currency * * @return array */ - public function sumIncomeBySource(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $revenue = null, - ?TransactionCurrency $currency = null + public function sumIncomeBySource( + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $revenue = null, + ?TransactionCurrency $currency = null ): array; /** * Sum of transfers in period for a set of accounts, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param TransactionCurrency|null $currency * * @return array */ diff --git a/app/Repositories/Attachment/AttachmentRepository.php b/app/Repositories/Attachment/AttachmentRepository.php index b6dc30e99d..85dd226ae2 100644 --- a/app/Repositories/Attachment/AttachmentRepository.php +++ b/app/Repositories/Attachment/AttachmentRepository.php @@ -1,4 +1,5 @@ getAttachmentLocation($attachment); try { Storage::disk('upload')->delete($path); - } catch (Exception $e) { // @phpstan-ignore-line + } catch (UnableToDeleteFile $e) { // @ignoreException } $attachment->delete(); @@ -66,7 +70,32 @@ class AttachmentRepository implements AttachmentRepositoryInterface } /** - * @param Attachment $attachment + * @param Attachment $attachment + * + * @return string + */ + public function getContent(Attachment $attachment): string + { + // create a disk. + $disk = Storage::disk('upload'); + $file = $attachment->fileName(); + $unencryptedContent = ''; + + if ($disk->exists($file)) { + $encryptedContent = (string)$disk->get($file); + + try { + $unencryptedContent = Crypt::decrypt($encryptedContent); // verified + } catch (DecryptException $e) { + $unencryptedContent = $encryptedContent; + } + } + + return $unencryptedContent; + } + + /** + * @param Attachment $attachment * * @return bool */ @@ -86,35 +115,10 @@ class AttachmentRepository implements AttachmentRepositoryInterface return $this->user->attachments()->get(); } - /** - * @param Attachment $attachment - * - * @return string - */ - public function getContent(Attachment $attachment): string - { - // create a disk. - $disk = Storage::disk('upload'); - $file = $attachment->fileName(); - $unencryptedContent = ''; - - if ($disk->exists($file)) { - $encryptedContent = (string) $disk->get($file); - - try { - $unencryptedContent = Crypt::decrypt($encryptedContent); // verified - } catch (DecryptException $e) { - $unencryptedContent = $encryptedContent; - } - } - - return $unencryptedContent; - } - /** * Get attachment note text or empty string. * - * @param Attachment $attachment + * @param Attachment $attachment * * @return string|null */ @@ -122,22 +126,14 @@ class AttachmentRepository implements AttachmentRepositoryInterface { $note = $attachment->notes()->first(); if (null !== $note) { - return (string) $note->text; + return (string)$note->text; } return null; } /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param array $data + * @param array $data * * @return Attachment * @throws FireflyException @@ -156,11 +152,18 @@ class AttachmentRepository implements AttachmentRepositoryInterface } /** - * @param Attachment $attachment - * @param array $data + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @param Attachment $attachment + * @param array $data * * @return Attachment - * @throws Exception */ public function update(Attachment $attachment, array $data): Attachment { @@ -168,31 +171,30 @@ class AttachmentRepository implements AttachmentRepositoryInterface $attachment->title = $data['title']; } - if (array_key_exists('filename', $data) && '' !== (string) $data['filename'] && $data['filename'] !== $attachment->filename) { + if (array_key_exists('filename', $data) && '' !== (string)$data['filename'] && $data['filename'] !== $attachment->filename) { $attachment->filename = $data['filename']; } // update model (move attachment) // should be validated already: if (array_key_exists('attachable_type', $data) && array_key_exists('attachable_id', $data)) { - $attachment->attachable_id = (int) $data['attachable_id']; + $attachment->attachable_id = (int)$data['attachable_id']; $attachment->attachable_type = sprintf('FireflyIII\\Models\\%s', $data['attachable_type']); } $attachment->save(); $attachment->refresh(); if (array_key_exists('notes', $data)) { - $this->updateNote($attachment, (string) $data['notes']); + $this->updateNote($attachment, (string)$data['notes']); } return $attachment; } /** - * @param Attachment $attachment - * @param string $note + * @param Attachment $attachment + * @param string $note * * @return bool - * @throws Exception */ public function updateNote(Attachment $attachment, string $note): bool { @@ -201,8 +203,8 @@ class AttachmentRepository implements AttachmentRepositoryInterface if (null !== $dbNote) { try { $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException + } catch (LogicException $e) { + Log::error($e->getMessage()); } } @@ -210,7 +212,7 @@ class AttachmentRepository implements AttachmentRepositoryInterface } $dbNote = $attachment->notes()->first(); if (null === $dbNote) { - $dbNote = new Note; + $dbNote = new Note(); $dbNote->noteable()->associate($attachment); } $dbNote->text = trim($note); diff --git a/app/Repositories/Attachment/AttachmentRepositoryInterface.php b/app/Repositories/Attachment/AttachmentRepositoryInterface.php index 4a8e3bfbcb..50d2d3b8a9 100644 --- a/app/Repositories/Attachment/AttachmentRepositoryInterface.php +++ b/app/Repositories/Attachment/AttachmentRepositoryInterface.php @@ -1,4 +1,5 @@ . + */ + +declare(strict_types=1); + +namespace FireflyIII\Repositories\AuditLogEntry; + +use FireflyIII\Models\AuditLogEntry; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Collection; + +/** + * Class ALERepository + */ +class ALERepository implements ALERepositoryInterface +{ + /** + * @inheritDoc + */ + public function getForObject(Model $model): Collection + { + // all Models have an ID. + return AuditLogEntry::where('auditable_id', $model->id)->where('auditable_type', get_class($model))->get(); // @phpstan-ignore-line + } + + /** + * @inheritDoc + */ + public function store(array $data): AuditLogEntry + { + $auditLogEntry = new AuditLogEntry(); + + $auditLogEntry->auditable()->associate($data['auditable']); + $auditLogEntry->changer()->associate($data['changer']); + $auditLogEntry->action = $data['action']; + $auditLogEntry->before = $data['before']; + $auditLogEntry->after = $data['after']; + $auditLogEntry->save(); + return $auditLogEntry; + } +} diff --git a/app/Repositories/AuditLogEntry/ALERepositoryInterface.php b/app/Repositories/AuditLogEntry/ALERepositoryInterface.php new file mode 100644 index 0000000000..26117f8457 --- /dev/null +++ b/app/Repositories/AuditLogEntry/ALERepositoryInterface.php @@ -0,0 +1,47 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Repositories\AuditLogEntry; + +use FireflyIII\Models\AuditLogEntry; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Collection; + +/** + * Interface ALERepositoryInterface + */ +interface ALERepositoryInterface +{ + /** + * @param Model $model + * @return Collection + */ + public function getForObject(Model $model): Collection; + + /** + * @param array $data + * @return AuditLogEntry + */ + public function store(array $data): AuditLogEntry; +} diff --git a/app/Repositories/Bill/BillRepository.php b/app/Repositories/Bill/BillRepository.php index f0277b97c1..0884bdd790 100644 --- a/app/Repositories/Bill/BillRepository.php +++ b/app/Repositories/Bill/BillRepository.php @@ -1,4 +1,5 @@ take($limit)->get(); } + /** + * @inheritDoc + * @deprecated + */ + public function collectBillsUnpaidInRange(Carbon $start, Carbon $end): Collection + { + $bills = $this->getActiveBills(); + $return = new Collection(); + /** @var Bill $bill */ + foreach ($bills as $bill) { + $dates = $this->getPayDatesInRange($bill, $start, $end); + $count = $bill->transactionJournals()->after($start)->before($end)->count(); + $total = $dates->count() - $count; + if ($total > 0) { + $return->push($bill); + } + } + + return $bills; + } + + /** + * @return Collection + */ + public function getActiveBills(): Collection + { + return $this->user->bills() + ->where('active', true) + ->orderBy('bills.name', 'ASC') + ->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount'),]); + } + + /** + * Between start and end, tells you on which date(s) the bill is expected to hit. + * + * @param Bill $bill + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getPayDatesInRange(Bill $bill, Carbon $start, Carbon $end): Collection + { + $set = new Collection(); + $currentStart = clone $start; + //Log::debug(sprintf('Now at bill "%s" (%s)', $bill->name, $bill->repeat_freq)); + //Log::debug(sprintf('First currentstart is %s', $currentStart->format('Y-m-d'))); + + while ($currentStart <= $end) { + //Log::debug(sprintf('Currentstart is now %s.', $currentStart->format('Y-m-d'))); + $nextExpectedMatch = $this->nextDateMatch($bill, $currentStart); + //Log::debug(sprintf('Next Date match after %s is %s', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); + if ($nextExpectedMatch > $end) {// If nextExpectedMatch is after end, we continue + break; + } + $set->push(clone $nextExpectedMatch); + //Log::debug(sprintf('Now %d dates in set.', $set->count())); + $nextExpectedMatch->addDay(); + + //Log::debug(sprintf('Currentstart (%s) has become %s.', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); + + $currentStart = clone $nextExpectedMatch; + } + + return $set; + } + + /** + * Given a bill and a date, this method will tell you at which moment this bill expects its next + * transaction. Whether or not it is there already, is not relevant. + * + * @param Bill $bill + * @param Carbon $date + * + * @return Carbon + */ + public function nextDateMatch(Bill $bill, Carbon $date): Carbon + { + $cache = new CacheProperties(); + $cache->addProperty($bill->id); + $cache->addProperty('nextDateMatch'); + $cache->addProperty($date); + if ($cache->has()) { + return $cache->get(); + } + // find the most recent date for this bill NOT in the future. Cache this date: + $start = clone $bill->date; + + while ($start < $date) { + $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); + } + $cache->store($start); + + return $start; + } + + /** + * @param array $data + * + * @return Bill + * @throws FireflyException + */ + public function store(array $data): Bill + { + /** @var BillFactory $factory */ + $factory = app(BillFactory::class); + $factory->setUser($this->user); + + return $factory->create($data); + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + /** * Correct order of piggies in case of issues. */ @@ -93,7 +213,7 @@ class BillRepository implements BillRepositoryInterface $set = $this->user->bills()->orderBy('order', 'ASC')->get(); $current = 1; foreach ($set as $bill) { - if ((int) $bill->order !== $current) { + if ((int)$bill->order !== $current) { $bill->order = $current; $bill->save(); } @@ -102,7 +222,7 @@ class BillRepository implements BillRepositoryInterface } /** - * @param Bill $bill + * @param Bill $bill * * @return bool * @@ -128,15 +248,15 @@ class BillRepository implements BillRepositoryInterface /** * Find bill by parameters. * - * @param int|null $billId - * @param string|null $billName + * @param int|null $billId + * @param string|null $billName * * @return Bill|null */ public function findBill(?int $billId, ?string $billName): ?Bill { if (null !== $billId) { - $searchResult = $this->find((int) $billId); + $searchResult = $this->find((int)$billId); if (null !== $searchResult) { Log::debug(sprintf('Found bill based on #%d, will return it.', $billId)); @@ -144,7 +264,7 @@ class BillRepository implements BillRepositoryInterface } } if (null !== $billName) { - $searchResult = $this->findByName((string) $billName); + $searchResult = $this->findByName((string)$billName); if (null !== $searchResult) { Log::debug(sprintf('Found bill based on "%s", will return it.', $billName)); @@ -159,7 +279,7 @@ class BillRepository implements BillRepositoryInterface /** * Find a bill by ID. * - * @param int $billId + * @param int $billId * * @return Bill|null */ @@ -171,7 +291,7 @@ class BillRepository implements BillRepositoryInterface /** * Find a bill by name. * - * @param string $name + * @param string $name * * @return Bill|null */ @@ -183,7 +303,7 @@ class BillRepository implements BillRepositoryInterface /** * Get all attachments. * - * @param Bill $bill + * @param Bill $bill * * @return Collection */ @@ -217,14 +337,28 @@ class BillRepository implements BillRepositoryInterface } /** - * @param Collection $accounts + * @param Collection $accounts * * @return Collection */ public function getBillsForAccounts(Collection $accounts): Collection { - $fields = ['bills.id', 'bills.created_at', 'bills.updated_at', 'bills.deleted_at', 'bills.user_id', 'bills.name', 'bills.amount_min', - 'bills.amount_max', 'bills.date', 'bills.transaction_currency_id', 'bills.repeat_freq', 'bills.skip', 'bills.automatch', 'bills.active',]; + $fields = [ + 'bills.id', + 'bills.created_at', + 'bills.updated_at', + 'bills.deleted_at', + 'bills.user_id', + 'bills.name', + 'bills.amount_min', + 'bills.amount_max', + 'bills.date', + 'bills.transaction_currency_id', + 'bills.repeat_freq', + 'bills.skip', + 'bills.automatch', + 'bills.active', + ]; $ids = $accounts->pluck('id')->toArray(); return $this->user->bills() @@ -249,14 +383,16 @@ class BillRepository implements BillRepositoryInterface } /** + * TODO unsure why this is deprecated. + * * Get the total amount of money paid for the users active bills in the date range given. * This amount will be negative (they're expenses). This method is equal to * getBillsUnpaidInRange. So the debug comments are gone. * - * @param Carbon $start - * @param Carbon $end - * + * @param Carbon $start + * @param Carbon $end * @return string + * @deprecated */ public function getBillsPaidInRange(Carbon $start, Carbon $end): string { @@ -268,7 +404,7 @@ class BillRepository implements BillRepositoryInterface $set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']); if ($set->count() > 0) { $journalIds = $set->pluck('id')->toArray(); - $amount = (string) Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); + $amount = (string)Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); $sum = bcadd($sum, $amount); //Log::debug(sprintf('Total > 0, so add to sum %f, which becomes %f', $amount, $sum)); } @@ -278,24 +414,15 @@ class BillRepository implements BillRepositoryInterface } /** - * @return Collection - */ - public function getActiveBills(): Collection - { - return $this->user->bills() - ->where('active', true) - ->orderBy('bills.name', 'ASC') - ->get(['bills.*', DB::raw('((bills.amount_min + bills.amount_max) / 2) AS expectedAmount'),]); - } - - /** + * TODO unsure why this is deprecated. + * * Get the total amount of money paid for the users active bills in the date range given, * grouped per currency. - * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array + * @deprecated */ public function getBillsPaidInRangePerCurrency(Carbon $start, Carbon $end): array { @@ -305,10 +432,10 @@ class BillRepository implements BillRepositoryInterface foreach ($bills as $bill) { /** @var Collection $set */ $set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']); - $currencyId = (int) $bill->transaction_currency_id; + $currencyId = (int)$bill->transaction_currency_id; if ($set->count() > 0) { $journalIds = $set->pluck('id')->toArray(); - $amount = (string) Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); + $amount = (string)Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); $return[$currencyId] = $return[$currencyId] ?? '0'; $return[$currencyId] = bcadd($amount, $return[$currencyId]); //Log::debug(sprintf('Total > 0, so add to sum %f, which becomes %f (currency %d)', $amount, $return[$currencyId], $currencyId)); @@ -319,12 +446,14 @@ class BillRepository implements BillRepositoryInterface } /** + * TODO unsure why this is deprecated. + * * Get the total amount of money due for the users active bills in the date range given. This amount will be positive. * - * @param Carbon $start - * @param Carbon $end - * + * @param Carbon $start + * @param Carbon $end * @return string + * @deprecated */ public function getBillsUnpaidInRange(Carbon $start, Carbon $end): string { @@ -341,7 +470,7 @@ class BillRepository implements BillRepositoryInterface if ($total > 0) { $average = bcdiv(bcadd($bill->amount_max, $bill->amount_min), '2'); - $multi = bcmul($average, (string) $total); + $multi = bcmul($average, (string)$total); $sum = bcadd($sum, $multi); //Log::debug(sprintf('Total > 0, so add to sum %f, which becomes %f', $multi, $sum)); } @@ -351,77 +480,14 @@ class BillRepository implements BillRepositoryInterface } /** - * Between start and end, tells you on which date(s) the bill is expected to hit. + * TODO unsure why this is deprecated. * - * @param Bill $bill - * @param Carbon $start - * @param Carbon $end - * - * @return Collection - * @throws JsonException - */ - public function getPayDatesInRange(Bill $bill, Carbon $start, Carbon $end): Collection - { - $set = new Collection; - $currentStart = clone $start; - //Log::debug(sprintf('Now at bill "%s" (%s)', $bill->name, $bill->repeat_freq)); - //Log::debug(sprintf('First currentstart is %s', $currentStart->format('Y-m-d'))); - - while ($currentStart <= $end) { - //Log::debug(sprintf('Currentstart is now %s.', $currentStart->format('Y-m-d'))); - $nextExpectedMatch = $this->nextDateMatch($bill, $currentStart); - //Log::debug(sprintf('Next Date match after %s is %s', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); - if ($nextExpectedMatch > $end) {// If nextExpectedMatch is after end, we continue - break; - } - $set->push(clone $nextExpectedMatch); - //Log::debug(sprintf('Now %d dates in set.', $set->count())); - $nextExpectedMatch->addDay(); - - //Log::debug(sprintf('Currentstart (%s) has become %s.', $currentStart->format('Y-m-d'), $nextExpectedMatch->format('Y-m-d'))); - - $currentStart = clone $nextExpectedMatch; - } - - return $set; - } - - /** - * Given a bill and a date, this method will tell you at which moment this bill expects its next - * transaction. Whether or not it is there already, is not relevant. - * - * @param Bill $bill - * @param Carbon $date - * - * @return Carbon - */ - public function nextDateMatch(Bill $bill, Carbon $date): Carbon - { - $cache = new CacheProperties; - $cache->addProperty($bill->id); - $cache->addProperty('nextDateMatch'); - $cache->addProperty($date); - if ($cache->has()) { - return $cache->get(); - } - // find the most recent date for this bill NOT in the future. Cache this date: - $start = clone $bill->date; - - while ($start < $date) { - $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); - } - $cache->store($start); - - return $start; - } - - /** * Get the total amount of money due for the users active bills in the date range given. * - * @param Carbon $start - * @param Carbon $end - * + * @param Carbon $start + * @param Carbon $end * @return array + * @deprecated */ public function getBillsUnpaidInRangePerCurrency(Carbon $start, Carbon $end): array { @@ -433,13 +499,13 @@ class BillRepository implements BillRepositoryInterface $dates = $this->getPayDatesInRange($bill, $start, $end); $count = $bill->transactionJournals()->after($start)->before($end)->count(); $total = $dates->count() - $count; - $currencyId = (int) $bill->transaction_currency_id; + $currencyId = (int)$bill->transaction_currency_id; //Log::debug(sprintf('Dates = %d, journalCount = %d, total = %d', $dates->count(), $count, $total)); if ($total > 0) { - $average = bcdiv(bcadd((string) $bill->amount_max, (string) $bill->amount_min), '2'); - $multi = bcmul($average, (string) $total); + $average = bcdiv(bcadd((string)$bill->amount_max, (string)$bill->amount_min), '2'); + $multi = bcmul($average, (string)$total); $return[$currencyId] = $return[$currencyId] ?? '0'; $return[$currencyId] = bcadd($return[$currencyId], $multi); //Log::debug(sprintf('Total > 0, so add to sum %f, which becomes %f (for currency %d)', $multi, $return[$currencyId], $currencyId)); @@ -452,7 +518,7 @@ class BillRepository implements BillRepositoryInterface /** * Get all bills with these ID's. * - * @param array $billIds + * @param array $billIds * * @return Collection */ @@ -464,7 +530,7 @@ class BillRepository implements BillRepositoryInterface /** * Get text or return empty string. * - * @param Bill $bill + * @param Bill $bill * * @return string */ @@ -473,14 +539,14 @@ class BillRepository implements BillRepositoryInterface /** @var Note $note */ $note = $bill->notes()->first(); if (null !== $note) { - return (string) $note->text; + return (string)$note->text; } return ''; } /** - * @param Bill $bill + * @param Bill $bill * * @return array */ @@ -498,35 +564,35 @@ class BillRepository implements BillRepositoryInterface foreach ($journals as $journal) { /** @var Transaction $transaction */ $transaction = $journal->transactions()->where('amount', '<', 0)->first(); - $currencyId = (int) $journal->transaction_currency_id; + $currencyId = (int)$journal->transaction_currency_id; $currency = $journal->transactionCurrency; $result[$currencyId] = $result[$currencyId] ?? [ - 'sum' => '0', - 'count' => 0, - 'avg' => '0', - 'currency_id' => $currency->id, - 'currency_code' => $currency->code, - 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => $currency->decimal_places, - ]; + 'sum' => '0', + 'count' => 0, + 'avg' => '0', + 'currency_id' => $currency->id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => $currency->decimal_places, + ]; $result[$currencyId]['sum'] = bcadd($result[$currencyId]['sum'], $transaction->amount); $result[$currencyId]['count']++; } // after loop, re-loop for avg. /** - * @var int $currencyId + * @var int $currencyId * @var array $arr */ foreach ($result as $currencyId => $arr) { - $result[$currencyId]['avg'] = bcdiv($arr['sum'], (string) $arr['count']); + $result[$currencyId]['avg'] = bcdiv($arr['sum'], (string)$arr['count']); } return $result; } /** - * @param int $size + * @param int $size * * @return LengthAwarePaginator */ @@ -540,9 +606,9 @@ class BillRepository implements BillRepositoryInterface /** * The "paid dates" list is a list of dates of transaction journals that are linked to this bill. * - * @param Bill $bill - * @param Carbon $start - * @param Carbon $end + * @param Bill $bill + * @param Carbon $start + * @param Carbon $end * * @return Collection */ @@ -552,17 +618,18 @@ class BillRepository implements BillRepositoryInterface return $bill->transactionJournals() ->before($end)->after($start)->get( - [ - 'transaction_journals.id', 'transaction_journals.date', - 'transaction_journals.transaction_group_id', - ] - ); + [ + 'transaction_journals.id', + 'transaction_journals.date', + 'transaction_journals.transaction_group_id', + ] + ); } /** * Return all rules for one bill * - * @param Bill $bill + * @param Bill $bill * * @return Collection */ @@ -581,7 +648,7 @@ class BillRepository implements BillRepositoryInterface * * 5 => [['id' => 1, 'title' => 'Some rule'],['id' => 2, 'title' => 'Some other rule']] * - * @param Collection $collection + * @param Collection $collection * * @return array */ @@ -606,8 +673,8 @@ class BillRepository implements BillRepositoryInterface } /** - * @param Bill $bill - * @param Carbon $date + * @param Bill $bill + * @param Carbon $date * * @return array */ @@ -621,8 +688,8 @@ class BillRepository implements BillRepositoryInterface $result = []; $journals = $bill->transactionJournals() - ->where('date', '>=', $date->year . '-01-01 00:00:00') - ->where('date', '<=', $date->year . '-12-31 23:59:59') + ->where('date', '>=', $date->year.'-01-01 00:00:00') + ->where('date', '<=', $date->year.'-12-31 23:59:59') ->get(); /** @var TransactionJournal $journal */ @@ -632,28 +699,28 @@ class BillRepository implements BillRepositoryInterface if (null === $transaction) { continue; } - $currencyId = (int) $journal->transaction_currency_id; + $currencyId = (int)$journal->transaction_currency_id; $currency = $journal->transactionCurrency; $result[$currencyId] = $result[$currencyId] ?? [ - 'sum' => '0', - 'count' => 0, - 'avg' => '0', - 'currency_id' => $currency->id, - 'currency_code' => $currency->code, - 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => $currency->decimal_places, - ]; + 'sum' => '0', + 'count' => 0, + 'avg' => '0', + 'currency_id' => $currency->id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => $currency->decimal_places, + ]; $result[$currencyId]['sum'] = bcadd($result[$currencyId]['sum'], $transaction->amount); $result[$currencyId]['count']++; } // after loop, re-loop for avg. /** - * @var int $currencyId + * @var int $currencyId * @var array $arr */ foreach ($result as $currencyId => $arr) { - $result[$currencyId]['avg'] = bcdiv($arr['sum'], (string) $arr['count']); + $result[$currencyId]['avg'] = bcdiv($arr['sum'], (string)$arr['count']); } return $result; @@ -662,14 +729,14 @@ class BillRepository implements BillRepositoryInterface /** * Link a set of journals to a bill. * - * @param Bill $bill - * @param array $transactions + * @param Bill $bill + * @param array $transactions */ public function linkCollectionToBill(Bill $bill, array $transactions): void { /** @var Transaction $transaction */ foreach ($transactions as $transaction) { - $journal = $bill->user->transactionJournals()->find((int) $transaction['transaction_journal_id']); + $journal = $bill->user->transactionJournals()->find((int)$transaction['transaction_journal_id']); $journal->bill_id = $bill->id; $journal->save(); Log::debug(sprintf('Linked journal #%d to bill #%d', $journal->id, $bill->id)); @@ -679,15 +746,15 @@ class BillRepository implements BillRepositoryInterface /** * Given the date in $date, this method will return a moment in the future where the bill is expected to be paid. * - * @param Bill $bill - * @param Carbon $date + * @param Bill $bill + * @param Carbon $date * * @return Carbon * @throws JsonException */ public function nextExpectedMatch(Bill $bill, Carbon $date): Carbon { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($bill->id); $cache->addProperty('nextExpectedMatch'); $cache->addProperty($date); @@ -696,12 +763,12 @@ class BillRepository implements BillRepositoryInterface } // find the most recent date for this bill NOT in the future. Cache this date: $start = clone $bill->date; - Log::debug('nextExpectedMatch: Start is ' . $start->format('Y-m-d')); + Log::debug('nextExpectedMatch: Start is '.$start->format('Y-m-d')); while ($start < $date) { Log::debug(sprintf('$start (%s) < $date (%s)', $start->format('Y-m-d'), $date->format('Y-m-d'))); $start = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); - Log::debug('Start is now ' . $start->format('Y-m-d')); + Log::debug('Start is now '.$start->format('Y-m-d')); } $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); @@ -715,8 +782,8 @@ class BillRepository implements BillRepositoryInterface $start = clone $end; $end = app('navigation')->addPeriod($start, $bill->repeat_freq, $bill->skip); } - Log::debug('nextExpectedMatch: Final start is ' . $start->format('Y-m-d')); - Log::debug('nextExpectedMatch: Matching end is ' . $end->format('Y-m-d')); + Log::debug('nextExpectedMatch: Final start is '.$start->format('Y-m-d')); + Log::debug('nextExpectedMatch: Matching end is '.$end->format('Y-m-d')); $cache->store($start); @@ -734,8 +801,8 @@ class BillRepository implements BillRepositoryInterface } /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ @@ -769,30 +836,67 @@ class BillRepository implements BillRepositoryInterface } /** - * @param User $user + * @inheritDoc */ - public function setUser(User $user): void + public function sumPaidInRange(Carbon $start, Carbon $end): array { - $this->user = $user; + $bills = $this->getActiveBills(); + $return = []; + /** @var Bill $bill */ + foreach ($bills as $bill) { + /** @var Collection $set */ + $set = $bill->transactionJournals()->after($start)->before($end)->get(['transaction_journals.*']); + $currency = $bill->transactionCurrency; + if ($set->count() > 0) { + $journalIds = $set->pluck('id')->toArray(); + $amount = (string)Transaction::whereIn('transaction_journal_id', $journalIds)->where('amount', '<', 0)->sum('amount'); + $return[$currency->id] = $return[$currency->id] ?? [ + 'id' => (string)$currency->id, + 'name' => $currency->name, + 'symbol' => $currency->symbol, + 'code' => $currency->code, + 'decimal_places' => $currency->decimal_places, + 'sum' => '0', + ]; + $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $amount); + } + } + return $return; } /** - * @param array $data - * - * @return Bill - * @throws FireflyException + * @inheritDoc */ - public function store(array $data): Bill + public function sumUnpaidInRange(Carbon $start, Carbon $end): array { - /** @var BillFactory $factory */ - $factory = app(BillFactory::class); - $factory->setUser($this->user); + $bills = $this->getActiveBills(); + $return = []; + /** @var Bill $bill */ + foreach ($bills as $bill) { + $dates = $this->getPayDatesInRange($bill, $start, $end); + $count = $bill->transactionJournals()->after($start)->before($end)->count(); + $total = $dates->count() - $count; - return $factory->create($data); + if ($total > 0) { + $currency = $bill->transactionCurrency; + $average = bcdiv(bcadd($bill->amount_max, $bill->amount_min), '2'); + $return[$currency->id] = $return[$currency->id] ?? [ + 'id' => (string)$currency->id, + 'name' => $currency->name, + 'symbol' => $currency->symbol, + 'code' => $currency->code, + 'decimal_places' => $currency->decimal_places, + 'sum' => '0', + ]; + $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], bcmul($average, (string)$total)); + } + } + + return $return; } /** - * @param Bill $bill + * @param Bill $bill */ public function unlinkAll(Bill $bill): void { @@ -800,8 +904,8 @@ class BillRepository implements BillRepositoryInterface } /** - * @param Bill $bill - * @param array $data + * @param Bill $bill + * @param array $data * * @return Bill */ diff --git a/app/Repositories/Bill/BillRepositoryInterface.php b/app/Repositories/Bill/BillRepositoryInterface.php index fcae8ee822..372d2da8b1 100644 --- a/app/Repositories/Bill/BillRepositoryInterface.php +++ b/app/Repositories/Bill/BillRepositoryInterface.php @@ -1,4 +1,5 @@ [['id' => 1, 'title' => 'Some rule'],['id' => 2, 'title' => 'Some other rule']] * - * @param Collection $collection + * @param Collection $collection * * @return array */ public function getRulesForBills(Collection $collection): array; /** - * @param Bill $bill - * @param Carbon $date + * @param Bill $bill + * @param Carbon $date * * @return array */ @@ -249,8 +259,8 @@ interface BillRepositoryInterface /** * Link a set of journals to a bill. * - * @param Bill $bill - * @param array $transactions + * @param Bill $bill + * @param array $transactions */ public function linkCollectionToBill(Bill $bill, array $transactions): void; @@ -258,39 +268,39 @@ interface BillRepositoryInterface * Given a bill and a date, this method will tell you at which moment this bill expects its next * transaction. Whether or not it is there already, is not relevant. * - * @param Bill $bill - * @param Carbon $date + * @param Bill $bill + * @param Carbon $date * * @return Carbon */ public function nextDateMatch(Bill $bill, Carbon $date): Carbon; /** - * @param Bill $bill - * @param Carbon $date + * @param Bill $bill + * @param Carbon $date * * @return Carbon */ public function nextExpectedMatch(Bill $bill, Carbon $date): Carbon; /** - * @param Bill $bill + * @param Bill $bill * * @return Bill */ public function removeObjectGroup(Bill $bill): Bill; /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ public function searchBill(string $query, int $limit): Collection; /** - * @param Bill $bill - * @param string $objectGroupTitle + * @param Bill $bill + * @param string $objectGroupTitle * * @return Bill */ @@ -299,18 +309,18 @@ interface BillRepositoryInterface /** * Set specific piggy bank to specific order. * - * @param Bill $bill - * @param int $order + * @param Bill $bill + * @param int $order */ public function setOrder(Bill $bill, int $order): void; /** - * @param User $user + * @param User $user */ public function setUser(User $user); /** - * @param array $data + * @param array $data * * @return Bill * @throws FireflyException @@ -318,13 +328,31 @@ interface BillRepositoryInterface public function store(array $data): Bill; /** - * @param Bill $bill + * Collect multi-currency of sum of bills already paid. + * + * @param Carbon $start + * @param Carbon $end + * @return array + */ + public function sumPaidInRange(Carbon $start, Carbon $end): array; + + /** + * Collect multi-currency of sum of bills yet to pay. + * + * @param Carbon $start + * @param Carbon $end + * @return array + */ + public function sumUnpaidInRange(Carbon $start, Carbon $end): array; + + /** + * @param Bill $bill */ public function unlinkAll(Bill $bill): void; /** - * @param Bill $bill - * @param array $data + * @param Bill $bill + * @param array $data * * @return Bill */ diff --git a/app/Repositories/Budget/AvailableBudgetRepository.php b/app/Repositories/Budget/AvailableBudgetRepository.php index 0c45754e0e..a1a080e987 100644 --- a/app/Repositories/Budget/AvailableBudgetRepository.php +++ b/app/Repositories/Budget/AvailableBudgetRepository.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Budget; use Carbon\Carbon; -use Exception; use FireflyIII\Models\AvailableBudget; use FireflyIII\Models\TransactionCurrency; use FireflyIII\User; @@ -48,34 +47,11 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface } /** - * @param AvailableBudget $availableBudget + * @param AvailableBudget $availableBudget */ public function destroyAvailableBudget(AvailableBudget $availableBudget): void { - try { - $availableBudget->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - } - - /** - * Find existing AB. - * - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end - * - * @return AvailableBudget|null - */ - public function find(TransactionCurrency $currency, Carbon $start, Carbon $end): ?AvailableBudget - { - return $this->user->availableBudgets() - ->where('transaction_currency_id', $currency->id) - ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d')) - ->first(); - + $availableBudget->delete(); } /** @@ -86,11 +62,70 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface return $this->user->availableBudgets->find($id); } + /** + * Find existing AB. + * + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * + * @return AvailableBudget|null + */ + public function find(TransactionCurrency $currency, Carbon $start, Carbon $end): ?AvailableBudget + { + return $this->user->availableBudgets() + ->where('transaction_currency_id', $currency->id) + ->where('start_date', $start->format('Y-m-d')) + ->where('end_date', $end->format('Y-m-d')) + ->first(); + } + + /** + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * + * @return string + */ + public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string + { + $amount = '0'; + $availableBudget = $this->user->availableBudgets() + ->where('transaction_currency_id', $currency->id) + ->where('start_date', $start->format('Y-m-d')) + ->where('end_date', $end->format('Y-m-d'))->first(); + if (null !== $availableBudget) { + $amount = (string)$availableBudget->amount; + } + + return $amount; + } + + /** + * @param Carbon $start + * @param Carbon $end + * + * @return array + */ + public function getAvailableBudgetWithCurrency(Carbon $start, Carbon $end): array + { + $return = []; + $availableBudgets = $this->user->availableBudgets() + ->where('start_date', $start->format('Y-m-d')) + ->where('end_date', $end->format('Y-m-d'))->get(); + /** @var AvailableBudget $availableBudget */ + foreach ($availableBudgets as $availableBudget) { + $return[$availableBudget->transaction_currency_id] = $availableBudget->amount; + } + + return $return; + } + /** * Return a list of all available budgets (in all currencies) (for the selected period). * - * @param Carbon|null $start - * @param Carbon|null $end + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ @@ -109,51 +144,10 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface return $query->get(['available_budgets.*']); } - /** - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end - * - * @return string - */ - public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string - { - $amount = '0'; - $availableBudget = $this->user->availableBudgets() - ->where('transaction_currency_id', $currency->id) - ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d'))->first(); - if (null !== $availableBudget) { - $amount = (string) $availableBudget->amount; - } - - return $amount; - } - - /** - * @param Carbon $start - * @param Carbon $end - * - * @return array - */ - public function getAvailableBudgetWithCurrency(Carbon $start, Carbon $end): array - { - $return = []; - $availableBudgets = $this->user->availableBudgets() - ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d'))->get(); - /** @var AvailableBudget $availableBudget */ - foreach ($availableBudgets as $availableBudget) { - $return[$availableBudget->transaction_currency_id] = $availableBudget->amount; - } - - return $return; - } - /** * Returns all available budget objects. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return Collection */ @@ -165,8 +159,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface /** * Returns all available budget objects. * - * @param Carbon|null $start - * @param Carbon|null $end + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection * @@ -198,10 +192,10 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface } /** - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end - * @param string $amount + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * @param string $amount * * @return AvailableBudget * @deprecated @@ -213,7 +207,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface ->where('start_date', $start->format('Y-m-d')) ->where('end_date', $end->format('Y-m-d'))->first(); if (null === $availableBudget) { - $availableBudget = new AvailableBudget; + $availableBudget = new AvailableBudget(); $availableBudget->user()->associate($this->user); $availableBudget->transactionCurrency()->associate($currency); $availableBudget->start_date = $start->format('Y-m-d'); @@ -226,7 +220,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { @@ -234,7 +228,7 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface } /** - * @param array $data + * @param array $data * * @return AvailableBudget|null */ @@ -262,8 +256,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface } /** - * @param AvailableBudget $availableBudget - * @param array $data + * @param AvailableBudget $availableBudget + * @param array $data * * @return AvailableBudget */ @@ -278,8 +272,8 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface } /** - * @param AvailableBudget $availableBudget - * @param array $data + * @param AvailableBudget $availableBudget + * @param array $data * * @return AvailableBudget */ @@ -312,6 +306,5 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface } return $availableBudget; - } } diff --git a/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php b/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php index 2385127975..7537291f96 100644 --- a/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php +++ b/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php @@ -34,30 +34,29 @@ use Illuminate\Support\Collection; */ interface AvailableBudgetRepositoryInterface { - /** * Delete all available budgets. */ public function destroyAll(): void; /** - * @param AvailableBudget $availableBudget + * @param AvailableBudget $availableBudget */ public function destroyAvailableBudget(AvailableBudget $availableBudget): void; /** * Find existing AB. * - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end * * @return AvailableBudget|null */ public function find(TransactionCurrency $currency, Carbon $start, Carbon $end): ?AvailableBudget; /** - * @param int $id + * @param int $id * * @return AvailableBudget|null */ @@ -66,17 +65,17 @@ interface AvailableBudgetRepositoryInterface /** * Return a list of all available budgets (in all currencies) (for the selected period). * - * @param Carbon|null $start - * @param Carbon|null $end + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ public function get(?Carbon $start = null, ?Carbon $end = null): Collection; /** - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end * * @return string * @deprecated @@ -84,8 +83,8 @@ interface AvailableBudgetRepositoryInterface public function getAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end): string; /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -94,7 +93,7 @@ interface AvailableBudgetRepositoryInterface /** * Returns all available budget objects. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return Collection */ @@ -103,8 +102,8 @@ interface AvailableBudgetRepositoryInterface /** * Returns all available budget objects. * - * @param Carbon|null $start - * @param Carbon|null $end + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection * @@ -114,19 +113,19 @@ interface AvailableBudgetRepositoryInterface /** * Get by transaction currency and date. Should always result in one entry or NULL. * - * @param Carbon $start - * @param Carbon $end - * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * @param TransactionCurrency $currency * * @return null|AvailableBudget */ public function getByCurrencyDate(Carbon $start, Carbon $end, TransactionCurrency $currency): ?AvailableBudget; /** - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end - * @param string $amount + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * @param string $amount * * @return AvailableBudget * @deprecated @@ -134,31 +133,30 @@ interface AvailableBudgetRepositoryInterface public function setAvailableBudget(TransactionCurrency $currency, Carbon $start, Carbon $end, string $amount): AvailableBudget; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** - * @param array $data + * @param array $data * * @return AvailableBudget|null */ public function store(array $data): ?AvailableBudget; /** - * @param AvailableBudget $availableBudget - * @param array $data + * @param AvailableBudget $availableBudget + * @param array $data * * @return AvailableBudget */ public function update(AvailableBudget $availableBudget, array $data): AvailableBudget; /** - * @param AvailableBudget $availableBudget - * @param array $data + * @param AvailableBudget $availableBudget + * @param array $data * * @return AvailableBudget */ public function updateAvailableBudget(AvailableBudget $availableBudget, array $data): AvailableBudget; - } diff --git a/app/Repositories/Budget/BudgetLimitRepository.php b/app/Repositories/Budget/BudgetLimitRepository.php index 423a7a5451..bdd7d4b73c 100644 --- a/app/Repositories/Budget/BudgetLimitRepository.php +++ b/app/Repositories/Budget/BudgetLimitRepository.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Repositories\Budget; use Carbon\Carbon; -use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\TransactionCurrencyFactory; use FireflyIII\Models\Budget; @@ -33,6 +32,7 @@ use FireflyIII\Models\TransactionCurrency; use FireflyIII\User; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; +use JsonException; use Log; /** @@ -47,50 +47,49 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface * Tells you which amount has been budgeted (for the given budgets) * in the selected query. Returns a positive amount as a string. * - * @param Carbon $start - * @param Carbon $end - * @param TransactionCurrency $currency - * @param Collection|null $budgets + * @param Carbon $start + * @param Carbon $end + * @param TransactionCurrency $currency + * @param Collection|null $budgets * * @return string */ public function budgeted(Carbon $start, Carbon $end, TransactionCurrency $currency, ?Collection $budgets = null): string { - $query = BudgetLimit - ::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id') + $query = BudgetLimit::leftJoin('budgets', 'budgets.id', '=', 'budget_limits.budget_id') // same complex where query as below. - ->where( - static function (Builder $q5) use ($start, $end) { - $q5->where( - static function (Builder $q1) use ($start, $end) { - $q1->where( - static function (Builder $q2) use ($start, $end) { - $q2->where('budget_limits.end_date', '>=', $start->format('Y-m-d')); - $q2->where('budget_limits.end_date', '<=', $end->format('Y-m-d')); + ->where( + static function (Builder $q5) use ($start, $end) { + $q5->where( + static function (Builder $q1) use ($start, $end) { + $q1->where( + static function (Builder $q2) use ($start, $end) { + $q2->where('budget_limits.end_date', '>=', $start->format('Y-m-d')); + $q2->where('budget_limits.end_date', '<=', $end->format('Y-m-d')); + } + ) + ->orWhere( + static function (Builder $q3) use ($start, $end) { + $q3->where('budget_limits.start_date', '>=', $start->format('Y-m-d')); + $q3->where('budget_limits.start_date', '<=', $end->format('Y-m-d')); + } + ); + } + ) + ->orWhere( + static function (Builder $q4) use ($start, $end) { + // or start is before start AND end is after end. + $q4->where('budget_limits.start_date', '<=', $start->format('Y-m-d')); + $q4->where('budget_limits.end_date', '>=', $end->format('Y-m-d')); + } + ); } ) - ->orWhere( - static function (Builder $q3) use ($start, $end) { - $q3->where('budget_limits.start_date', '>=', $start->format('Y-m-d')); - $q3->where('budget_limits.start_date', '<=', $end->format('Y-m-d')); - } - ); - } - ) - ->orWhere( - static function (Builder $q4) use ($start, $end) { - // or start is before start AND end is after end. - $q4->where('budget_limits.start_date', '<=', $start->format('Y-m-d')); - $q4->where('budget_limits.end_date', '>=', $end->format('Y-m-d')); - } - ); - } - ) - ->where('budget_limits.transaction_currency_id', $currency->id) - ->whereNull('budgets.deleted_at') - ->where('budgets.active', true) - ->where('budgets.user_id', $this->user->id); + ->where('budget_limits.transaction_currency_id', $currency->id) + ->whereNull('budgets.deleted_at') + ->where('budgets.active', true) + ->where('budgets.user_id', $this->user->id); if (null !== $budgets && $budgets->count() > 0) { $query->whereIn('budget_limits.budget_id', $budgets->pluck('id')->toArray()); } @@ -120,37 +119,17 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface /** * Destroy a budget limit. * - * @param BudgetLimit $budgetLimit + * @param BudgetLimit $budgetLimit */ public function destroyBudgetLimit(BudgetLimit $budgetLimit): void { - try { - $budgetLimit->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $budgetLimit->delete(); } /** - * @param Budget $budget - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end - * - * @return BudgetLimit|null - */ - public function find(Budget $budget, TransactionCurrency $currency, Carbon $start, Carbon $end): ?BudgetLimit - { - return $budget->budgetlimits() - ->where('transaction_currency_id', $currency->id) - ->where('start_date', $start->format('Y-m-d')) - ->where('end_date', $end->format('Y-m-d'))->first(); - } - - /** - * @param TransactionCurrency $currency - * @param Carbon|null $start - * @param Carbon|null $end + * @param TransactionCurrency $currency + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ @@ -164,8 +143,8 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface } /** - * @param Carbon|null $start - * @param Carbon|null $end + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ @@ -232,9 +211,9 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface } /** - * @param Budget $budget - * @param Carbon|null $start - * @param Carbon|null $end + * @param Budget $budget + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ @@ -273,11 +252,11 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface ) // budget limit start within period ->orWhere( - static function (Builder $q3) use ($start, $end) { - $q3->where('budget_limits.start_date', '>=', $start->format('Y-m-d 00:00:00')); - $q3->where('budget_limits.start_date', '<=', $end->format('Y-m-d 23:59:59')); - } - ); + static function (Builder $q3) use ($start, $end) { + $q3->where('budget_limits.start_date', '>=', $start->format('Y-m-d 00:00:00')); + $q3->where('budget_limits.start_date', '<=', $end->format('Y-m-d 23:59:59')); + } + ); } ) ->orWhere( @@ -292,7 +271,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { @@ -300,11 +279,11 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface } /** - * @param array $data + * @param array $data * * @return BudgetLimit * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ public function store(array $data): BudgetLimit { @@ -319,7 +298,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface $currency->save(); // find the budget: - $budget = $this->user->budgets()->find((int) $data['budget_id']); + $budget = $this->user->budgets()->find((int)$data['budget_id']); if (null === $budget) { throw new FireflyException('200004: Budget does not exist.'); } @@ -336,7 +315,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface Log::debug('No existing budget limit, create a new one'); // or create one and return it. - $limit = new BudgetLimit; + $limit = new BudgetLimit(); $limit->budget()->associate($budget); $limit->start_date = $data['start_date']->format('Y-m-d'); $limit->end_date = $data['end_date']->format('Y-m-d'); @@ -349,12 +328,28 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface } /** - * @param BudgetLimit $budgetLimit - * @param array $data + * @param Budget $budget + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end + * + * @return BudgetLimit|null + */ + public function find(Budget $budget, TransactionCurrency $currency, Carbon $start, Carbon $end): ?BudgetLimit + { + return $budget->budgetlimits() + ->where('transaction_currency_id', $currency->id) + ->where('start_date', $start->format('Y-m-d')) + ->where('end_date', $end->format('Y-m-d'))->first(); + } + + /** + * @param BudgetLimit $budgetLimit + * @param array $data * * @return BudgetLimit * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ public function update(BudgetLimit $budgetLimit, array $data): BudgetLimit { @@ -386,10 +381,10 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface } /** - * @param Budget $budget - * @param Carbon $start - * @param Carbon $end - * @param string $amount + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end + * @param string $amount * * @return BudgetLimit|null * @@ -424,11 +419,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface // 1 if the left_operand is larger than the right_operand, -1 otherwise. if (null !== $limit && bccomp($amount, '0') <= 0) { Log::debug(sprintf('%s is zero, delete budget limit #%d', $amount, $limit->id)); - try { - $limit->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $limit->delete(); return null; } @@ -442,7 +433,7 @@ class BudgetLimitRepository implements BudgetLimitRepositoryInterface } Log::debug('No existing budget limit, create a new one'); // or create one and return it. - $limit = new BudgetLimit; + $limit = new BudgetLimit(); $limit->budget()->associate($budget); $limit->start_date = $start->startOfDay(); $limit->end_date = $end->startOfDay(); diff --git a/app/Repositories/Budget/BudgetLimitRepositoryInterface.php b/app/Repositories/Budget/BudgetLimitRepositoryInterface.php index 1f93291dde..3c6c914c8a 100644 --- a/app/Repositories/Budget/BudgetLimitRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetLimitRepositoryInterface.php @@ -35,15 +35,14 @@ use Illuminate\Support\Collection; */ interface BudgetLimitRepositoryInterface { - /** * Tells you which amount has been budgeted (for the given budgets) * in the selected query. Returns a positive amount as a string. * - * @param Carbon $start - * @param Carbon $end - * @param TransactionCurrency $currency - * @param Collection|null $budgets + * @param Carbon $start + * @param Carbon $end + * @param TransactionCurrency $currency + * @param Collection|null $budgets * * @return string */ @@ -57,76 +56,75 @@ interface BudgetLimitRepositoryInterface /** * Destroy a budget limit. * - * @param BudgetLimit $budgetLimit + * @param BudgetLimit $budgetLimit */ public function destroyBudgetLimit(BudgetLimit $budgetLimit): void; /** - * @param Budget $budget - * @param TransactionCurrency $currency - * @param Carbon $start - * @param Carbon $end + * @param Budget $budget + * @param TransactionCurrency $currency + * @param Carbon $start + * @param Carbon $end * * @return BudgetLimit|null */ public function find(Budget $budget, TransactionCurrency $currency, Carbon $start, Carbon $end): ?BudgetLimit; /** - * See reference nr. 11 + * TODO this method is not multi currency aware. * - * @param Carbon|null $start - * @param Carbon|null $end + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ public function getAllBudgetLimits(Carbon $start = null, Carbon $end = null): Collection; /** - * @param TransactionCurrency $currency - * @param Carbon|null $start - * @param Carbon|null $end + * @param TransactionCurrency $currency + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ public function getAllBudgetLimitsByCurrency(TransactionCurrency $currency, Carbon $start = null, Carbon $end = null): Collection; /** - * @param Budget $budget - * @param Carbon|null $start - * @param Carbon|null $end + * @param Budget $budget + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ public function getBudgetLimits(Budget $budget, Carbon $start = null, Carbon $end = null): Collection; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** - * @param array $data + * @param array $data * * @return BudgetLimit */ public function store(array $data): BudgetLimit; /** - * @param BudgetLimit $budgetLimit - * @param array $data + * @param BudgetLimit $budgetLimit + * @param array $data * * @return BudgetLimit */ public function update(BudgetLimit $budgetLimit, array $data): BudgetLimit; /** - * @param Budget $budget - * @param Carbon $start - * @param Carbon $end - * @param string $amount + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end + * @param string $amount * * @return BudgetLimit|null */ public function updateLimitAmount(Budget $budget, Carbon $start, Carbon $end, string $amount): ?BudgetLimit; - } diff --git a/app/Repositories/Budget/BudgetRepository.php b/app/Repositories/Budget/BudgetRepository.php index 705d1ab03c..cef6d344a5 100644 --- a/app/Repositories/Budget/BudgetRepository.php +++ b/app/Repositories/Budget/BudgetRepository.php @@ -1,4 +1,5 @@ delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + Log::debug(sprintf('Now in budgetedInPeriod("%s", "%s")', $start->format('Y-m-d'), $end->format('Y-m-d'))); + $return = []; + /** @var BudgetLimitRepository $limitRepository */ + $limitRepository = app(BudgetLimitRepository::class); + $limitRepository->setUser($this->user); $budgets = $this->getActiveBudgets(); - /** - * @var int $index - * @var Budget $budget - */ - foreach ($budgets as $index => $budget) { - $budget->order = $index + 1; - $budget->save(); + /** @var Budget $budget */ + foreach ($budgets as $budget) { + Log::debug(sprintf('Budget #%d: "%s"', $budget->id, $budget->name)); + $limits = $limitRepository->getBudgetLimits($budget, $start, $end); + /** @var BudgetLimit $limit */ + foreach ($limits as $limit) { + Log::debug(sprintf('Budget limit #%d', $limit->id)); + $currency = $limit->transactionCurrency; + $return[$currency->id] = $return[$currency->id] ?? [ + 'id' => (string)$currency->id, + 'name' => $currency->name, + 'symbol' => $currency->symbol, + 'code' => $currency->code, + 'decimal_places' => $currency->decimal_places, + 'sum' => '0', + ]; + // same period + if ($limit->start_date->isSameDay($start) && $limit->end_date->isSameDay($end)) { + $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], (string)$limit->amount); + Log::debug(sprintf('Add full amount [1]: %s', $limit->amount)); + continue; + } + // limit is inside of date range + if ($start->lte($limit->start_date) && $end->gte($limit->end_date)) { + $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], (string)$limit->amount); + Log::debug(sprintf('Add full amount [2]: %s', $limit->amount)); + continue; + } + $total = $limit->start_date->diffInDays($limit->end_date) + 1; // include the day itself. + $days = $this->daysInOverlap($limit, $start, $end); + $amount = bcmul(bcdiv((string)$limit->amount, (string)$total), (string)$days); + $return[$currency->id]['sum'] = bcadd($return[$currency->id]['sum'], $amount); + Log::debug( + sprintf( + 'Amount per day: %s (%s over %d days). Total amount for %d days: %s', + bcdiv((string)$limit->amount, (string)$total), + $limit->amount, + $total, + $days, + $amount + ) + ); + } } - // other budgets, set to 0. - $this->user->budgets()->where('active', 0)->update(['order' => 0]); + return $return; + } - return true; + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; } /** @@ -118,7 +164,249 @@ class BudgetRepository implements BudgetRepositoryInterface } /** - * @param Budget $budget + * How many days of this budget limit are between start and end? + * + * @param BudgetLimit $limit + * @param Carbon $start + * @param Carbon $end + * @return int + */ + private function daysInOverlap(BudgetLimit $limit, Carbon $start, Carbon $end): int + { + // start1 = $start + // start2 = $limit->start_date + // start1 = $end + // start2 = $limit->end_date + + // limit is larger than start and end (inclusive) + // |-----------| + // |----------------| + if ($start->gte($limit->start_date) && $end->lte($limit->end_date)) { + return $start->diffInDays($end) + 1; // add one day + } + // limit starts earlier and limit ends first: + // |-----------| + // |-------| + if ($limit->start_date->lte($start) && $limit->end_date->lte($end)) { + // return days in the range $start-$limit_end + return $start->diffInDays($limit->end_date) + 1; // add one day, the day itself + } + // limit starts later and limit ends earlier + // |-----------| + // |-------| + if ($limit->start_date->gte($start) && $limit->end_date->gte($end)) { + // return days in the range $limit_start - $end + return $limit->start_date->diffInDays($end) + 1; // add one day, the day itself + } + return 0; + } + + /** + * @return bool + */ + public function cleanupBudgets(): bool + { + // delete limits with amount 0: + BudgetLimit::where('amount', 0)->delete(); + $budgets = $this->getActiveBudgets(); + /** + * @var int $index + * @var Budget $budget + */ + foreach ($budgets as $index => $budget) { + $budget->order = $index + 1; + $budget->save(); + } + // other budgets, set to 0. + $this->user->budgets()->where('active', 0)->update(['order' => 0]); + + return true; + } + + /** + * @param Budget $budget + * @param array $data + * + * @return Budget + */ + public function update(Budget $budget, array $data): Budget + { + Log::debug('Now in update()'); + + $oldName = $budget->name; + if (array_key_exists('name', $data)) { + $budget->name = $data['name']; + $this->updateRuleActions($oldName, $budget->name); + $this->updateRuleTriggers($oldName, $budget->name); + } + if (array_key_exists('active', $data)) { + $budget->active = $data['active']; + } + if (array_key_exists('notes', $data)) { + $this->setNoteText($budget, (string)$data['notes']); + } + $budget->save(); + + // update or create auto-budget: + $autoBudget = $this->getAutoBudget($budget); + + // first things first: delete when no longer required: + $autoBudgetType = array_key_exists('auto_budget_type', $data) ? $data['auto_budget_type'] : null; + + if (0 === $autoBudgetType && null !== $autoBudget) { + // delete! + $autoBudget->delete(); + + return $budget; + } + if (0 === $autoBudgetType && null === $autoBudget) { + return $budget; + } + if (null === $autoBudgetType && null === $autoBudget) { + return $budget; + } + $this->updateAutoBudget($budget, $data); + + return $budget; + } + + /** + * @param string $oldName + * @param string $newName + */ + private function updateRuleActions(string $oldName, string $newName): void + { + $types = ['set_budget',]; + $actions = RuleAction::leftJoin('rules', 'rules.id', '=', 'rule_actions.rule_id') + ->where('rules.user_id', $this->user->id) + ->whereIn('rule_actions.action_type', $types) + ->where('rule_actions.action_value', $oldName) + ->get(['rule_actions.*']); + Log::debug(sprintf('Found %d actions to update.', $actions->count())); + /** @var RuleAction $action */ + foreach ($actions as $action) { + $action->action_value = $newName; + $action->save(); + Log::debug(sprintf('Updated action %d: %s', $action->id, $action->action_value)); + } + } + + /** + * @param string $oldName + * @param string $newName + */ + private function updateRuleTriggers(string $oldName, string $newName): void + { + $types = ['budget_is',]; + $triggers = RuleTrigger::leftJoin('rules', 'rules.id', '=', 'rule_triggers.rule_id') + ->where('rules.user_id', $this->user->id) + ->whereIn('rule_triggers.trigger_type', $types) + ->where('rule_triggers.trigger_value', $oldName) + ->get(['rule_triggers.*']); + Log::debug(sprintf('Found %d triggers to update.', $triggers->count())); + /** @var RuleTrigger $trigger */ + foreach ($triggers as $trigger) { + $trigger->trigger_value = $newName; + $trigger->save(); + Log::debug(sprintf('Updated trigger %d: %s', $trigger->id, $trigger->trigger_value)); + } + } + + /** + * @param Budget $budget + * @param string $text + * @return void + */ + private function setNoteText(Budget $budget, string $text): void + { + $dbNote = $budget->notes()->first(); + if ('' !== $text) { + if (null === $dbNote) { + $dbNote = new Note(); + $dbNote->noteable()->associate($budget); + } + $dbNote->text = trim($text); + $dbNote->save(); + + return; + } + if (null !== $dbNote) { + $dbNote->delete(); + } + } + + /** + * @inheritDoc + */ + public function getAutoBudget(Budget $budget): ?AutoBudget + { + return $budget->autoBudgets()->first(); + } + + /** + * @param Budget $budget + * @param array $data + * @throws FireflyException + * @throws JsonException + */ + private function updateAutoBudget(Budget $budget, array $data): void + { + // update or create auto-budget: + $autoBudget = $this->getAutoBudget($budget); + + // grab default currency: + $currency = app('amount')->getDefaultCurrencyByUser($this->user); + + if (null === $autoBudget) { + // at this point it's a blind assumption auto_budget_type is 1 or 2. + $autoBudget = new AutoBudget(); + $autoBudget->auto_budget_type = $data['auto_budget_type']; + $autoBudget->budget_id = $budget->id; + $autoBudget->transaction_currency_id = $currency->id; + } + + // set or update the currency. + if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { + $repos = app(CurrencyRepositoryInterface::class); + $currencyId = (int)($data['currency_id'] ?? 0); + $currencyCode = (string)($data['currency_code'] ?? ''); + $currency = $repos->find($currencyId); + if (null === $currency) { + $currency = $repos->findByCodeNull($currencyCode); + } + if (null !== $currency) { + $autoBudget->transaction_currency_id = $currency->id; + } + } + + // change values if submitted or presented: + if (array_key_exists('auto_budget_type', $data)) { + $autoBudget->auto_budget_type = $data['auto_budget_type']; + } + if (array_key_exists('auto_budget_amount', $data)) { + $autoBudget->amount = $data['auto_budget_amount']; + } + if (array_key_exists('auto_budget_period', $data)) { + $autoBudget->period = $data['auto_budget_period']; + } + + $autoBudget->save(); + } + + /** + * Find a budget or return NULL + * + * @param int|null $budgetId |null + * + * @return Budget|null + */ + public function find(int $budgetId = null): ?Budget + { + return $this->user->budgets()->find($budgetId); + } + + /** + * @param Budget $budget * * @return bool */ @@ -139,10 +427,10 @@ class BudgetRepository implements BudgetRepositoryInterface $budgets = $this->getBudgets(); /** @var Budget $budget */ foreach ($budgets as $budget) { - DB::table('budget_transaction')->where('budget_id', (int) $budget->id)->delete(); - DB::table('budget_transaction_journal')->where('budget_id', (int) $budget->id)->delete(); - RecurrenceTransactionMeta::where('name', 'budget_id')->where('value', (string) $budget->id)->delete(); - RuleAction::where('action_type', 'set_budget')->where('action_value', (string) $budget->id)->delete(); + DB::table('budget_transaction')->where('budget_id', (int)$budget->id)->delete(); + DB::table('budget_transaction_journal')->where('budget_id', (int)$budget->id)->delete(); + RecurrenceTransactionMeta::where('name', 'budget_id')->where('value', (string)$budget->id)->delete(); + RuleAction::where('action_type', 'set_budget')->where('action_value', (string)$budget->id)->delete(); $budget->delete(); } } @@ -168,8 +456,8 @@ class BudgetRepository implements BudgetRepositoryInterface } /** - * @param int|null $budgetId - * @param string|null $budgetName + * @param int|null $budgetId + * @param string|null $budgetName * * @return Budget|null */ @@ -177,10 +465,10 @@ class BudgetRepository implements BudgetRepositoryInterface { Log::debug('Now in findBudget()'); Log::debug(sprintf('Searching for budget with ID #%d...', $budgetId)); - $result = $this->find((int) $budgetId); + $result = $this->find((int)$budgetId); if (null === $result && null !== $budgetName && '' !== $budgetName) { Log::debug(sprintf('Searching for budget with name %s...', $budgetName)); - $result = $this->findByName((string) $budgetName); + $result = $this->findByName((string)$budgetName); } if (null !== $result) { Log::debug(sprintf('Found budget #%d: %s', $result->id, $result->name)); @@ -190,22 +478,10 @@ class BudgetRepository implements BudgetRepositoryInterface return $result; } - /** - * Find a budget or return NULL - * - * @param int|null $budgetId |null - * - * @return Budget|null - */ - public function find(int $budgetId = null): ?Budget - { - return $this->user->budgets()->find($budgetId); - } - /** * Find budget by name. * - * @param string|null $name + * @param string|null $name * * @return Budget|null */ @@ -223,7 +499,7 @@ class BudgetRepository implements BudgetRepositoryInterface * This method returns the oldest journal or transaction date known to this budget. * Will cache result. * - * @param Budget $budget + * @param Budget $budget * * @return Carbon|null */ @@ -261,7 +537,7 @@ class BudgetRepository implements BudgetRepositoryInterface /** * Get all budgets with these ID's. * - * @param array $budgetIds + * @param array $budgetIds * * @return Collection */ @@ -294,14 +570,13 @@ class BudgetRepository implements BudgetRepositoryInterface } /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ public function searchBudget(string $query, int $limit): Collection { - $search = $this->user->budgets(); if ('' !== $query) { $search->where('name', 'LIKE', sprintf('%%%s%%', $query)); @@ -313,8 +588,8 @@ class BudgetRepository implements BudgetRepositoryInterface } /** - * @param Budget $budget - * @param int $order + * @param Budget $budget + * @param int $order */ public function setBudgetOrder(Budget $budget, int $order): void { @@ -323,19 +598,74 @@ class BudgetRepository implements BudgetRepositoryInterface } /** - * @param User $user + * @inheritDoc */ - public function setUser(User $user): void + public function spentInPeriod(Carbon $start, Carbon $end): array { - $this->user = $user; + Log::debug(sprintf('Now in %s', __METHOD__)); + $start->startOfDay(); + $end->endOfDay(); + + // exclude specific liabilities + $repository = app(AccountRepositoryInterface::class); + $repository->setUser($this->user); + $subset = $repository->getAccountsByType(config('firefly.valid_liabilities')); + $selection = new Collection(); + /** @var Account $account */ + foreach ($subset as $account) { + if ('credit' === $repository->getMetaValue($account, 'liability_direction')) { + $selection->push($account); + } + } + + // start collecting: + /** @var GroupCollectorInterface $collector */ + $collector = app(GroupCollectorInterface::class); + $collector->setUser($this->user) + ->setRange($start, $end) + ->excludeDestinationAccounts($selection) + ->setTypes([TransactionType::WITHDRAWAL]) + ->setBudgets($this->getActiveBudgets()); + + $journals = $collector->getExtractedJournals(); + $array = []; + + foreach ($journals as $journal) { + $currencyId = (int)$journal['currency_id']; + $array[$currencyId] = $array[$currencyId] ?? [ + 'id' => (string)$currencyId, + 'name' => $journal['currency_name'], + 'symbol' => $journal['currency_symbol'], + 'code' => $journal['currency_code'], + 'decimal_places' => $journal['currency_decimal_places'], + 'sum' => '0', + ]; + $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'])); + + // also do foreign amount: + $foreignId = (int)$journal['foreign_currency_id']; + if (0 !== $foreignId) { + $array[$foreignId] = $array[$foreignId] ?? [ + 'id' => (string)$foreignId, + 'name' => $journal['foreign_currency_name'], + 'symbol' => $journal['foreign_currency_symbol'], + 'code' => $journal['foreign_currency_code'], + 'decimal_places' => $journal['foreign_currency_decimal_places'], + 'sum' => '0', + ]; + $array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->negative($journal['foreign_amount'])); + } + } + + return $array; } /** - * @param array $data + * @param array $data * * @return Budget * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ public function store(array $data): Budget { @@ -357,7 +687,7 @@ class BudgetRepository implements BudgetRepositoryInterface // set notes if (array_key_exists('notes', $data)) { - $this->setNoteText($newBudget, (string) $data['notes']); + $this->setNoteText($newBudget, (string)$data['notes']); } if (!array_key_exists('auto_budget_type', $data) || !array_key_exists('auto_budget_amount', $data) || !array_key_exists('auto_budget_period', $data)) { @@ -381,16 +711,16 @@ class BudgetRepository implements BudgetRepositoryInterface $repos = app(CurrencyRepositoryInterface::class); $currency = null; if (array_key_exists('currency_id', $data)) { - $currency = $repos->find((int) $data['currency_id']); + $currency = $repos->find((int)$data['currency_id']); } if (array_key_exists('currency_code', $data)) { - $currency = $repos->findByCode((string) $data['currency_code']); + $currency = $repos->findByCode((string)$data['currency_code']); } if (null === $currency) { $currency = app('amount')->getDefaultCurrencyByUser($this->user); } - $autoBudget = new AutoBudget; + $autoBudget = new AutoBudget(); $autoBudget->budget()->associate($newBudget); $autoBudget->transaction_currency_id = $currency->id; $autoBudget->auto_budget_type = $type; @@ -420,181 +750,6 @@ class BudgetRepository implements BudgetRepositoryInterface public function getMaxOrder(): int { - return (int) $this->user->budgets()->max('order'); - } - - /** - * @param Budget $budget - * @param string $text - * @return void - */ - private function setNoteText(Budget $budget, string $text): void - { - $dbNote = $budget->notes()->first(); - if ('' !== $text) { - if (null === $dbNote) { - $dbNote = new Note; - $dbNote->noteable()->associate($budget); - } - $dbNote->text = trim($text); - $dbNote->save(); - - return; - } - if (null !== $dbNote) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - } - } - - /** - * @param Budget $budget - * @param array $data - * - * @return Budget - */ - public function update(Budget $budget, array $data): Budget - { - Log::debug('Now in update()'); - - $oldName = $budget->name; - if (array_key_exists('name', $data)) { - $budget->name = $data['name']; - $this->updateRuleActions($oldName, $budget->name); - $this->updateRuleTriggers($oldName, $budget->name); - } - if (array_key_exists('active', $data)) { - $budget->active = $data['active']; - } - if (array_key_exists('notes', $data)) { - $this->setNoteText($budget, (string) $data['notes']); - } - $budget->save(); - - // update or create auto-budget: - $autoBudget = $this->getAutoBudget($budget); - - // first things first: delete when no longer required: - $autoBudgetType = array_key_exists('auto_budget_type', $data) ? $data['auto_budget_type'] : null; - - if (0 === $autoBudgetType && null !== $autoBudget) { - // delete! - $autoBudget->delete(); - - return $budget; - } - if (0 === $autoBudgetType && null === $autoBudget) { - return $budget; - } - if (null === $autoBudgetType && null === $autoBudget) { - return $budget; - } - $this->updateAutoBudget($budget, $data); - - return $budget; - } - - /** - * @param string $oldName - * @param string $newName - */ - private function updateRuleActions(string $oldName, string $newName): void - { - $types = ['set_budget',]; - $actions = RuleAction::leftJoin('rules', 'rules.id', '=', 'rule_actions.rule_id') - ->where('rules.user_id', $this->user->id) - ->whereIn('rule_actions.action_type', $types) - ->where('rule_actions.action_value', $oldName) - ->get(['rule_actions.*']); - Log::debug(sprintf('Found %d actions to update.', $actions->count())); - /** @var RuleAction $action */ - foreach ($actions as $action) { - $action->action_value = $newName; - $action->save(); - Log::debug(sprintf('Updated action %d: %s', $action->id, $action->action_value)); - } - } - - /** - * @param string $oldName - * @param string $newName - */ - private function updateRuleTriggers(string $oldName, string $newName): void - { - $types = ['budget_is',]; - $triggers = RuleTrigger::leftJoin('rules', 'rules.id', '=', 'rule_triggers.rule_id') - ->where('rules.user_id', $this->user->id) - ->whereIn('rule_triggers.trigger_type', $types) - ->where('rule_triggers.trigger_value', $oldName) - ->get(['rule_triggers.*']); - Log::debug(sprintf('Found %d triggers to update.', $triggers->count())); - /** @var RuleTrigger $trigger */ - foreach ($triggers as $trigger) { - $trigger->trigger_value = $newName; - $trigger->save(); - Log::debug(sprintf('Updated trigger %d: %s', $trigger->id, $trigger->trigger_value)); - } - } - - /** - * @inheritDoc - */ - public function getAutoBudget(Budget $budget): ?AutoBudget - { - return $budget->autoBudgets()->first(); - } - - /** - * @param Budget $budget - * @param array $data - * @throws FireflyException - * @throws \JsonException - */ - private function updateAutoBudget(Budget $budget, array $data): void - { - // update or create auto-budget: - $autoBudget = $this->getAutoBudget($budget); - - // grab default currency: - $currency = app('amount')->getDefaultCurrencyByUser($this->user); - - if (null === $autoBudget) { - // at this point it's a blind assumption auto_budget_type is 1 or 2. - $autoBudget = new AutoBudget; - $autoBudget->auto_budget_type = $data['auto_budget_type']; - $autoBudget->budget_id = $budget->id; - $autoBudget->transaction_currency_id = $currency->id; - } - - // set or update the currency. - if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { - $repos = app(CurrencyRepositoryInterface::class); - $currencyId = (int) ($data['currency_id'] ?? 0); - $currencyCode = (string) ($data['currency_code'] ?? ''); - $currency = $repos->find($currencyId); - if (null === $currency) { - $currency = $repos->findByCodeNull($currencyCode); - } - if (null !== $currency) { - $autoBudget->transaction_currency_id = $currency->id; - } - } - - // change values if submitted or presented: - if (array_key_exists('auto_budget_type', $data)) { - $autoBudget->auto_budget_type = $data['auto_budget_type']; - } - if (array_key_exists('auto_budget_amount', $data)) { - $autoBudget->amount = $data['auto_budget_amount']; - - } - if (array_key_exists('auto_budget_period', $data)) { - $autoBudget->period = $data['auto_budget_period']; - } - - $autoBudget->save(); + return (int)$this->user->budgets()->max('order'); } } diff --git a/app/Repositories/Budget/BudgetRepositoryInterface.php b/app/Repositories/Budget/BudgetRepositoryInterface.php index d06d560530..9441b3b76a 100644 --- a/app/Repositories/Budget/BudgetRepositoryInterface.php +++ b/app/Repositories/Budget/BudgetRepositoryInterface.php @@ -1,4 +1,5 @@ 0, - 'name' => sprintf('%s (%s)', trans('firefly.no_budget'), $journal['currency_name']), - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_code' => $journal['currency_code'], - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - 'entries' => [], - ]; + 'id' => 0, + 'name' => sprintf('%s (%s)', trans('firefly.no_budget'), $journal['currency_name']), + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_code' => $journal['currency_code'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + 'entries' => [], + ]; $date = $journal['date']->format($carbonFormat); if (!array_key_exists($date, $data[$currencyId]['entries'])) { @@ -86,17 +86,9 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface } /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return array * @deprecated @@ -133,7 +125,7 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface /** @var TransactionCurrency $currency */ $currency = $currencies[$code]; $return[] = [ - 'currency_id' => (string) $currency['id'], + 'currency_id' => (string)$currency['id'], 'currency_code' => $code, 'currency_name' => $currency['name'], 'currency_symbol' => $currency['symbol'], @@ -145,21 +137,27 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface return $return; } - /** @noinspection MoreThanThreeArgumentsInspection */ /** - * See reference nr. 15 - * See reference nr. 16 + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * TODO this method does not include multi currency. It just counts. + * TODO this probably also applies to the other "sumExpenses" methods. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param TransactionCurrency|null $currency * * @return array */ public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array { - /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); $collector->setUser($this->user)->setRange($start, $end)->setTypes([TransactionType::WITHDRAWAL]); @@ -176,17 +174,16 @@ class NoBudgetRepository implements NoBudgetRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'])); - } return $array; diff --git a/app/Repositories/Budget/NoBudgetRepositoryInterface.php b/app/Repositories/Budget/NoBudgetRepositoryInterface.php index 0f6da40270..f431b59522 100644 --- a/app/Repositories/Budget/NoBudgetRepositoryInterface.php +++ b/app/Repositories/Budget/NoBudgetRepositoryInterface.php @@ -34,9 +34,9 @@ use Illuminate\Support\Collection; interface NoBudgetRepositoryInterface { /** - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return array * @deprecated @@ -44,29 +44,27 @@ interface NoBudgetRepositoryInterface public function getNoBudgetPeriodReport(Collection $accounts, Carbon $start, Carbon $end): array; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return array * @deprecated */ public function spentInPeriodWoBudgetMc(Collection $accounts, Carbon $start, Carbon $end): array; - /** @noinspection MoreThanThreeArgumentsInspection */ /** - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param TransactionCurrency|null $currency + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param TransactionCurrency|null $currency * * @return array */ public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?TransactionCurrency $currency = null): array; - } diff --git a/app/Repositories/Budget/OperationsRepository.php b/app/Repositories/Budget/OperationsRepository.php index 6e80d50305..4f983d051e 100644 --- a/app/Repositories/Budget/OperationsRepository.php +++ b/app/Repositories/Budget/OperationsRepository.php @@ -46,7 +46,7 @@ class OperationsRepository implements OperationsRepositoryInterface * A method that returns the amount of money budgeted per day for this budget, * on average. * - * @param Budget $budget + * @param Budget $budget * * @return string */ @@ -58,15 +58,15 @@ class OperationsRepository implements OperationsRepositoryInterface foreach ($budget->budgetlimits as $limit) { $diff = $limit->start_date->diffInDays($limit->end_date); $diff = 0 === $diff ? 1 : $diff; - $amount = (string) $limit->amount; - $perDay = bcdiv($amount, (string) $diff); + $amount = (string)$limit->amount; + $perDay = bcdiv($amount, (string)$diff); $total = bcadd($total, $perDay); $count++; Log::debug(sprintf('Found %d budget limits. Per day is %s, total is %s', $count, $perDay, $total)); } $avg = $total; if ($count > 0) { - $avg = bcdiv($total, (string) $count); + $avg = bcdiv($total, (string)$count); } Log::debug(sprintf('%s / %d = %s = average.', $total, $count, $avg)); @@ -77,10 +77,10 @@ class OperationsRepository implements OperationsRepositoryInterface * This method is being used to generate the budget overview in the year/multi-year report. Its used * in both the year/multi-year budget overview AND in the accompanying chart. * - * @param Collection $budgets - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $budgets + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return array * @deprecated @@ -100,24 +100,24 @@ class OperationsRepository implements OperationsRepositoryInterface /** @var array $journal */ foreach ($journals as $journal) { // prep data array for currency: - $budgetId = (int) $journal['budget_id']; + $budgetId = (int)$journal['budget_id']; $budgetName = $journal['budget_name']; - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $key = sprintf('%d-%d', $budgetId, $currencyId); $data[$key] = $data[$key] ?? [ - 'id' => $budgetId, - 'name' => sprintf('%s (%s)', $budgetName, $journal['currency_name']), - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_code' => $journal['currency_code'], - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - 'entries' => [], - ]; + 'id' => $budgetId, + 'name' => sprintf('%s (%s)', $budgetName, $journal['currency_name']), + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_code' => $journal['currency_code'], + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + 'entries' => [], + ]; $date = $journal['date']->format($carbonFormat); - $data[$key]['entries'][$date] = bcadd($data[$budgetId]['entries'][$date] ?? '0', $journal['amount']); + $data[$key]['entries'][$date] = bcadd($data[$key]['entries'][$date] ?? '0', $journal['amount']); } return $data; @@ -128,10 +128,10 @@ class OperationsRepository implements OperationsRepositoryInterface * which have the specified budget set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $budgets + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $budgets * * @return array */ @@ -154,9 +154,9 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $budgetId = (int) $journal['budget_id']; - $budgetName = (string) $journal['budget_name']; + $currencyId = (int)$journal['currency_id']; + $budgetId = (int)$journal['budget_id']; + $budgetName = (string)$journal['budget_name']; // catch "no category" entries. if (0 === $budgetId) { @@ -165,24 +165,24 @@ class OperationsRepository implements OperationsRepositoryInterface // info about the currency: $array[$currencyId] = $array[$currencyId] ?? [ - 'budgets' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'budgets' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // info about the categories: $array[$currencyId]['budgets'][$budgetId] = $array[$currencyId]['budgets'][$budgetId] ?? [ - 'id' => $budgetId, - 'name' => $budgetName, - 'transaction_journals' => [], - ]; + 'id' => $budgetId, + 'name' => $budgetName, + 'transaction_journals' => [], + ]; // add journal to array: // only a subset of the fields. - $journalId = (int) $journal['transaction_journal_id']; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId]['budgets'][$budgetId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->negative($journal['amount']), 'destination_account_id' => $journal['destination_account_id'], @@ -194,12 +194,19 @@ class OperationsRepository implements OperationsRepositoryInterface 'transaction_group_id' => $journal['transaction_group_id'], 'date' => $journal['date'], ]; - } return $array; } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + /** * @return Collection */ @@ -211,21 +218,11 @@ class OperationsRepository implements OperationsRepositoryInterface return $repos->getActiveBudgets(); } - /** @noinspection MoreThanThreeArgumentsInspection */ - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param Collection $budgets - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $budgets + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return array * @deprecated @@ -240,7 +237,7 @@ class OperationsRepository implements OperationsRepositoryInterface if ($accounts->count() > 0) { $collector->setAccounts($accounts); } - // See reference nr. 13 + // TODO possible candidate for "get extracted groups" method. $set = $collector->getGroups(); $return = []; $total = []; @@ -270,7 +267,7 @@ class OperationsRepository implements OperationsRepositoryInterface /** @var TransactionCurrency $currency */ $currency = $currencies[$code]; $return[] = [ - 'currency_id' => (string) $currency['id'], + 'currency_id' => (string)$currency['id'], 'currency_code' => $code, 'currency_name' => $currency['name'], 'currency_symbol' => $currency['symbol'], @@ -283,17 +280,21 @@ class OperationsRepository implements OperationsRepositoryInterface } /** - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $budgets - * @param TransactionCurrency|null $currency - * + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $budgets + * @param TransactionCurrency|null $currency * @return array + * @deprecated */ - public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null - ): array - { + public function sumExpenses( + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $budgets = null, + ?TransactionCurrency $currency = null + ): array { Log::debug(sprintf('Now in %s', __METHOD__)); $start->startOfDay(); $end->endOfDay(); @@ -306,7 +307,7 @@ class OperationsRepository implements OperationsRepositoryInterface $repository = app(AccountRepositoryInterface::class); $repository->setUser($this->user); $subset = $repository->getAccountsByType(config('firefly.valid_liabilities')); - $selection = new Collection; + $selection = new Collection(); /** @var Account $account */ foreach ($subset as $account) { if ('credit' === $repository->getMetaValue($account, 'liability_direction')) { @@ -353,28 +354,28 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'])); // also do foreign amount: - $foreignId = (int) $journal['foreign_currency_id']; + $foreignId = (int)$journal['foreign_currency_id']; if (0 !== $foreignId) { $array[$foreignId] = $array[$foreignId] ?? [ - 'sum' => '0', - 'currency_id' => $foreignId, - 'currency_name' => $journal['foreign_currency_name'], - 'currency_symbol' => $journal['foreign_currency_symbol'], - 'currency_code' => $journal['foreign_currency_code'], - 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $foreignId, + 'currency_name' => $journal['foreign_currency_name'], + 'currency_symbol' => $journal['foreign_currency_symbol'], + 'currency_code' => $journal['foreign_currency_code'], + 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], + ]; $array[$foreignId]['sum'] = bcadd($array[$foreignId]['sum'], app('steam')->negative($journal['foreign_amount'])); } } @@ -384,11 +385,11 @@ class OperationsRepository implements OperationsRepositoryInterface /** * For now, simply refer to whichever repository holds this function. - * See reference nr. 14 + * TODO perhaps better in the future. * - * @param Budget $budget - * @param Carbon|null $start - * @param Carbon|null $end + * @param Budget $budget + * @param Carbon|null $start + * @param Carbon|null $end * * @return Collection */ diff --git a/app/Repositories/Budget/OperationsRepositoryInterface.php b/app/Repositories/Budget/OperationsRepositoryInterface.php index 691ff64805..6ff33a97c3 100644 --- a/app/Repositories/Budget/OperationsRepositoryInterface.php +++ b/app/Repositories/Budget/OperationsRepositoryInterface.php @@ -38,17 +38,17 @@ interface OperationsRepositoryInterface * A method that returns the amount of money budgeted per day for this budget, * on average. * - * @param Budget $budget + * @param Budget $budget * * @return string */ public function budgetedPerDay(Budget $budget): string; /** - * @param Collection $budgets - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $budgets + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return array * @deprecated @@ -60,29 +60,28 @@ interface OperationsRepositoryInterface * which have the specified budget set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $budgets + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $budgets * * @return array */ public function listExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null): array; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; - /** @noinspection MoreThanThreeArgumentsInspection */ /** * Return multi-currency spent information. * - * @param Collection $budgets - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $budgets + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return array * @deprecated @@ -90,15 +89,21 @@ interface OperationsRepositoryInterface public function spentInPeriodMc(Collection $budgets, Collection $accounts, Carbon $start, Carbon $end): array; /** - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $budgets - * @param TransactionCurrency|null $currency + * TODO this method was marked as deprecated but I'm not sure why. + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $budgets + * @param TransactionCurrency|null $currency * * @return array + * */ - public function sumExpenses(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $budgets = null, ?TransactionCurrency $currency = null + public function sumExpenses( + Carbon $start, + Carbon $end, + ?Collection $accounts = null, + ?Collection $budgets = null, + ?TransactionCurrency $currency = null ): array; - } diff --git a/app/Repositories/Category/CategoryRepository.php b/app/Repositories/Category/CategoryRepository.php index 030bbc63e6..cbfd18453e 100644 --- a/app/Repositories/Category/CategoryRepository.php +++ b/app/Repositories/Category/CategoryRepository.php @@ -1,4 +1,5 @@ find((int) $categoryId); + $result = $this->find((int)$categoryId); if (null === $result) { Log::debug(sprintf('Searching for category with name %s...', $categoryName)); - $result = $this->findByName((string) $categoryName); - if (null === $result && '' !== (string) $categoryName) { + $result = $this->findByName((string)$categoryName); + if (null === $result && '' !== (string)$categoryName) { // create it! $result = $this->store(['name' => $categoryName]); } @@ -145,7 +146,7 @@ class CategoryRepository implements CategoryRepositoryInterface /** * Find a category or return NULL * - * @param int $categoryId + * @param int $categoryId * * @return Category|null */ @@ -157,7 +158,7 @@ class CategoryRepository implements CategoryRepositoryInterface /** * Find a category. * - * @param string $name + * @param string $name * * @return Category|null */ @@ -167,7 +168,7 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param array $data + * @param array $data * * @return Category * @throws FireflyException @@ -192,11 +193,18 @@ class CategoryRepository implements CategoryRepositoryInterface } return $category; - } /** - * @param Category $category + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @param Category $category */ public function removeNotes(Category $category): void { @@ -210,7 +218,7 @@ class CategoryRepository implements CategoryRepositoryInterface { $dbNote = $category->notes()->first(); if (null === $dbNote) { - $dbNote = new Note; + $dbNote = new Note(); $dbNote->noteable()->associate($category); } $dbNote->text = trim($notes); @@ -218,7 +226,7 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param Category $category + * @param Category $category * * @return Carbon|null * @@ -246,7 +254,7 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param Category $category + * @param Category $category * * @return Carbon|null */ @@ -263,7 +271,7 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param Category $category + * @param Category $category * * @return Carbon|null */ @@ -306,7 +314,7 @@ class CategoryRepository implements CategoryRepositoryInterface /** * Get all categories with ID's. * - * @param array $categoryIds + * @param array $categoryIds * * @return Collection */ @@ -329,8 +337,8 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param Category $category - * @param Collection $accounts + * @param Category $category + * @param Collection $accounts * * @return Carbon|null * @throws Exception @@ -358,8 +366,8 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param Category $category - * @param Collection $accounts + * @param Category $category + * @param Collection $accounts * * @return Carbon|null */ @@ -382,8 +390,8 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param Category $category - * @param Collection $accounts + * @param Category $category + * @param Collection $accounts * * @return Carbon|null * @throws Exception @@ -408,8 +416,8 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ @@ -424,16 +432,8 @@ class CategoryRepository implements CategoryRepositoryInterface } /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param Category $category - * @param array $data + * @param Category $category + * @param array $data * * @return Category * @throws Exception diff --git a/app/Repositories/Category/CategoryRepositoryInterface.php b/app/Repositories/Category/CategoryRepositoryInterface.php index d26dd08bf3..b660fe9332 100644 --- a/app/Repositories/Category/CategoryRepositoryInterface.php +++ b/app/Repositories/Category/CategoryRepositoryInterface.php @@ -1,4 +1,5 @@ [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'categories' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // info about the non-existent category: $array[$currencyId]['categories'][0] = $array[$currencyId]['categories'][0] ?? [ - 'id' => 0, - 'name' => (string) trans('firefly.noCategory'), - 'transaction_journals' => [], - ]; + 'id' => 0, + 'name' => (string)trans('firefly.noCategory'), + 'transaction_journals' => [], + ]; // add journal to array: // only a subset of the fields. - $journalId = (int) $journal['transaction_journal_id']; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId]['categories'][0]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->negative($journal['amount']), 'date' => $journal['date'], ]; - } return $array; } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + /** * This method returns a list of all the deposit transaction journals (as arrays) set in that period * which have no category set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ @@ -113,50 +120,41 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'categories' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'categories' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // info about the non-existent category: $array[$currencyId]['categories'][0] = $array[$currencyId]['categories'][0] ?? [ - 'id' => 0, - 'name' => (string) trans('firefly.noCategory'), - 'transaction_journals' => [], - ]; + 'id' => 0, + 'name' => (string)trans('firefly.noCategory'), + 'transaction_journals' => [], + ]; // add journal to array: // only a subset of the fields. - $journalId = (int) $journal['transaction_journal_id']; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId]['categories'][0]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->positive($journal['amount']), 'date' => $journal['date'], ]; - } return $array; } - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - /** * Sum of withdrawal journals in period without a category, grouped per currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ @@ -173,15 +171,15 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'] ?? '0')); } @@ -191,9 +189,9 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface /** * Sum of income journals in period without a category, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ @@ -210,15 +208,15 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->positive($journal['amount'])); } @@ -241,15 +239,15 @@ class NoCategoryRepository implements NoCategoryRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->positive($journal['amount'])); } diff --git a/app/Repositories/Category/NoCategoryRepositoryInterface.php b/app/Repositories/Category/NoCategoryRepositoryInterface.php index c1835114b5..483f3f505d 100644 --- a/app/Repositories/Category/NoCategoryRepositoryInterface.php +++ b/app/Repositories/Category/NoCategoryRepositoryInterface.php @@ -38,9 +38,9 @@ interface NoCategoryRepositoryInterface * which have no category set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ @@ -51,25 +51,25 @@ interface NoCategoryRepositoryInterface * which have no category set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ public function listIncome(Carbon $start, Carbon $end, ?Collection $accounts = null): array; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** * Sum of withdrawal journals in period without a category, grouped per currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ @@ -78,9 +78,9 @@ interface NoCategoryRepositoryInterface /** * Sum of income journals in period without a category, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ @@ -89,9 +89,9 @@ interface NoCategoryRepositoryInterface /** * Sum of transfers in period without a category, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts * * @return array */ diff --git a/app/Repositories/Category/OperationsRepository.php b/app/Repositories/Category/OperationsRepository.php index 510de53ef9..a2dabc2a7d 100644 --- a/app/Repositories/Category/OperationsRepository.php +++ b/app/Repositories/Category/OperationsRepository.php @@ -44,10 +44,10 @@ class OperationsRepository implements OperationsRepositoryInterface * * First currency, then categories. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -70,9 +70,9 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $categoryId = (int) $journal['category_id']; - $categoryName = (string) $journal['category_name']; + $currencyId = (int)$journal['currency_id']; + $categoryId = (int)$journal['category_id']; + $categoryName = (string)$journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { @@ -81,24 +81,24 @@ class OperationsRepository implements OperationsRepositoryInterface // info about the currency: $array[$currencyId] = $array[$currencyId] ?? [ - 'categories' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'categories' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // info about the categories: $array[$currencyId]['categories'][$categoryId] = $array[$currencyId]['categories'][$categoryId] ?? [ - 'id' => $categoryId, - 'name' => $categoryName, - 'transaction_journals' => [], - ]; + 'id' => $categoryId, + 'name' => $categoryName, + 'transaction_journals' => [], + ]; // add journal to array: // only a subset of the fields. - $journalId = (int) $journal['transaction_journal_id']; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->negative($journal['amount']), 'date' => $journal['date'], @@ -110,12 +110,19 @@ class OperationsRepository implements OperationsRepositoryInterface 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], ]; - } return $array; } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + /** * Returns a list of all the categories belonging to a user. * @@ -131,10 +138,10 @@ class OperationsRepository implements OperationsRepositoryInterface * which have the specified category set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -157,35 +164,35 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $categoryId = (int) $journal['category_id']; - $categoryName = (string) $journal['category_name']; + $currencyId = (int)$journal['currency_id']; + $categoryId = (int)$journal['category_id']; + $categoryName = (string)$journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { - $categoryName = (string) trans('firefly.no_category'); + $categoryName = (string)trans('firefly.no_category'); } // info about the currency: $array[$currencyId] = $array[$currencyId] ?? [ - 'categories' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'categories' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // info about the categories: $array[$currencyId]['categories'][$categoryId] = $array[$currencyId]['categories'][$categoryId] ?? [ - 'id' => $categoryId, - 'name' => $categoryName, - 'transaction_journals' => [], - ]; + 'id' => $categoryId, + 'name' => $categoryName, + 'transaction_journals' => [], + ]; // add journal to array: // only a subset of the fields. - $journalId = (int) $journal['transaction_journal_id']; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->positive($journal['amount']), 'date' => $journal['date'], @@ -196,7 +203,6 @@ class OperationsRepository implements OperationsRepositoryInterface 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], ]; - } return $array; @@ -222,9 +228,9 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $categoryId = (int) $journal['category_id']; - $categoryName = (string) $journal['category_name']; + $currencyId = (int)$journal['currency_id']; + $categoryId = (int)$journal['category_id']; + $categoryName = (string)$journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { @@ -233,24 +239,24 @@ class OperationsRepository implements OperationsRepositoryInterface // info about the currency: $array[$currencyId] = $array[$currencyId] ?? [ - 'categories' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'categories' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // info about the categories: $array[$currencyId]['categories'][$categoryId] = $array[$currencyId]['categories'][$categoryId] ?? [ - 'id' => $categoryId, - 'name' => $categoryName, - 'transaction_journals' => [], - ]; + 'id' => $categoryId, + 'name' => $categoryName, + 'transaction_journals' => [], + ]; // add journal to array: // only a subset of the fields. - $journalId = (int) $journal['transaction_journal_id']; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->positive($journal['amount']), 'date' => $journal['date'], @@ -262,7 +268,6 @@ class OperationsRepository implements OperationsRepositoryInterface 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], ]; - } return $array; @@ -288,9 +293,9 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; - $categoryId = (int) $journal['category_id']; - $categoryName = (string) $journal['category_name']; + $currencyId = (int)$journal['currency_id']; + $categoryId = (int)$journal['category_id']; + $categoryName = (string)$journal['category_name']; // catch "no category" entries. if (0 === $categoryId) { @@ -299,24 +304,24 @@ class OperationsRepository implements OperationsRepositoryInterface // info about the currency: $array[$currencyId] = $array[$currencyId] ?? [ - 'categories' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'categories' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // info about the categories: $array[$currencyId]['categories'][$categoryId] = $array[$currencyId]['categories'][$categoryId] ?? [ - 'id' => $categoryId, - 'name' => $categoryName, - 'transaction_journals' => [], - ]; + 'id' => $categoryId, + 'name' => $categoryName, + 'transaction_journals' => [], + ]; // add journal to array: // only a subset of the fields. - $journalId = (int) $journal['transaction_journal_id']; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId]['categories'][$categoryId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->negative($journal['amount']), 'date' => $journal['date'], @@ -328,27 +333,18 @@ class OperationsRepository implements OperationsRepositoryInterface 'description' => $journal['description'], 'transaction_group_id' => $journal['transaction_group_id'], ]; - } return $array; } - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - /** * Sum of withdrawal journals in period for a set of categories, grouped per currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -371,15 +367,15 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => (int) $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => (int)$journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->negative($journal['amount'])); } @@ -389,10 +385,10 @@ class OperationsRepository implements OperationsRepositoryInterface /** * Sum of income journals in period for a set of categories, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -414,15 +410,15 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->positive($journal['amount'])); } @@ -432,10 +428,10 @@ class OperationsRepository implements OperationsRepositoryInterface /** * Sum of income journals in period for a set of categories, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -457,15 +453,15 @@ class OperationsRepository implements OperationsRepositoryInterface $array = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'sum' => '0', - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'sum' => '0', + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; $array[$currencyId]['sum'] = bcadd($array[$currencyId]['sum'], app('steam')->positive($journal['amount'])); } diff --git a/app/Repositories/Category/OperationsRepositoryInterface.php b/app/Repositories/Category/OperationsRepositoryInterface.php index 0f24e11ad5..1a30eee764 100644 --- a/app/Repositories/Category/OperationsRepositoryInterface.php +++ b/app/Repositories/Category/OperationsRepositoryInterface.php @@ -38,10 +38,10 @@ interface OperationsRepositoryInterface * which have the specified category set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -52,10 +52,10 @@ interface OperationsRepositoryInterface * which have the specified category set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -67,10 +67,10 @@ interface OperationsRepositoryInterface * It excludes any transfers between the listed accounts. * It's grouped per currency, with as few details in the array as possible. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * @param Collection|null $categories * * @return array */ @@ -82,27 +82,27 @@ interface OperationsRepositoryInterface * It excludes any transfers between the listed accounts. * It's grouped per currency, with as few details in the array as possible. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection $accounts + * @param Collection|null $categories * * @return array */ public function listTransferredOut(Carbon $start, Carbon $end, Collection $accounts, ?Collection $categories = null): array; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** * Sum of withdrawal journals in period for a set of categories, grouped per currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -111,10 +111,10 @@ interface OperationsRepositoryInterface /** * Sum of income journals in period for a set of categories, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ @@ -123,10 +123,10 @@ interface OperationsRepositoryInterface /** * Sum of transfers in period for a set of categories, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $categories + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $categories * * @return array */ diff --git a/app/Repositories/Currency/CurrencyRepository.php b/app/Repositories/Currency/CurrencyRepository.php index 4619703cfc..96ff6e83a1 100644 --- a/app/Repositories/Currency/CurrencyRepository.php +++ b/app/Repositories/Currency/CurrencyRepository.php @@ -1,4 +1,5 @@ where('data', json_encode((string) $currency->id))->count(); + $meta = AccountMeta::where('name', 'currency_id')->where('data', json_encode((string)$currency->id))->count(); if ($meta > 0) { Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta)); @@ -112,10 +113,9 @@ class CurrencyRepository implements CurrencyRepositoryInterface } // is being used in accounts (as integer) - $meta = AccountMeta - ::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') - ->whereNull('accounts.deleted_at') - ->where('account_meta.name', 'currency_id')->where('account_meta.data', json_encode((int) $currency->id))->count(); + $meta = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') + ->whereNull('accounts.deleted_at') + ->where('account_meta.name', 'currency_id')->where('account_meta.data', json_encode((int)$currency->id))->count(); if ($meta > 0) { Log::info(sprintf('Used in %d accounts as currency_id, return true. ', $meta)); @@ -152,7 +152,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return int */ @@ -173,7 +173,15 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @param TransactionCurrency $currency + * @return Collection + */ + public function get(): Collection + { + return TransactionCurrency::where('enabled', true)->orderBy('code', 'ASC')->get(); + } + + /** + * @param TransactionCurrency $currency * * @return bool */ @@ -193,7 +201,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** * Disables a currency * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency */ public function disable(TransactionCurrency $currency): void { @@ -220,11 +228,21 @@ class CurrencyRepository implements CurrencyRepositoryInterface } } + /** + * @param TransactionCurrency $currency + * Enables a currency + */ + public function enable(TransactionCurrency $currency): void + { + $currency->enabled = true; + $currency->save(); + } + /** * Find by currency code, return NULL if unfound. * Used in Import Currency! * - * @param string $currencyCode + * @param string $currencyCode * * @return TransactionCurrency|null * @deprecated @@ -237,7 +255,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** * Find by currency name. * - * @param string $currencyName + * @param string $currencyName * * @return TransactionCurrency|null */ @@ -250,7 +268,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface * Find by currency name or return null. * Used in Import Currency! * - * @param string $currencyName + * @param string $currencyName * * @return TransactionCurrency|null * @deprecated @@ -263,7 +281,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** * Find by currency symbol. * - * @param string $currencySymbol + * @param string $currencySymbol * * @return TransactionCurrency|null */ @@ -276,7 +294,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface * Find by currency symbol or return NULL * Used in Import Currency! * - * @param string $currencySymbol + * @param string $currencySymbol * * @return TransactionCurrency|null * @deprecated @@ -289,8 +307,8 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** * Find by object, ID or code. Returns user default or system default. * - * @param int|null $currencyId - * @param string|null $currencyCode + * @param int|null $currencyId + * @param string|null $currencyCode * * @return TransactionCurrency * @throws FireflyException @@ -321,18 +339,18 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** * Find by object, ID or code. Returns NULL if nothing found. * - * @param int|null $currencyId - * @param string|null $currencyCode + * @param int|null $currencyId + * @param string|null $currencyCode * * @return TransactionCurrency|null */ public function findCurrencyNull(?int $currencyId, ?string $currencyCode): ?TransactionCurrency { Log::debug('Now in findCurrencyNull()'); - $result = $this->find((int) $currencyId); + $result = $this->find((int)$currencyId); if (null === $result) { Log::debug(sprintf('Searching for currency with code %s...', $currencyCode)); - $result = $this->findByCode((string) $currencyCode); + $result = $this->findByCode((string)$currencyCode); } if (null !== $result && false === $result->enabled) { Log::debug(sprintf('Also enabled currency %s', $result->code)); @@ -345,7 +363,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** * Find by ID, return NULL if not found. * - * @param int $currencyId + * @param int $currencyId * * @return TransactionCurrency|null */ @@ -357,7 +375,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** * Find by currency code, return NULL if unfound. * - * @param string $currencyCode + * @param string $currencyCode * * @return TransactionCurrency|null */ @@ -367,25 +385,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @param TransactionCurrency $currency - * Enables a currency - */ - public function enable(TransactionCurrency $currency): void - { - $currency->enabled = true; - $currency->save(); - } - - /** - * @return Collection - */ - public function get(): Collection - { - return TransactionCurrency::where('enabled', true)->orderBy('code', 'ASC')->get(); - } - - /** - * @param array $ids + * @param array $ids * * @return Collection */ @@ -395,7 +395,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @param Preference $preference + * @param Preference $preference * * @return TransactionCurrency */ @@ -412,16 +412,16 @@ class CurrencyRepository implements CurrencyRepositoryInterface /** * Get currency exchange rate. * - * @param TransactionCurrency $fromCurrency - * @param TransactionCurrency $toCurrency - * @param Carbon $date + * @param TransactionCurrency $fromCurrency + * @param TransactionCurrency $toCurrency + * @param Carbon $date * * @return CurrencyExchangeRate|null */ public function getExchangeRate(TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date): ?CurrencyExchangeRate { if ($fromCurrency->id === $toCurrency->id) { - $rate = new CurrencyExchangeRate; + $rate = new CurrencyExchangeRate(); $rate->rate = 1; $rate->id = 0; @@ -450,8 +450,8 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @param string $search - * @param int $limit + * @param string $search + * @param int $limit * * @return Collection */ @@ -466,7 +466,28 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @param User $user + * TODO must be a factory + * @param TransactionCurrency $fromCurrency + * @param TransactionCurrency $toCurrency + * @param Carbon $date + * @param float $rate + * @return CurrencyExchangeRate + */ + public function setExchangeRate(TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date, float $rate): CurrencyExchangeRate + { + return CurrencyExchangeRate::create( + [ + 'user_id' => $this->user->id, + 'from_currency_id' => $fromCurrency->id, + 'to_currency_id' => $toCurrency->id, + 'date' => $date, + 'rate' => $rate, + ] + ); + } + + /** + * @param User $user */ public function setUser(User $user): void { @@ -474,7 +495,7 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @param array $data + * @param array $data * * @return TransactionCurrency * @throws FireflyException @@ -493,8 +514,8 @@ class CurrencyRepository implements CurrencyRepositoryInterface } /** - * @param TransactionCurrency $currency - * @param array $data + * @param TransactionCurrency $currency + * @param array $data * * @return TransactionCurrency */ diff --git a/app/Repositories/Currency/CurrencyRepositoryInterface.php b/app/Repositories/Currency/CurrencyRepositoryInterface.php index 35efcb3b76..7c45bf9e27 100644 --- a/app/Repositories/Currency/CurrencyRepositoryInterface.php +++ b/app/Repositories/Currency/CurrencyRepositoryInterface.php @@ -1,4 +1,5 @@ notes()->first(); $attachment->file_exists = $disk->exists($attachment->fileName()); - $attachment->notes = $notes ? $notes->text : ''; + $attachment->notes = $notes ? $notes->text : ''; // TODO should not set notes like this. return $attachment; } @@ -91,7 +93,7 @@ class JournalAPIRepository implements JournalAPIRepositoryInterface /** * Get all piggy bank events for a journal. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Collection */ @@ -108,7 +110,7 @@ class JournalAPIRepository implements JournalAPIRepositoryInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { diff --git a/app/Repositories/Journal/JournalAPIRepositoryInterface.php b/app/Repositories/Journal/JournalAPIRepositoryInterface.php index ad6e372987..16dd484b79 100644 --- a/app/Repositories/Journal/JournalAPIRepositoryInterface.php +++ b/app/Repositories/Journal/JournalAPIRepositoryInterface.php @@ -36,7 +36,7 @@ interface JournalAPIRepositoryInterface /** * Returns transaction by ID. Used to validate attachments. * - * @param int $transactionId + * @param int $transactionId * * @return Transaction|null */ @@ -45,7 +45,7 @@ interface JournalAPIRepositoryInterface /** * Return all attachments for journal. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Collection */ @@ -54,7 +54,7 @@ interface JournalAPIRepositoryInterface /** * Return all journal links for journal. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Collection */ @@ -63,14 +63,14 @@ interface JournalAPIRepositoryInterface /** * Get all piggy bank events for a journal. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Collection */ public function getPiggyBankEvents(TransactionJournal $journal): Collection; /** - * @param User $user + * @param User $user */ public function setUser(User $user); } diff --git a/app/Repositories/Journal/JournalCLIRepository.php b/app/Repositories/Journal/JournalCLIRepository.php index 28aa64bff2..c12473dfb8 100644 --- a/app/Repositories/Journal/JournalCLIRepository.php +++ b/app/Repositories/Journal/JournalCLIRepository.php @@ -25,12 +25,10 @@ namespace FireflyIII\Repositories\Journal; use Carbon\Carbon; use DB; -use Exception; use FireflyIII\Models\TransactionJournal; use FireflyIII\Support\CacheProperties; use FireflyIII\User; use Illuminate\Support\Collection; -use JsonException; use stdClass; /** @@ -44,23 +42,22 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface /** * Get all transaction journals with a specific type, regardless of user. * - * @param array $types + * @param array $types * * @return Collection */ public function getAllJournals(array $types): Collection { - return TransactionJournal - ::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') - ->whereIn('transaction_types.type', $types) - ->with(['user', 'transactionType', 'transactionCurrency', 'transactions', 'transactions.account']) - ->get(['transaction_journals.*']); + return TransactionJournal::leftJoin('transaction_types', 'transaction_types.id', '=', 'transaction_journals.transaction_type_id') + ->whereIn('transaction_types.type', $types) + ->with(['user', 'transactionType', 'transactionCurrency', 'transactions', 'transactions.account']) + ->get(['transaction_journals.*']); } /** * Return the ID of the budget linked to the journal (if any) or the transactions (if any). * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return int */ @@ -70,7 +67,6 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface if (null !== $budget) { return $budget->id; } - /** @noinspection NullPointerExceptionInspection */ $budget = $journal->transactions()->first()->budgets()->first(); if (null !== $budget) { return $budget->id; @@ -82,7 +78,7 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface /** * Return the ID of the category linked to the journal (if any) or to the transactions (if any). * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return int */ @@ -92,7 +88,6 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface if (null !== $category) { return $category->id; } - /** @noinspection NullPointerExceptionInspection */ $category = $journal->transactions()->first()->categories()->first(); if (null !== $category) { return $category->id; @@ -114,42 +109,29 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface /** * Return Carbon value of a meta field (or NULL). * - * @param TransactionJournal $journal - * @param string $field + * @param TransactionJournal $journal + * @param string $field * * @return null|Carbon */ public function getMetaDate(TransactionJournal $journal, string $field): ?Carbon { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('journal-meta-updated'); $cache->addProperty($journal->id); $cache->addProperty($field); if ($cache->has()) { $result = null; - try { - $result = new Carbon($cache->get()); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - - return $result; + return new Carbon($cache->get()); } $entry = $journal->transactionJournalMeta()->where('name', $field)->first(); if (null === $entry) { return null; } - $value = null; - try { - $value = new Carbon($entry->data); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - if (null !== $value) { - $cache->store($value); - } + $value = new Carbon($entry->data); + $cache->store($value); return $value; } @@ -157,14 +139,14 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface /** * Return value of a meta field (or NULL) as a string. * - * @param TransactionJournal $journal - * @param string $field + * @param TransactionJournal $journal + * @param string $field * * @return null|string */ public function getMetaField(TransactionJournal $journal, string $field): ?string { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('journal-meta-updated'); $cache->addProperty($journal->id); $cache->addProperty($field); @@ -188,12 +170,8 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface } // return when something else: - $return = (string) $value; - try { - $cache->store($return); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $return = (string)$value; + $cache->store($return); return $return; } @@ -201,7 +179,7 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface /** * Return text of a note attached to journal, or NULL * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return string|null */ @@ -223,28 +201,26 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface */ public function getSplitJournals(): Collection { - $query = TransactionJournal - ::leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') - ->groupBy('transaction_journals.id'); + $query = TransactionJournal::leftJoin('transactions', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') + ->groupBy('transaction_journals.id'); $result = $query->get(['transaction_journals.id as id', DB::raw('count(transactions.id) as transaction_count')]); $journalIds = []; /** @var stdClass $row */ foreach ($result as $row) { - if ((int) $row->transaction_count > 2) { - $journalIds[] = (int) $row->id; + if ((int)$row->transaction_count > 2) { + $journalIds[] = (int)$row->id; } } $journalIds = array_unique($journalIds); - return TransactionJournal - ::with(['transactions']) - ->whereIn('id', $journalIds)->get(); + return TransactionJournal::with(['transactions']) + ->whereIn('id', $journalIds)->get(); } /** * Return all tags as strings in an array. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return array */ @@ -254,7 +230,7 @@ class JournalCLIRepository implements JournalCLIRepositoryInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { diff --git a/app/Repositories/Journal/JournalCLIRepositoryInterface.php b/app/Repositories/Journal/JournalCLIRepositoryInterface.php index f9b2c1e899..b226973bda 100644 --- a/app/Repositories/Journal/JournalCLIRepositoryInterface.php +++ b/app/Repositories/Journal/JournalCLIRepositoryInterface.php @@ -36,7 +36,7 @@ interface JournalCLIRepositoryInterface /** * Get all transaction journals with a specific type, regardless of user. * - * @param array $types + * @param array $types * * @return Collection */ @@ -45,7 +45,7 @@ interface JournalCLIRepositoryInterface /** * Return the ID of the budget linked to the journal (if any) or the transactions (if any). * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return int */ @@ -54,7 +54,7 @@ interface JournalCLIRepositoryInterface /** * Return the ID of the category linked to the journal (if any) or to the transactions (if any). * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return int */ @@ -70,8 +70,8 @@ interface JournalCLIRepositoryInterface /** * Return Carbon value of a meta field (or NULL). * - * @param TransactionJournal $journal - * @param string $field + * @param TransactionJournal $journal + * @param string $field * * @return null|Carbon */ @@ -80,8 +80,8 @@ interface JournalCLIRepositoryInterface /** * Return value of a meta field (or NULL). * - * @param TransactionJournal $journal - * @param string $field + * @param TransactionJournal $journal + * @param string $field * * @return null|string */ @@ -90,7 +90,7 @@ interface JournalCLIRepositoryInterface /** * Return text of a note attached to journal, or NULL * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return string|null */ @@ -107,15 +107,14 @@ interface JournalCLIRepositoryInterface /** * Return all tags as strings in an array. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return array */ public function getTags(TransactionJournal $journal): array; /** - * @param User $user + * @param User $user */ public function setUser(User $user); - } diff --git a/app/Repositories/Journal/JournalRepository.php b/app/Repositories/Journal/JournalRepository.php index 5e682539d6..b48ed7fc75 100644 --- a/app/Repositories/Journal/JournalRepository.php +++ b/app/Repositories/Journal/JournalRepository.php @@ -1,4 +1,5 @@ destroy($journal); } - /** - * Find a specific journal. - * - * @param int $journalId - * - * @return TransactionJournal|null - */ - public function find(int $journalId): ?TransactionJournal - { - return $this->user->transactionJournals()->find($journalId); - } - /** * @inheritDoc */ @@ -127,13 +115,13 @@ class JournalRepository implements JournalRepositoryInterface /** * Return total amount of journal. Is always positive. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return string */ public function getJournalTotal(TransactionJournal $journal): string { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($journal->id); $cache->addProperty('amount-positive'); if ($cache->has()) { @@ -142,7 +130,7 @@ class JournalRepository implements JournalRepositoryInterface // saves on queries: $amount = $journal->transactions()->where('amount', '>', 0)->get()->sum('amount'); - $amount = (string) $amount; + $amount = (string)$amount; $cache->store($amount); return $amount; @@ -164,7 +152,7 @@ class JournalRepository implements JournalRepositoryInterface } /** - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link * * @return string */ @@ -182,14 +170,14 @@ class JournalRepository implements JournalRepositoryInterface /** * Return Carbon value of a meta field (or NULL). * - * @param int $journalId - * @param string $field + * @param int $journalId + * @param string $field * * @return null|Carbon */ public function getMetaDateById(int $journalId, string $field): ?Carbon { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('journal-meta-updated'); $cache->addProperty($journalId); $cache->addProperty($field); @@ -223,7 +211,7 @@ class JournalRepository implements JournalRepositoryInterface } /** - * @param int $journalId + * @param int $journalId */ public function reconcileById(int $journalId): void { @@ -232,11 +220,23 @@ class JournalRepository implements JournalRepositoryInterface $journal?->transactions()->update(['reconciled' => true]); } + /** + * Find a specific journal. + * + * @param int $journalId + * + * @return TransactionJournal|null + */ + public function find(int $journalId): ?TransactionJournal + { + return $this->user->transactionJournals()->find($journalId); + } + /** * Search in journal descriptions. * - * @param string $search - * @param int $limit + * @param string $search + * @param int $limit * * @return Collection */ @@ -252,7 +252,7 @@ class JournalRepository implements JournalRepositoryInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { @@ -262,8 +262,8 @@ class JournalRepository implements JournalRepositoryInterface /** * Update budget for a journal. * - * @param TransactionJournal $journal - * @param int $budgetId + * @param TransactionJournal $journal + * @param int $budgetId * * @return TransactionJournal */ @@ -287,8 +287,8 @@ class JournalRepository implements JournalRepositoryInterface /** * Update category for a journal. * - * @param TransactionJournal $journal - * @param string $category + * @param TransactionJournal $journal + * @param string $category * * @return TransactionJournal */ @@ -311,8 +311,8 @@ class JournalRepository implements JournalRepositoryInterface /** * Update tag(s) for a journal. * - * @param TransactionJournal $journal - * @param array $tags + * @param TransactionJournal $journal + * @param array $tags * * @return TransactionJournal */ diff --git a/app/Repositories/Journal/JournalRepositoryInterface.php b/app/Repositories/Journal/JournalRepositoryInterface.php index 0fe9801237..2dac2b5d3d 100644 --- a/app/Repositories/Journal/JournalRepositoryInterface.php +++ b/app/Repositories/Journal/JournalRepositoryInterface.php @@ -1,4 +1,5 @@ name = $data['name']; + } + if (array_key_exists('inward', $data) && '' !== (string)$data['inward']) { + $linkType->inward = $data['inward']; + } + if (array_key_exists('outward', $data) && '' !== (string)$data['outward']) { + $linkType->outward = $data['outward']; + } + $linkType->save(); + + return $linkType; + } + + /** + * @param TransactionJournalLink $link * * @return bool * @throws Exception @@ -83,8 +106,8 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface /** * Check if link exists between journals. * - * @param TransactionJournal $one - * @param TransactionJournal $two + * @param TransactionJournal $one + * @param TransactionJournal $two * * @return bool */ @@ -97,18 +120,10 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return $count + $opposingCount > 0; } - /** - * @return Collection - */ - public function get(): Collection - { - return LinkType::orderBy('name', 'ASC')->get(); - } - /** * Return array of all journal ID's for this type of link. * - * @param LinkType $linkType + * @param LinkType $linkType * * @return array */ @@ -121,23 +136,30 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return array_unique(array_merge($sources, $destinations)); } + /** + * @return Collection + */ + public function get(): Collection + { + return LinkType::orderBy('name', 'ASC')->get(); + } + /** * Returns all the journal links (of a specific type). * - * @param LinkType|null $linkType + * @param LinkType|null $linkType * * @return Collection */ public function getJournalLinks(LinkType $linkType = null): Collection { - $query = TransactionJournalLink - ::with(['source', 'destination']) - ->leftJoin('transaction_journals as source_journals', 'journal_links.source_id', '=', 'source_journals.id') - ->leftJoin('transaction_journals as dest_journals', 'journal_links.destination_id', '=', 'dest_journals.id') - ->where('source_journals.user_id', $this->user->id) - ->where('dest_journals.user_id', $this->user->id) - ->whereNull('source_journals.deleted_at') - ->whereNull('dest_journals.deleted_at'); + $query = TransactionJournalLink::with(['source', 'destination']) + ->leftJoin('transaction_journals as source_journals', 'journal_links.source_id', '=', 'source_journals.id') + ->leftJoin('transaction_journals as dest_journals', 'journal_links.destination_id', '=', 'dest_journals.id') + ->where('source_journals.user_id', $this->user->id) + ->where('dest_journals.user_id', $this->user->id) + ->whereNull('source_journals.deleted_at') + ->whereNull('dest_journals.deleted_at'); if (null !== $linkType) { $query->where('journal_links.link_type_id', $linkType->id); @@ -159,7 +181,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface /** * Return list of existing connections. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Collection */ @@ -177,7 +199,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { @@ -185,13 +207,13 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface } /** - * @param array $data + * @param array $data * * @return LinkType */ public function store(array $data): LinkType { - $linkType = new LinkType; + $linkType = new LinkType(); $linkType->name = $data['name']; $linkType->inward = $data['inward']; $linkType->outward = $data['outward']; @@ -204,16 +226,16 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface /** * Store link between two journals. * - * @param array $information - * @param TransactionJournal $inward - * @param TransactionJournal $outward + * @param array $information + * @param TransactionJournal $inward + * @param TransactionJournal $outward * * @return TransactionJournalLink|null * @throws Exception */ public function storeLink(array $information, TransactionJournal $inward, TransactionJournal $outward): ?TransactionJournalLink { - $linkType = $this->find((int) ($information['link_type_id'] ?? 0)); + $linkType = $this->find((int)($information['link_type_id'] ?? 0)); if (null === $linkType) { $linkType = $this->findByName($information['link_type_name']); @@ -229,7 +251,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return $existing; } - $link = new TransactionJournalLink; + $link = new TransactionJournalLink(); $link->linkType()->associate($linkType); if ('inward' === $information['direction']) { Log::debug(sprintf('Link type is inwards ("%s"), so %d is source and %d is destination.', $linkType->inward, $inward->id, $outward->id)); @@ -245,13 +267,13 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface $link->save(); // make note in noteable: - $this->setNoteText($link, (string) $information['notes']); + $this->setNoteText($link, (string)$information['notes']); return $link; } /** - * @param int $linkTypeId + * @param int $linkTypeId * * @return LinkType|null */ @@ -261,7 +283,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface } /** - * @param string|null $name + * @param string|null $name * * @return LinkType|null */ @@ -277,24 +299,22 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface /** * See if such a link already exists (and get it). * - * @param LinkType $linkType - * @param TransactionJournal $inward - * @param TransactionJournal $outward + * @param LinkType $linkType + * @param TransactionJournal $inward + * @param TransactionJournal $outward * * @return TransactionJournalLink|null */ public function findSpecificLink(LinkType $linkType, TransactionJournal $inward, TransactionJournal $outward): ?TransactionJournalLink { - return TransactionJournalLink - ::where('link_type_id', $linkType->id) - ->where('source_id', $inward->id) - ->where('destination_id', $outward->id)->first(); - + return TransactionJournalLink::where('link_type_id', $linkType->id) + ->where('source_id', $inward->id) + ->where('destination_id', $outward->id)->first(); } /** - * @param TransactionJournalLink $link - * @param string $text + * @param TransactionJournalLink $link + * @param string $text * * @throws Exception */ @@ -311,14 +331,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return; } - if (null !== $dbNote && '' === $text) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - } - + $dbNote?->delete(); } /** @@ -336,7 +349,7 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface } /** - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link * * @return bool */ @@ -350,33 +363,11 @@ class LinkTypeRepository implements LinkTypeRepositoryInterface return true; } - /** - * @param LinkType $linkType - * @param array $data - * - * @return LinkType - */ - public function update(LinkType $linkType, array $data): LinkType - { - if (array_key_exists('name', $data) && '' !== (string) $data['name']) { - $linkType->name = $data['name']; - } - if (array_key_exists('inward', $data) && '' !== (string) $data['inward']) { - $linkType->inward = $data['inward']; - } - if (array_key_exists('outward', $data) && '' !== (string) $data['outward']) { - $linkType->outward = $data['outward']; - } - $linkType->save(); - - return $linkType; - } - /** * Update an existing transaction journal link. * - * @param TransactionJournalLink $journalLink - * @param array $data + * @param TransactionJournalLink $journalLink + * @param array $data * * @return TransactionJournalLink * @throws Exception diff --git a/app/Repositories/LinkType/LinkTypeRepositoryInterface.php b/app/Repositories/LinkType/LinkTypeRepositoryInterface.php index 2898350046..9c3c9f338a 100644 --- a/app/Repositories/LinkType/LinkTypeRepositoryInterface.php +++ b/app/Repositories/LinkType/LinkTypeRepositoryInterface.php @@ -1,4 +1,5 @@ user->objectGroups()->max('order'); + return (int)$this->user->objectGroups()->max('order'); } /** - * @param string $title + * @param string $title * * @return bool */ @@ -81,7 +81,7 @@ trait CreatesObjectGroups } /** - * @param string $title + * @param string $title * * @return null|ObjectGroup */ diff --git a/app/Repositories/ObjectGroup/ObjectGroupRepository.php b/app/Repositories/ObjectGroup/ObjectGroupRepository.php index 72758404d7..35a42991fa 100644 --- a/app/Repositories/ObjectGroup/ObjectGroupRepository.php +++ b/app/Repositories/ObjectGroup/ObjectGroupRepository.php @@ -118,7 +118,7 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface $index = 1; /** @var ObjectGroup $objectGroup */ foreach ($list as $objectGroup) { - if ($index !== (int) $objectGroup->order) { + if ($index !== (int)$objectGroup->order) { Log::debug( sprintf('objectGroup #%d ("%s"): order should %d be but is %d.', $objectGroup->id, $objectGroup->title, $index, $objectGroup->order) ); @@ -130,8 +130,8 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface } /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ @@ -145,14 +145,13 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface $search = sprintf('%%%s%%', $part); $dbQuery->where('title', 'LIKE', $search); } - } return $dbQuery->take($limit)->get(['object_groups.*']); } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { @@ -169,7 +168,7 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface } if (array_key_exists('order', $data)) { - $this->setOrder($objectGroup, (int) $data['order']); + $this->setOrder($objectGroup, (int)$data['order']); } $objectGroup->save(); @@ -182,7 +181,7 @@ class ObjectGroupRepository implements ObjectGroupRepositoryInterface */ public function setOrder(ObjectGroup $objectGroup, int $newOrder): ObjectGroup { - $oldOrder = (int) $objectGroup->order; + $oldOrder = (int)$objectGroup->order; if ($newOrder > $oldOrder) { $this->user->objectGroups()->where('object_groups.order', '<=', $newOrder)->where('object_groups.order', '>', $oldOrder) diff --git a/app/Repositories/ObjectGroup/ObjectGroupRepositoryInterface.php b/app/Repositories/ObjectGroup/ObjectGroupRepositoryInterface.php index c22ff21833..2a5b2c44e7 100644 --- a/app/Repositories/ObjectGroup/ObjectGroupRepositoryInterface.php +++ b/app/Repositories/ObjectGroup/ObjectGroupRepositoryInterface.php @@ -44,7 +44,7 @@ interface ObjectGroupRepositoryInterface public function deleteEmpty(): void; /** - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup */ public function destroy(ObjectGroup $objectGroup): void; @@ -54,14 +54,14 @@ interface ObjectGroupRepositoryInterface public function get(): Collection; /** - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return Collection */ public function getBills(ObjectGroup $objectGroup): Collection; /** - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return Collection */ @@ -73,32 +73,31 @@ interface ObjectGroupRepositoryInterface public function resetOrder(): void; /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ public function search(string $query, int $limit): Collection; /** - * @param ObjectGroup $objectGroup - * @param int $newOrder + * @param ObjectGroup $objectGroup + * @param int $newOrder * * @return ObjectGroup */ public function setOrder(ObjectGroup $objectGroup, int $newOrder): ObjectGroup; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** - * @param ObjectGroup $objectGroup - * @param array $data + * @param ObjectGroup $objectGroup + * @param array $data * * @return ObjectGroup */ public function update(ObjectGroup $objectGroup, array $data): ObjectGroup; - } diff --git a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php index d43ff1def1..4f403150af 100644 --- a/app/Repositories/PiggyBank/ModifiesPiggyBanks.php +++ b/app/Repositories/PiggyBank/ModifiesPiggyBanks.php @@ -42,6 +42,46 @@ trait ModifiesPiggyBanks { use CreatesObjectGroups; + /** + * @param PiggyBankRepetition $repetition + * @param string $amount + * + * @return void + */ + public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount, TransactionJournal $journal): void + { + Log::debug(sprintf('addAmountToRepetition: %s', $amount)); + if (-1 === bccomp($amount, '0')) { + Log::debug('Remove amount.'); + $this->removeAmount($repetition->piggyBank, bcmul($amount, '-1'), $journal); + } + if (1 === bccomp($amount, '0')) { + Log::debug('Add amount.'); + $this->addAmount($repetition->piggyBank, $amount, $journal); + } + } + + /** + * @param PiggyBank $piggyBank + * @param string $amount + * + * @return bool + */ + public function removeAmount(PiggyBank $piggyBank, string $amount, ?TransactionJournal $journal = null): bool + { + $repetition = $this->getRepetition($piggyBank); + if (null === $repetition) { + return false; + } + $repetition->currentamount = bcsub($repetition->currentamount, $amount); + $repetition->save(); + + Log::debug('addAmount: Trigger change for negative amount.'); + event(new ChangedPiggyBankAmount($piggyBank, bcmul($amount, '-1'), $journal, null)); + + return true; + } + /** * @param PiggyBank $piggyBank * @param string $amount @@ -64,25 +104,6 @@ trait ModifiesPiggyBanks return true; } - /** - * @param PiggyBankRepetition $repetition - * @param string $amount - * - * @return void - */ - public function addAmountToRepetition(PiggyBankRepetition $repetition, string $amount, TransactionJournal $journal): void - { - Log::debug(sprintf('addAmountToRepetition: %s', $amount)); - if (-1 === bccomp($amount, '0')) { - Log::debug('Remove amount.'); - $this->removeAmount($repetition->piggyBank, bcmul($amount, '-1'), $journal); - } - if (1 === bccomp($amount, '0')) { - Log::debug('Add amount.'); - $this->addAmount($repetition->piggyBank, $amount, $journal); - } - } - /** * @param PiggyBank $piggyBank * @param string $amount @@ -144,27 +165,6 @@ trait ModifiesPiggyBanks return true; } - /** - * @param PiggyBank $piggyBank - * @param string $amount - * - * @return bool - */ - public function removeAmount(PiggyBank $piggyBank, string $amount, ?TransactionJournal $journal = null): bool - { - $repetition = $this->getRepetition($piggyBank); - if (null === $repetition) { - return false; - } - $repetition->currentamount = bcsub($repetition->currentamount, $amount); - $repetition->save(); - - Log::debug('addAmount: Trigger change for negative amount.'); - event(new ChangedPiggyBankAmount($piggyBank, bcmul($amount, '-1'), $journal, null)); - - return true; - } - /** * @inheritDoc */ @@ -339,19 +339,13 @@ trait ModifiesPiggyBanks { if ('' === $note) { $dbNote = $piggyBank->notes()->first(); - if (null !== $dbNote) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } - } + $dbNote?->delete(); return true; } $dbNote = $piggyBank->notes()->first(); if (null === $dbNote) { - $dbNote = new Note; + $dbNote = new Note(); $dbNote->noteable()->associate($piggyBank); } $dbNote->text = trim($note); diff --git a/app/Repositories/PiggyBank/PiggyBankRepository.php b/app/Repositories/PiggyBank/PiggyBankRepository.php index e74d486dd3..0396642f7c 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepository.php +++ b/app/Repositories/PiggyBank/PiggyBankRepository.php @@ -1,4 +1,5 @@ find((int) $piggyBankId); + $searchResult = $this->find((int)$piggyBankId); if (null !== $searchResult) { Log::debug(sprintf('Found piggy based on #%d, will return it.', $piggyBankId)); @@ -73,7 +76,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface } } if (null !== $piggyBankName) { - $searchResult = $this->findByName((string) $piggyBankName); + $searchResult = $this->findByName((string)$piggyBankName); if (null !== $searchResult) { Log::debug(sprintf('Found piggy based on "%s", will return it.', $piggyBankName)); @@ -86,19 +89,20 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface } /** - * @param int $piggyBankId + * @param int $piggyBankId * * @return PiggyBank|null */ public function find(int $piggyBankId): ?PiggyBank { - return $this->user->piggyBanks()->find($piggyBankId); + // phpstan doesn't get the Model. + return $this->user->piggyBanks()->find($piggyBankId); // @phpstan-ignore-line } /** * Find by name or return NULL. * - * @param string $name + * @param string $name * * @return PiggyBank|null */ @@ -121,7 +125,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface static function (Attachment $attachment) use ($disk) { $notes = $attachment->notes()->first(); $attachment->file_exists = $disk->exists($attachment->fileName()); - $attachment->notes = $notes ? $notes->text : ''; + $attachment->notes = $notes ? $notes->text : ''; // TODO setting the text to the 'notes' field doesn't work. return $attachment; } @@ -131,7 +135,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface /** * Get current amount saved in piggy bank. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return string */ @@ -142,11 +146,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return '0'; } - return (string) $rep->currentamount; + return (string)$rep->currentamount; } /** - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return PiggyBankRepetition|null */ @@ -156,7 +160,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface } /** - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return Collection */ @@ -168,13 +172,13 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface /** * Used for connecting to a piggy bank. * - * @param PiggyBank $piggyBank - * @param PiggyBankRepetition $repetition - * @param TransactionJournal $journal + * @param PiggyBank $piggyBank + * @param PiggyBankRepetition $repetition + * @param TransactionJournal $journal * * @return string - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException + * @throws FireflyException + * @throws JsonException */ public function getExactAmount(PiggyBank $piggyBank, PiggyBankRepetition $repetition, TransactionJournal $journal): string { @@ -221,11 +225,11 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface // currency of the account + the piggy bank currency are almost the same. // which amount from the transaction matches? $amount = null; - if ((int) $source->transaction_currency_id === (int) $currency->id) { + if ((int)$source->transaction_currency_id === (int)$currency->id) { Log::debug('Use normal amount'); $amount = app('steam')->$operator($source->amount); } - if ((int) $source->foreign_currency_id === (int) $currency->id) { + if ((int)$source->foreign_currency_id === (int)$currency->id) { Log::debug('Use foreign amount'); $amount = app('steam')->$operator($source->foreign_amount); } @@ -236,10 +240,10 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface } Log::debug(sprintf('The currency is %s and the amount is %s', $currency->code, $amount)); - $room = bcsub((string) $piggyBank->targetamount, (string) $repetition->currentamount); + $room = bcsub((string)$piggyBank->targetamount, (string)$repetition->currentamount); $compare = bcmul($repetition->currentamount, '-1'); - if(bccomp((string) $piggyBank->targetamount,'0') === 0) { + if (bccomp((string)$piggyBank->targetamount, '0') === 0) { // amount is zero? then the "room" is positive amount of we wish to add or remove. $room = app('steam')->positive($amount); Log::debug(sprintf('Room is now %s', $room)); @@ -266,7 +270,15 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return $compare; } - return (string) $amount; + return (string)$amount; + } + + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; } /** @@ -274,13 +286,13 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface */ public function getMaxOrder(): int { - return (int) $this->user->piggyBanks()->max('piggy_banks.order'); + return (int)$this->user->piggyBanks()->max('piggy_banks.order'); } /** * Return note for piggy bank. * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return string */ @@ -302,7 +314,6 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface */ public function getPiggyBanksWithAmount(): Collection { - $currency = app('amount')->getDefaultCurrency(); $set = $this->getPiggyBanks(); @@ -310,7 +321,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface /** @var PiggyBank $piggy */ foreach ($set as $piggy) { $currentAmount = $this->getRepetition($piggy)->currentamount ?? '0'; - $piggy->name = $piggy->name . ' (' . app('amount')->formatAnything($currency, $currentAmount, false) . ')'; + $piggy->name = $piggy->name.' ('.app('amount')->formatAnything($currency, $currentAmount, false).')'; } return $set; @@ -321,13 +332,19 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface */ public function getPiggyBanks(): Collection { - return $this->user->piggyBanks()->with(['account', 'objectGroups'])->orderBy('order', 'ASC')->get(); + return $this->user // @phpstan-ignore-line (phpstan does not recognize objectGroups) + ->piggyBanks() + ->with( + ['account', + 'objectGroups'] + ) + ->orderBy('order', 'ASC')->get(); } /** * Returns the suggested amount the user should save per month, or "". * - * @param PiggyBank $piggyBank + * @param PiggyBank $piggyBank * * @return string * @@ -347,7 +364,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface // more than 1 month to go and still need money to save: if ($diffInMonths > 0 && 1 === bccomp($remainingAmount, '0')) { - $savePerMonth = bcdiv($remainingAmount, (string) $diffInMonths); + $savePerMonth = bcdiv($remainingAmount, (string)$diffInMonths); } // less than 1 month to go but still need money to save: @@ -362,15 +379,14 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface /** * Get for piggy account what is left to put in piggies. * - * @param PiggyBank $piggyBank - * @param Carbon $date + * @param PiggyBank $piggyBank + * @param Carbon $date * * @return string - * @throws \JsonException + * @throws JsonException */ public function leftOnAccount(PiggyBank $piggyBank, Carbon $date): string { - $balance = app('steam')->balanceIgnoreVirtual($piggyBank->account, $date); /** @var Collection $piggies */ @@ -401,12 +417,4 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface return $search->take($limit)->get(); } - - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } } diff --git a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php index e3b83132b2..d786a77364 100644 --- a/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php +++ b/app/Repositories/PiggyBank/PiggyBankRepositoryInterface.php @@ -1,4 +1,5 @@ where('name', 'recurrence_id'); + $q1->where('data', json_encode((string)$recurrence->id)); + })->get(['journal_meta.transaction_journal_id']); + + // there are X journals made for this recurrence. Any of them meant for today? + foreach ($set as $journalMeta) { + $count = TransactionJournalMeta::where(function (Builder $q2) use ($date) { + $string = (string)$date; + Log::debug(sprintf('Search for date: %s', json_encode($string))); + $q2->where('name', 'recurrence_date'); + $q2->where('data', json_encode($string)); + }) + ->where('transaction_journal_id', $journalMeta->transaction_journal_id) + ->count(); + if ($count > 0) { + Log::debug(sprintf('Looks like journal #%d was already created', $journalMeta->transaction_journal_id)); + return true; + } + } + return false; + } + /** * Destroy a recurring transaction. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence */ public function destroy(Recurrence $recurrence): void { @@ -77,6 +111,20 @@ class RecurringRepository implements RecurringRepositoryInterface $this->user->recurrences()->delete(); } + /** + * Get ALL recurring transactions. + * + * @return Collection + */ + public function getAll(): Collection + { + // grab ALL recurring transactions: + return Recurrence::with(['TransactionCurrency', 'TransactionType', 'RecurrenceRepetitions', 'RecurrenceTransactions']) + ->orderBy('active', 'DESC') + ->orderBy('title', 'ASC') + ->get(); + } + /** * Returns all of the user's recurring transactions. * @@ -92,21 +140,6 @@ class RecurringRepository implements RecurringRepositoryInterface ->get(); } - /** - * Get ALL recurring transactions. - * - * @return Collection - */ - public function getAll(): Collection - { - // grab ALL recurring transactions: - return Recurrence - ::with(['TransactionCurrency', 'TransactionType', 'RecurrenceRepetitions', 'RecurrenceTransactions']) - ->orderBy('active', 'DESC') - ->orderBy('title', 'ASC') - ->get(); - } - /** * @inheritDoc */ @@ -116,7 +149,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $meta */ foreach ($recTransaction->recurrenceTransactionMeta as $meta) { if ('bill_id' === $meta->name) { - $return = (int) $meta->value; + $return = (int)$meta->value; } } @@ -126,7 +159,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Get the budget ID from a recurring transaction transaction. * - * @param RecurrenceTransaction $recTransaction + * @param RecurrenceTransaction $recTransaction * * @return null|int */ @@ -136,7 +169,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $meta */ foreach ($recTransaction->recurrenceTransactionMeta as $meta) { if ('budget_id' === $meta->name) { - $return = (int) $meta->value; + $return = (int)$meta->value; } } @@ -146,7 +179,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Get the category from a recurring transaction transaction. * - * @param RecurrenceTransaction $recTransaction + * @param RecurrenceTransaction $recTransaction * * @return null|int */ @@ -156,7 +189,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $meta */ foreach ($recTransaction->recurrenceTransactionMeta as $meta) { if ('category_id' === $meta->name) { - $return = (int) $meta->value; + $return = (int)$meta->value; } } @@ -166,7 +199,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Get the category from a recurring transaction transaction. * - * @param RecurrenceTransaction $recTransaction + * @param RecurrenceTransaction $recTransaction * * @return null|string */ @@ -176,7 +209,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $meta */ foreach ($recTransaction->recurrenceTransactionMeta as $meta) { if ('category_name' === $meta->name) { - $return = (string) $meta->value; + $return = (string)$meta->value; } } @@ -186,34 +219,32 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Returns the journals created for this recurrence, possibly limited by time. * - * @param Recurrence $recurrence - * @param Carbon|null $start - * @param Carbon|null $end + * @param Recurrence $recurrence + * @param Carbon|null $start + * @param Carbon|null $end * * @return int */ public function getJournalCount(Recurrence $recurrence, Carbon $start = null, Carbon $end = null): int { - $query = TransactionJournal - ::leftJoin('journal_meta', 'journal_meta.transaction_journal_id', '=', 'transaction_journals.id') - ->where('transaction_journals.user_id', $recurrence->user_id) - ->whereNull('transaction_journals.deleted_at') - ->where('journal_meta.name', 'recurrence_id') - ->where('journal_meta.data', '"' . $recurrence->id . '"'); + $query = TransactionJournal::leftJoin('journal_meta', 'journal_meta.transaction_journal_id', '=', 'transaction_journals.id') + ->where('transaction_journals.user_id', $recurrence->user_id) + ->whereNull('transaction_journals.deleted_at') + ->where('journal_meta.name', 'recurrence_id') + ->where('journal_meta.data', '"'.$recurrence->id.'"'); if (null !== $start) { $query->where('transaction_journals.date', '>=', $start->format('Y-m-d 00:00:00')); } if (null !== $end) { $query->where('transaction_journals.date', '<=', $end->format('Y-m-d 00:00:00')); } - return $query->count(['transaction_journals.id']); } /** * Get journal ID's for journals created by this recurring transaction. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return array */ @@ -222,14 +253,14 @@ class RecurringRepository implements RecurringRepositoryInterface return TransactionJournalMeta::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') ->where('transaction_journals.user_id', $this->user->id) ->where('journal_meta.name', '=', 'recurrence_id') - ->where('journal_meta.data', '=', json_encode((string) $recurrence->id)) + ->where('journal_meta.data', '=', json_encode((string)$recurrence->id)) ->get(['journal_meta.transaction_journal_id'])->pluck('transaction_journal_id')->toArray(); } /** * Get the notes. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return string */ @@ -238,14 +269,14 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var Note $note */ $note = $recurrence->notes()->first(); if (null !== $note) { - return (string) $note->text; + return (string)$note->text; } return ''; } /** - * @param RecurrenceTransaction $transaction + * @param RecurrenceTransaction $transaction * * @return int|null */ @@ -255,7 +286,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** @var RecurrenceTransactionMeta $metaEntry */ foreach ($meta as $metaEntry) { if ('piggy_bank_id' === $metaEntry->name) { - return (int) $metaEntry->value; + return (int)$metaEntry->value; } } @@ -265,7 +296,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Get the tags from the recurring transaction. * - * @param RecurrenceTransaction $transaction + * @param RecurrenceTransaction $transaction * * @return array * @throws JsonException @@ -284,24 +315,23 @@ class RecurringRepository implements RecurringRepositoryInterface } /** - * @param Recurrence $recurrence - * @param int $page - * @param int $pageSize + * @param Recurrence $recurrence + * @param int $page + * @param int $pageSize * * @return LengthAwarePaginator */ public function getTransactionPaginator(Recurrence $recurrence, int $page, int $pageSize): LengthAwarePaginator { - $journalMeta = TransactionJournalMeta - ::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') - ->whereNull('transaction_journals.deleted_at') - ->where('transaction_journals.user_id', $this->user->id) - ->where('name', 'recurrence_id') - ->where('data', json_encode((string) $recurrence->id)) - ->get()->pluck('transaction_journal_id')->toArray(); + $journalMeta = TransactionJournalMeta::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') + ->whereNull('transaction_journals.deleted_at') + ->where('transaction_journals.user_id', $this->user->id) + ->where('name', 'recurrence_id') + ->where('data', json_encode((string)$recurrence->id)) + ->get()->pluck('transaction_journal_id')->toArray(); $search = []; foreach ($journalMeta as $journalId) { - $search[] = (int) $journalId; + $search[] = (int)$journalId; } /** @var GroupCollectorInterface $collector */ $collector = app(GroupCollectorInterface::class); @@ -315,27 +345,35 @@ class RecurringRepository implements RecurringRepositoryInterface } /** - * @param Recurrence $recurrence + * Set user for in repository. + * + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @param Recurrence $recurrence * * @return Collection */ public function getTransactions(Recurrence $recurrence): Collection { - $journalMeta = TransactionJournalMeta - ::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') - ->whereNull('transaction_journals.deleted_at') - ->where('transaction_journals.user_id', $this->user->id) - ->where('name', 'recurrence_id') - ->where('data', json_encode((string) $recurrence->id)) - ->get()->pluck('transaction_journal_id')->toArray(); + $journalMeta = TransactionJournalMeta::leftJoin('transaction_journals', 'transaction_journals.id', '=', 'journal_meta.transaction_journal_id') + ->whereNull('transaction_journals.deleted_at') + ->where('transaction_journals.user_id', $this->user->id) + ->where('name', 'recurrence_id') + ->where('data', json_encode((string)$recurrence->id)) + ->get()->pluck('transaction_journal_id')->toArray(); $search = []; foreach ($journalMeta as $journalId) { - $search[] = (int) $journalId; + $search[] = (int)$journalId; } - if (empty($search)) { - - return new Collection; + if (0 === count($search)) { + return new Collection(); } /** @var GroupCollectorInterface $collector */ @@ -352,9 +390,9 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Calculate the next X iterations starting on the date given in $date. * - * @param RecurrenceRepetition $repetition - * @param Carbon $date - * @param int $count + * @param RecurrenceRepetition $repetition + * @param Carbon $date + * @param int $count * * @return array * @@ -389,10 +427,10 @@ class RecurringRepository implements RecurringRepositoryInterface * * Only returns them of they are after $afterDate * - * @param RecurrenceRepetition $repetition - * @param Carbon $date - * @param Carbon $afterDate - * @param int $count + * @param RecurrenceRepetition $repetition + * @param Carbon $date + * @param Carbon $afterDate + * @param int $count * * @return array */ @@ -427,8 +465,8 @@ class RecurringRepository implements RecurringRepositoryInterface } /** - * @param Carbon|null $max - * @param array $occurrences + * @param Carbon|null $max + * @param array $occurrences * * @return array */ @@ -450,7 +488,7 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Parse the repetition in a string that is user readable. * - * @param RecurrenceRepetition $repetition + * @param RecurrenceRepetition $repetition * * @return string * @throws FireflyException @@ -462,26 +500,29 @@ class RecurringRepository implements RecurringRepositoryInterface $pref = app('preferences')->getForUser($this->user, 'language', config('firefly.default_language', 'en_US')); $language = $pref->data; if ('daily' === $repetition->repetition_type) { - return (string) trans('firefly.recurring_daily', [], $language); + return (string)trans('firefly.recurring_daily', [], $language); } if ('weekly' === $repetition->repetition_type) { - $dayOfWeek = trans(sprintf('config.dow_%s', $repetition->repetition_moment), [], $language); if ($repetition->repetition_skip > 0) { - return (string) trans('firefly.recurring_weekly_skip', ['weekday' => $dayOfWeek, 'skip' => $repetition->repetition_skip + 1], $language); + return (string)trans('firefly.recurring_weekly_skip', ['weekday' => $dayOfWeek, 'skip' => $repetition->repetition_skip + 1], $language); } - return (string) trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek], $language); + return (string)trans('firefly.recurring_weekly', ['weekday' => $dayOfWeek], $language); } if ('monthly' === $repetition->repetition_type) { if ($repetition->repetition_skip > 0) { - return (string) trans( - 'firefly.recurring_monthly_skip', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip + 1], $language + return (string)trans( + 'firefly.recurring_monthly_skip', + ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip + 1], + $language ); } - return (string) trans( - 'firefly.recurring_monthly', ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], $language + return (string)trans( + 'firefly.recurring_monthly', + ['dayOfMonth' => $repetition->repetition_moment, 'skip' => $repetition->repetition_skip - 1], + $language ); } if ('ndom' === $repetition->repetition_type) { @@ -489,7 +530,7 @@ class RecurringRepository implements RecurringRepositoryInterface // first part is number of week, second is weekday. $dayOfWeek = trans(sprintf('config.dow_%s', $parts[1]), [], $language); - return (string) trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $parts[0]], $language); + return (string)trans('firefly.recurring_ndom', ['weekday' => $dayOfWeek, 'dayOfMonth' => $parts[0]], $language); } if ('yearly' === $repetition->repetition_type) { // @@ -497,13 +538,12 @@ class RecurringRepository implements RecurringRepositoryInterface $repDate = Carbon::createFromFormat('Y-m-d', $repetition->repetition_moment); $diffInYears = $today->diffInYears($repDate); $repDate->addYears($diffInYears); // technically not necessary. - $string = $repDate->isoFormat((string) trans('config.month_and_day_no_year_js')); + $string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js')); - return (string) trans('firefly.recurring_yearly', ['date' => $string], $language); + return (string)trans('firefly.recurring_yearly', ['date' => $string], $language); } return ''; - } /** @@ -522,17 +562,7 @@ class RecurringRepository implements RecurringRepositoryInterface } /** - * Set user for in repository. - * - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param array $data + * @param array $data * * @return Recurrence * @throws FireflyException @@ -556,16 +586,16 @@ class RecurringRepository implements RecurringRepositoryInterface public function totalTransactions(Recurrence $recurrence, RecurrenceRepetition $repetition): int { // if repeat = null just return 0. - if (null === $recurrence->repeat_until && 0 === (int) $recurrence->repetitions) { + if (null === $recurrence->repeat_until && 0 === (int)$recurrence->repetitions) { return 0; } // expect X transactions then stop. Return that number - if (null === $recurrence->repeat_until && 0 !== (int) $recurrence->repetitions) { - return (int) $recurrence->repetitions; + if (null === $recurrence->repeat_until && 0 !== (int)$recurrence->repetitions) { + return (int)$recurrence->repetitions; } // need to calculate, this depends on the repetition: - if (null !== $recurrence->repeat_until && 0 === (int) $recurrence->repetitions) { + if (null !== $recurrence->repeat_until && 0 === (int)$recurrence->repetitions) { $occurrences = $this->getOccurrencesInRange($repetition, $recurrence->first_date ?? today(), $recurrence->repeat_until); return count($occurrences); @@ -577,9 +607,9 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Generate events in the date range. * - * @param RecurrenceRepetition $repetition - * @param Carbon $start - * @param Carbon $end + * @param RecurrenceRepetition $repetition + * @param Carbon $start + * @param Carbon $end * * @return array * @@ -616,8 +646,8 @@ class RecurringRepository implements RecurringRepositoryInterface /** * Update a recurring transaction. * - * @param Recurrence $recurrence - * @param array $data + * @param Recurrence $recurrence + * @param array $data * * @return Recurrence * @throws FireflyException diff --git a/app/Repositories/Recurring/RecurringRepositoryInterface.php b/app/Repositories/Recurring/RecurringRepositoryInterface.php index 08ceab085a..c4fca83361 100644 --- a/app/Repositories/Recurring/RecurringRepositoryInterface.php +++ b/app/Repositories/Recurring/RecurringRepositoryInterface.php @@ -38,10 +38,17 @@ use Illuminate\Support\Collection; */ interface RecurringRepositoryInterface { + /** + * @param Recurrence $recurrence + * @param Carbon $date + * @return bool + */ + public function createdPreviously(Recurrence $recurrence, Carbon $date): bool; + /** * Destroy a recurring transaction. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence */ public function destroy(Recurrence $recurrence): void; @@ -67,7 +74,7 @@ interface RecurringRepositoryInterface /** * Get the category from a recurring transaction transaction. * - * @param RecurrenceTransaction $recTransaction + * @param RecurrenceTransaction $recTransaction * * @return null|int */ @@ -76,7 +83,7 @@ interface RecurringRepositoryInterface /** * Get the budget ID from a recurring transaction transaction. * - * @param RecurrenceTransaction $recTransaction + * @param RecurrenceTransaction $recTransaction * * @return null|int */ @@ -85,7 +92,7 @@ interface RecurringRepositoryInterface /** * Get the category from a recurring transaction transaction. * - * @param RecurrenceTransaction $recTransaction + * @param RecurrenceTransaction $recTransaction * * @return null|int */ @@ -94,7 +101,7 @@ interface RecurringRepositoryInterface /** * Get the category from a recurring transaction transaction. * - * @param RecurrenceTransaction $recTransaction + * @param RecurrenceTransaction $recTransaction * * @return null|string */ @@ -103,9 +110,9 @@ interface RecurringRepositoryInterface /** * Returns the count of journals created for this recurrence, possibly limited by time. * - * @param Recurrence $recurrence - * @param Carbon|null $start - * @param Carbon|null $end + * @param Recurrence $recurrence + * @param Carbon|null $start + * @param Carbon|null $end * * @return int */ @@ -114,7 +121,7 @@ interface RecurringRepositoryInterface /** * Get journal ID's for journals created by this recurring transaction. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return array */ @@ -123,7 +130,7 @@ interface RecurringRepositoryInterface /** * Get the notes. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return string */ @@ -132,16 +139,16 @@ interface RecurringRepositoryInterface /** * Generate events in the date range. * - * @param RecurrenceRepetition $repetition - * @param Carbon $start - * @param Carbon $end + * @param RecurrenceRepetition $repetition + * @param Carbon $start + * @param Carbon $end * * @return array */ public function getOccurrencesInRange(RecurrenceRepetition $repetition, Carbon $start, Carbon $end): array; /** - * @param RecurrenceTransaction $transaction + * @param RecurrenceTransaction $transaction * * @return int|null */ @@ -150,23 +157,23 @@ interface RecurringRepositoryInterface /** * Get the tags from the recurring transaction. * - * @param RecurrenceTransaction $transaction + * @param RecurrenceTransaction $transaction * * @return array */ public function getTags(RecurrenceTransaction $transaction): array; /** - * @param Recurrence $recurrence - * @param int $page - * @param int $pageSize + * @param Recurrence $recurrence + * @param int $page + * @param int $pageSize * * @return LengthAwarePaginator */ public function getTransactionPaginator(Recurrence $recurrence, int $page, int $pageSize): LengthAwarePaginator; /** - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return Collection */ @@ -176,9 +183,9 @@ interface RecurringRepositoryInterface * Calculate the next X iterations starting on the date given in $date. * Returns an array of Carbon objects. * - * @param RecurrenceRepetition $repetition - * @param Carbon $date - * @param int $count + * @param RecurrenceRepetition $repetition + * @param Carbon $date + * @param int $count * * @return array * @throws FireflyException @@ -191,10 +198,10 @@ interface RecurringRepositoryInterface * * Only returns them of they are after $afterDate * - * @param RecurrenceRepetition $repetition - * @param Carbon $date - * @param Carbon $afterDate - * @param int $count + * @param RecurrenceRepetition $repetition + * @param Carbon $date + * @param Carbon $afterDate + * @param int $count * * @return array * @throws FireflyException @@ -204,15 +211,15 @@ interface RecurringRepositoryInterface /** * Parse the repetition in a string that is user readable. * - * @param RecurrenceRepetition $repetition + * @param RecurrenceRepetition $repetition * * @return string */ public function repetitionDescription(RecurrenceRepetition $repetition): string; /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ @@ -221,14 +228,14 @@ interface RecurringRepositoryInterface /** * Set user for in repository. * - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** * Store a new recurring transaction. * - * @param array $data + * @param array $data * * @return Recurrence * @throws FireflyException @@ -238,8 +245,8 @@ interface RecurringRepositoryInterface /** * Calculate how many transactions are to be expected from this recurrence. * - * @param Recurrence $recurrence - * @param RecurrenceRepetition $repetition + * @param Recurrence $recurrence + * @param RecurrenceRepetition $repetition * * @return int */ @@ -248,11 +255,10 @@ interface RecurringRepositoryInterface /** * Update a recurring transaction. * - * @param Recurrence $recurrence - * @param array $data + * @param Recurrence $recurrence + * @param array $data * * @return Recurrence */ public function update(Recurrence $recurrence, array $data): Recurrence; - } diff --git a/app/Repositories/Rule/RuleRepository.php b/app/Repositories/Rule/RuleRepository.php index 7305677f64..32a1377b4b 100644 --- a/app/Repositories/Rule/RuleRepository.php +++ b/app/Repositories/Rule/RuleRepository.php @@ -1,4 +1,5 @@ user->rules()->count(); - } - - /** - * @param Rule $rule + * @param Rule $rule * * @return bool * @throws Exception @@ -76,7 +69,7 @@ class RuleRepository implements RuleRepositoryInterface public function duplicate(Rule $rule): Rule { $newRule = $rule->replicate(); - $newRule->title = (string) trans('firefly.rule_copy_of', ['title' => $rule->title]); + $newRule->title = (string)trans('firefly.rule_copy_of', ['title' => $rule->title]); $newRule->save(); // replicate all triggers @@ -98,16 +91,6 @@ class RuleRepository implements RuleRepositoryInterface return $newRule; } - /** - * @param int $ruleId - * - * @return Rule|null - */ - public function find(int $ruleId): ?Rule - { - return $this->user->rules()->find($ruleId); - } - /** * Get all the users rules. * @@ -129,17 +112,17 @@ class RuleRepository implements RuleRepositoryInterface } /** - * @param RuleGroup $ruleGroup + * @param RuleGroup $ruleGroup * * @return int */ public function getHighestOrderInRuleGroup(RuleGroup $ruleGroup): int { - return (int) $ruleGroup->rules()->max('order'); + return (int)$ruleGroup->rules()->max('order'); } /** - * @param Rule $rule + * @param Rule $rule * * @return string * @@ -149,14 +132,22 @@ class RuleRepository implements RuleRepositoryInterface { $count = $rule->ruleTriggers()->count(); if (0 === $count) { - throw new FireflyException('Rules should have more than zero triggers, rule #' . $rule->id . ' has none!'); + throw new FireflyException('Rules should have more than zero triggers, rule #'.$rule->id.' has none!'); } return $rule->ruleTriggers()->where('trigger_type', 'user_action')->first()->trigger_value; } /** - * @param Rule $rule + * @return int + */ + public function count(): int + { + return $this->user->rules()->count(); + } + + /** + * @param Rule $rule * * @return Collection */ @@ -166,7 +157,7 @@ class RuleRepository implements RuleRepositoryInterface } /** - * @param Rule $rule + * @param Rule $rule * * @return Collection */ @@ -196,7 +187,6 @@ class RuleRepository implements RuleRepositoryInterface } return implode(' ', $params); - } /** @@ -212,7 +202,7 @@ class RuleRepository implements RuleRepositoryInterface ->orderBy('rules.order', 'ASC') ->orderBy('rules.id', 'ASC') ->with(['ruleGroup', 'ruleTriggers'])->get(['rules.*']); - $filtered = new Collection; + $filtered = new Collection(); /** @var Rule $rule */ foreach ($collection as $rule) { /** @var RuleTrigger $ruleTrigger */ @@ -239,7 +229,7 @@ class RuleRepository implements RuleRepositoryInterface ->orderBy('rules.order', 'ASC') ->orderBy('rules.id', 'ASC') ->with(['ruleGroup', 'ruleTriggers'])->get(); - $filtered = new Collection; + $filtered = new Collection(); /** @var Rule $rule */ foreach ($collection as $rule) { /** @var RuleTrigger $ruleTrigger */ @@ -269,15 +259,7 @@ class RuleRepository implements RuleRepositoryInterface } /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param array $data + * @param array $data * * @return Rule * @throws FireflyException @@ -296,7 +278,7 @@ class RuleRepository implements RuleRepositoryInterface } // start by creating a new rule: - $rule = new Rule; + $rule = new Rule(); $rule->user()->associate($this->user->id); $rule->rule_group_id = $ruleGroup->id; @@ -331,8 +313,18 @@ class RuleRepository implements RuleRepositoryInterface } /** - * @param string $moment - * @param Rule $rule + * @param int $ruleId + * + * @return Rule|null + */ + public function find(int $ruleId): ?Rule + { + return $this->user->rules()->find($ruleId); + } + + /** + * @param string $moment + * @param Rule $rule */ private function setRuleTrigger(string $moment, Rule $rule): void { @@ -344,7 +336,7 @@ class RuleRepository implements RuleRepositoryInterface return; } - $trigger = new RuleTrigger; + $trigger = new RuleTrigger(); $trigger->order = 0; $trigger->trigger_type = 'user_action'; $trigger->trigger_value = $moment; @@ -355,7 +347,7 @@ class RuleRepository implements RuleRepositoryInterface } /** - * @param RuleGroup $ruleGroup + * @param RuleGroup $ruleGroup * * @return bool */ @@ -368,13 +360,21 @@ class RuleRepository implements RuleRepositoryInterface return true; } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + /** * @inheritDoc */ public function setOrder(Rule $rule, int $newOrder): void { - $oldOrder = (int) $rule->order; - $groupId = (int) $rule->rule_group_id; + $oldOrder = (int)$rule->order; + $groupId = (int)$rule->rule_group_id; $maxOrder = $this->maxOrder($rule->ruleGroup); $newOrder = $newOrder > $maxOrder ? $maxOrder + 1 : $newOrder; Log::debug(sprintf('New order will be %d', $newOrder)); @@ -409,12 +409,12 @@ class RuleRepository implements RuleRepositoryInterface */ public function maxOrder(RuleGroup $ruleGroup): int { - return (int) $ruleGroup->rules()->max('order'); + return (int)$ruleGroup->rules()->max('order'); } /** - * @param Rule $rule - * @param array $data + * @param Rule $rule + * @param array $data * * @return void */ @@ -425,9 +425,13 @@ class RuleRepository implements RuleRepositoryInterface $value = $trigger['value'] ?? ''; $stopProcessing = $trigger['stop_processing'] ?? false; $active = $trigger['active'] ?? true; + $type = $trigger['type']; + if (true === $trigger['prohibited']) { + $type = sprintf('-%s', $type); + } $triggerValues = [ - 'action' => $trigger['type'], + 'action' => $type, 'value' => $value, 'stop_processing' => $stopProcessing, 'order' => $order, @@ -436,18 +440,17 @@ class RuleRepository implements RuleRepositoryInterface $this->storeTrigger($rule, $triggerValues); ++$order; } - } /** - * @param Rule $rule - * @param array $values + * @param Rule $rule + * @param array $values * * @return RuleTrigger */ public function storeTrigger(Rule $rule, array $values): RuleTrigger { - $ruleTrigger = new RuleTrigger; + $ruleTrigger = new RuleTrigger(); $ruleTrigger->rule()->associate($rule); $ruleTrigger->order = $values['order']; $ruleTrigger->active = $values['active']; @@ -460,8 +463,8 @@ class RuleRepository implements RuleRepositoryInterface } /** - * @param Rule $rule - * @param array $data + * @param Rule $rule + * @param array $data * * @return void */ @@ -482,18 +485,17 @@ class RuleRepository implements RuleRepositoryInterface $this->storeAction($rule, $actionValues); ++$order; } - } /** - * @param Rule $rule - * @param array $values + * @param Rule $rule + * @param array $values * * @return RuleAction */ public function storeAction(Rule $rule, array $values): RuleAction { - $ruleAction = new RuleAction; + $ruleAction = new RuleAction(); $ruleAction->rule()->associate($rule); $ruleAction->order = $values['order']; $ruleAction->active = $values['active']; @@ -506,8 +508,8 @@ class RuleRepository implements RuleRepositoryInterface } /** - * @param Rule $rule - * @param array $data + * @param Rule $rule + * @param array $data * * @return Rule */ @@ -533,7 +535,7 @@ class RuleRepository implements RuleRepositoryInterface // update the order: $this->resetRuleOrder($group); if (array_key_exists('order', $data)) { - $this->moveRule($rule, $group, (int) $data['order']); + $this->moveRule($rule, $group, (int)$data['order']); } diff --git a/app/Repositories/Rule/RuleRepositoryInterface.php b/app/Repositories/Rule/RuleRepositoryInterface.php index 0fc7c4bf5e..5f2577737e 100644 --- a/app/Repositories/Rule/RuleRepositoryInterface.php +++ b/app/Repositories/Rule/RuleRepositoryInterface.php @@ -1,4 +1,5 @@ user->ruleGroups()->orderBy('order', 'ASC')->get(); + } + /** * @return int */ @@ -70,8 +79,8 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param RuleGroup $ruleGroup - * @param RuleGroup|null $moveTo + * @param RuleGroup $ruleGroup + * @param RuleGroup|null $moveTo * * @return bool * @throws Exception @@ -128,7 +137,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param RuleGroup $ruleGroup + * @param RuleGroup $ruleGroup * * @return bool */ @@ -142,7 +151,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface $count = 1; /** @var Rule $entry */ foreach ($set as $entry) { - if ((int) $entry->order !== $count) { + if ((int)$entry->order !== $count) { Log::debug(sprintf('Rule #%d was on spot %d but must be on spot %d', $entry->id, $entry->order, $count)); $entry->order = $count; $entry->save(); @@ -157,7 +166,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param Rule $rule + * @param Rule $rule */ private function resetRuleActionOrder(Rule $rule): void { @@ -169,7 +178,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface $index = 1; /** @var RuleAction $action */ foreach ($actions as $action) { - if ((int) $action->order !== $index) { + if ((int)$action->order !== $index) { $action->order = $index; $action->save(); Log::debug(sprintf('Rule action #%d was on spot %d but must be on spot %d', $action->id, $action->order, $index)); @@ -179,7 +188,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param Rule $rule + * @param Rule $rule */ private function resetRuleTriggerOrder(Rule $rule): void { @@ -191,7 +200,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface $index = 1; /** @var RuleTrigger $trigger */ foreach ($triggers as $trigger) { - $order = (int) $trigger->order; + $order = (int)$trigger->order; if ($order !== $index) { $trigger->order = $index; $trigger->save(); @@ -215,15 +224,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @return Collection - */ - public function get(): Collection - { - return $this->user->ruleGroups()->orderBy('order', 'ASC')->get(); - } - - /** - * @param int $ruleGroupId + * @param int $ruleGroupId * * @return RuleGroup|null */ @@ -233,7 +234,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param string $title + * @param string $title * * @return RuleGroup|null */ @@ -251,7 +252,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param RuleGroup $group + * @param RuleGroup $group * * @return Collection */ @@ -263,7 +264,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param RuleGroup $group + * @param RuleGroup $group * * @return Collection */ @@ -278,7 +279,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param RuleGroup $group + * @param RuleGroup $group * * @return Collection */ @@ -293,7 +294,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param string|null $filter + * @param string|null $filter * * @return Collection */ @@ -351,11 +352,11 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface { $entry = $this->user->ruleGroups()->max('order'); - return (int) $entry; + return (int)$entry; } /** - * @param string|null $filter + * @param string|null $filter * * @return Collection */ @@ -408,7 +409,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param RuleGroup $group + * @param RuleGroup $group * * @return Collection */ @@ -423,7 +424,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface */ public function maxOrder(): int { - return (int) $this->user->ruleGroups()->where('active', true)->max('order'); + return (int)$this->user->ruleGroups()->where('active', true)->max('order'); } /** @@ -442,7 +443,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { @@ -450,7 +451,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param array $data + * @param array $data * * @return RuleGroup */ @@ -479,7 +480,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface */ public function setOrder(RuleGroup $ruleGroup, int $newOrder): void { - $oldOrder = (int) $ruleGroup->order; + $oldOrder = (int)$ruleGroup->order; if ($newOrder > $oldOrder) { $this->user->ruleGroups()->where('rule_groups.order', '<=', $newOrder)->where('rule_groups.order', '>', $oldOrder) @@ -501,8 +502,8 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface } /** - * @param RuleGroup $ruleGroup - * @param array $data + * @param RuleGroup $ruleGroup + * @param array $data * * @return RuleGroup */ @@ -521,7 +522,7 @@ class RuleGroupRepository implements RuleGroupRepositoryInterface // order if (array_key_exists('order', $data) && $ruleGroup->order !== $data['order']) { $this->resetOrder(); - $this->setOrder($ruleGroup, (int) $data['order']); + $this->setOrder($ruleGroup, (int)$data['order']); } $ruleGroup->save(); diff --git a/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php b/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php index 06f8e329a3..f2fa871fde 100644 --- a/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php +++ b/app/Repositories/RuleGroup/RuleGroupRepositoryInterface.php @@ -1,4 +1,5 @@ [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'tags' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // may have multiple tags: foreach ($journal['tags'] as $tag) { - $tagId = (int) $tag['id']; - $tagName = (string) $tag['name']; - $journalId = (int) $journal['transaction_journal_id']; + $tagId = (int)$tag['id']; + $tagName = (string)$tag['name']; + $journalId = (int)$journal['transaction_journal_id']; if (in_array($journalId, $listedJournals, true)) { continue; } $listedJournals[] = $journalId; $array[$currencyId]['tags'][$tagId] = $array[$currencyId]['tags'][$tagId] ?? [ - 'id' => $tagId, - 'name' => $tagName, - 'transaction_journals' => [], - ]; + 'id' => $tagId, + 'name' => $tagName, + 'transaction_journals' => [], + ]; $array[$currencyId]['tags'][$tagId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->negative($journal['amount']), @@ -114,10 +116,18 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + /** * @return Collection - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function getTags(): Collection { @@ -131,10 +141,10 @@ class OperationsRepository implements OperationsRepositoryInterface * which have the specified tag(s) set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $tags + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $tags * * @return array */ @@ -158,21 +168,21 @@ class OperationsRepository implements OperationsRepositoryInterface $listedJournals = []; foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $array[$currencyId] = $array[$currencyId] ?? [ - 'tags' => [], - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_code' => $journal['currency_code'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - ]; + 'tags' => [], + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_code' => $journal['currency_code'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + ]; // may have multiple tags: foreach ($journal['tags'] as $tag) { - $tagId = (int) $tag['id']; - $tagName = (string) $tag['name']; - $journalId = (int) $journal['transaction_journal_id']; + $tagId = (int)$tag['id']; + $tagName = (string)$tag['name']; + $journalId = (int)$journal['transaction_journal_id']; if (in_array($journalId, $listedJournals, true)) { continue; @@ -180,11 +190,11 @@ class OperationsRepository implements OperationsRepositoryInterface $listedJournals[] = $journalId; $array[$currencyId]['tags'][$tagId] = $array[$currencyId]['tags'][$tagId] ?? [ - 'id' => $tagId, - 'name' => $tagName, - 'transaction_journals' => [], - ]; - $journalId = (int) $journal['transaction_journal_id']; + 'id' => $tagId, + 'name' => $tagName, + 'transaction_journals' => [], + ]; + $journalId = (int)$journal['transaction_journal_id']; $array[$currencyId]['tags'][$tagId]['transaction_journals'][$journalId] = [ 'amount' => app('steam')->positive($journal['amount']), 'date' => $journal['date'], @@ -202,21 +212,13 @@ class OperationsRepository implements OperationsRepositoryInterface return $array; } - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - /** * Sum of withdrawal journals in period for a set of tags, grouped per currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $tags + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $tags * * @return array * @throws FireflyException @@ -229,10 +231,10 @@ class OperationsRepository implements OperationsRepositoryInterface /** * Sum of income journals in period for a set of tags, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $tags + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $tags * * @return array * @throws FireflyException diff --git a/app/Repositories/Tag/OperationsRepositoryInterface.php b/app/Repositories/Tag/OperationsRepositoryInterface.php index bb254c841b..f5f6dd09b1 100644 --- a/app/Repositories/Tag/OperationsRepositoryInterface.php +++ b/app/Repositories/Tag/OperationsRepositoryInterface.php @@ -39,10 +39,10 @@ interface OperationsRepositoryInterface * which have the specified tag(s) set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $tags + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $tags * * @return array */ @@ -53,27 +53,27 @@ interface OperationsRepositoryInterface * which have the specified tag(s) set to them. It's grouped per currency, with as few details in the array * as possible. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $tags + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $tags * * @return array */ public function listIncome(Carbon $start, Carbon $end, ?Collection $accounts = null, ?Collection $tags = null): array; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** * Sum of withdrawal journals in period for a set of tags, grouped per currency. Amounts are always negative. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $tags + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $tags * * @return array */ @@ -82,10 +82,10 @@ interface OperationsRepositoryInterface /** * Sum of income journals in period for a set of tags, grouped per currency. Amounts are always positive. * - * @param Carbon $start - * @param Carbon $end - * @param Collection|null $accounts - * @param Collection|null $tags + * @param Carbon $start + * @param Carbon $end + * @param Collection|null $accounts + * @param Collection|null $tags * * @return array */ diff --git a/app/Repositories/Tag/TagRepository.php b/app/Repositories/Tag/TagRepository.php index aa65cb596e..8e37750467 100644 --- a/app/Repositories/Tag/TagRepository.php +++ b/app/Repositories/Tag/TagRepository.php @@ -1,4 +1,5 @@ user = $user; + } + + /** + * @param int $tagId * * @return Tag|null */ @@ -118,7 +127,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param string $tag + * @param string $tag * * @return Tag|null */ @@ -128,7 +137,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag + * @param Tag $tag * * @return Carbon|null */ @@ -163,7 +172,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param int|null $year + * @param int|null $year * * @return array */ @@ -180,7 +189,7 @@ class TagRepository implements TagRepositoryInterface if (null !== $year) { Log::debug(sprintf('Get tags with year %s.', $year)); - $tagQuery->where('tags.date', '>=', $year . '-01-01 00:00:00')->where('tags.date', '<=', $year . '-12-31 23:59:59'); + $tagQuery->where('tags.date', '>=', $year.'-01-01 00:00:00')->where('tags.date', '<=', $year.'-12-31 23:59:59'); } $collection = $tagQuery->get(); $return = []; @@ -200,9 +209,9 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag - * @param Carbon $start - * @param Carbon $end + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -218,7 +227,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag + * @param Tag $tag * * @return Carbon|null */ @@ -253,7 +262,7 @@ class TagRepository implements TagRepositoryInterface /** * Find one or more tags based on the query. * - * @param string $query + * @param string $query * * @return Collection */ @@ -267,8 +276,8 @@ class TagRepository implements TagRepositoryInterface /** * Search the users tags. * - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ @@ -285,15 +294,7 @@ class TagRepository implements TagRepositoryInterface } /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param array $data + * @param array $data * * @return Tag */ @@ -307,9 +308,9 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag - * @param Carbon|null $start - * @param Carbon|null $end + * @param Tag $tag + * @param Carbon|null $start + * @param Carbon|null $end * * @return array * @@ -330,21 +331,21 @@ class TagRepository implements TagRepositoryInterface /** @var array $journal */ foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $sums[$currencyId] = $sums[$currencyId] ?? [ - 'currency_id' => $currencyId, - 'currency_name' => $journal['currency_name'], - 'currency_symbol' => $journal['currency_symbol'], - 'currency_decimal_places' => $journal['currency_decimal_places'], - TransactionType::WITHDRAWAL => '0', - TransactionType::DEPOSIT => '0', - TransactionType::TRANSFER => '0', - TransactionType::RECONCILIATION => '0', - TransactionType::OPENING_BALANCE => '0', - ]; + 'currency_id' => $currencyId, + 'currency_name' => $journal['currency_name'], + 'currency_symbol' => $journal['currency_symbol'], + 'currency_decimal_places' => $journal['currency_decimal_places'], + TransactionType::WITHDRAWAL => '0', + TransactionType::DEPOSIT => '0', + TransactionType::TRANSFER => '0', + TransactionType::RECONCILIATION => '0', + TransactionType::OPENING_BALANCE => '0', + ]; // add amount to correct type: - $amount = app('steam')->positive((string) $journal['amount']); + $amount = app('steam')->positive((string)$journal['amount']); $type = $journal['transaction_type_type']; if (TransactionType::WITHDRAWAL === $type) { $amount = bcmul($amount, '-1'); @@ -354,24 +355,23 @@ class TagRepository implements TagRepositoryInterface $foreignCurrencyId = $journal['foreign_currency_id']; if (null !== $foreignCurrencyId && 0 !== $foreignCurrencyId) { $sums[$foreignCurrencyId] = $sums[$foreignCurrencyId] ?? [ - 'currency_id' => $foreignCurrencyId, - 'currency_name' => $journal['foreign_currency_name'], - 'currency_symbol' => $journal['foreign_currency_symbol'], - 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], - TransactionType::WITHDRAWAL => '0', - TransactionType::DEPOSIT => '0', - TransactionType::TRANSFER => '0', - TransactionType::RECONCILIATION => '0', - TransactionType::OPENING_BALANCE => '0', - ]; + 'currency_id' => $foreignCurrencyId, + 'currency_name' => $journal['foreign_currency_name'], + 'currency_symbol' => $journal['foreign_currency_symbol'], + 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], + TransactionType::WITHDRAWAL => '0', + TransactionType::DEPOSIT => '0', + TransactionType::TRANSFER => '0', + TransactionType::RECONCILIATION => '0', + TransactionType::OPENING_BALANCE => '0', + ]; // add foreign amount to correct type: - $amount = app('steam')->positive((string) $journal['foreign_amount']); + $amount = app('steam')->positive((string)$journal['foreign_amount']); $type = $journal['transaction_type_type']; if (TransactionType::WITHDRAWAL === $type) { $amount = bcmul($amount, '-1'); } $sums[$foreignCurrencyId][$type] = bcadd($sums[$foreignCurrencyId][$type], $amount); - } } @@ -379,9 +379,9 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag - * @param Carbon $start - * @param Carbon $end + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -396,8 +396,8 @@ class TagRepository implements TagRepositoryInterface } /** - * @param Tag $tag - * @param array $data + * @param Tag $tag + * @param array $data * * @return Tag */ @@ -433,7 +433,7 @@ class TagRepository implements TagRepositoryInterface if (!(null === $data['latitude'] && null === $data['longitude'] && null === $data['zoom_level'])) { $location = $this->getLocation($tag); if (null === $location) { - $location = new Location; + $location = new Location(); $location->locatable()->associate($tag); } @@ -457,5 +457,4 @@ class TagRepository implements TagRepositoryInterface { return $tag->locations()->first(); } - } diff --git a/app/Repositories/Tag/TagRepositoryInterface.php b/app/Repositories/Tag/TagRepositoryInterface.php index 1a546821b3..0a5bbd76cc 100644 --- a/app/Repositories/Tag/TagRepositoryInterface.php +++ b/app/Repositories/Tag/TagRepositoryInterface.php @@ -1,4 +1,5 @@ user->transactionJournals()->find($journalId); return $journal->attachments()->count(); - } /** - * @param TransactionGroup $group + * Find a transaction group by its ID. + * + * @param int $groupId + * + * @return TransactionGroup|null + */ + public function find(int $groupId): ?TransactionGroup + { + return $this->user->transactionGroups()->find($groupId); + } + + /** + * @param TransactionGroup $group */ public function destroy(TransactionGroup $group): void { - $service = new TransactionGroupDestroyService; + Log::debug(sprintf('Now in %s', __METHOD__)); + $service = new TransactionGroupDestroyService(); $service->destroy($group); } @@ -93,7 +106,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return array */ @@ -120,7 +133,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface } /** - * @param Transaction $transaction + * @param Transaction $transaction * * @return array */ @@ -142,22 +155,10 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface return $array; } - /** - * Find a transaction group by its ID. - * - * @param int $groupId - * - * @return TransactionGroup|null - */ - public function find(int $groupId): ?TransactionGroup - { - return $this->user->transactionGroups()->find($groupId); - } - /** * Return all attachments for all journals in the group. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return array */ @@ -174,23 +175,51 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface $result = []; /** @var Attachment $attachment */ foreach ($set as $attachment) { - $journalId = (int) $attachment->attachable_id; + $journalId = (int)$attachment->attachable_id; $result[$journalId] = $result[$journalId] ?? []; $current = $attachment->toArray(); $current['file_exists'] = true; $current['notes'] = $repository->getNoteText($attachment); + // already determined that this attachable is a TransactionJournal. $current['journal_title'] = $attachment->attachable->description; // @phpstan-ignore-line $result[$journalId][] = $current; - } return $result; } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * Get the note text for a journal (by ID). + * + * @param int $journalId + * + * @return string|null + */ + public function getNoteText(int $journalId): ?string + { + /** @var Note|null $note */ + $note = Note::where('noteable_id', $journalId) + ->where('noteable_type', TransactionJournal::class) + ->first(); + if (null === $note) { + return null; + } + + return $note->text; + } + /** * Return all journal links for all journals in the group. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return array */ @@ -198,21 +227,22 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface { $return = []; $journals = $group->transactionJournals->pluck('id')->toArray(); - $set = TransactionJournalLink - ::where( - static function (Builder $q) use ($journals) { - $q->whereIn('source_id', $journals); - $q->orWhereIn('destination_id', $journals); - } - ) - ->with(['source', 'destination', 'source.transactions']) - ->leftJoin('link_types', 'link_types.id', '=', 'journal_links.link_type_id') - ->get(['journal_links.*', 'link_types.inward', 'link_types.outward', 'link_types.editable']); + $set = TransactionJournalLink::where( + static function (Builder $q) use ($journals) { + $q->whereIn('source_id', $journals); + $q->orWhereIn('destination_id', $journals); + } + ) + ->with(['source', 'destination', 'source.transactions']) + ->leftJoin('link_types', 'link_types.id', '=', 'journal_links.link_type_id') + ->get(['journal_links.*', 'link_types.inward', 'link_types.outward', 'link_types.editable']); /** @var TransactionJournalLink $entry */ foreach ($set as $entry) { $journalId = in_array($entry->source_id, $journals, true) ? $entry->source_id : $entry->destination_id; $return[$journalId] = $return[$journalId] ?? []; + // phpstan: the editable field is provided by the query. + if ($journalId === $entry->source_id) { $amount = $this->getFormattedAmount($entry->destination); $foreignAmount = $this->getFormattedForeignAmount($entry->destination); @@ -221,7 +251,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface 'link' => $entry->outward, 'group' => $entry->destination->transaction_group_id, 'description' => $entry->destination->description, - 'editable' => 1 === $entry->editable, + 'editable' => 1 === (int)$entry->editable, // @phpstan-ignore-line 'amount' => $amount, 'foreign_amount' => $foreignAmount, ]; @@ -234,7 +264,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface 'link' => $entry->inward, 'group' => $entry->source->transaction_group_id, 'description' => $entry->source->description, - 'editable' => 1 === $entry->editable, + 'editable' => 1 === (int)$entry->editable, // @phpstan-ignore-line 'amount' => $amount, 'foreign_amount' => $foreignAmount, ]; @@ -245,7 +275,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return string */ @@ -262,14 +292,13 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface } if (TransactionType::WITHDRAWAL !== $type) { $return = app('amount')->formatAnything($currency, $amount); - } return $return; } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return string */ @@ -311,20 +340,19 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface /** * Return object with all found meta field things as Carbon objects. * - * @param int $journalId - * @param array $fields + * @param int $journalId + * @param array $fields * * @return NullArrayObject * @throws Exception */ public function getMetaDateFields(int $journalId, array $fields): NullArrayObject { - $query = DB - ::table('journal_meta') - ->where('transaction_journal_id', $journalId) - ->whereIn('name', $fields) - ->whereNull('deleted_at') - ->get(['name', 'data']); + $query = DB::table('journal_meta') + ->where('transaction_journal_id', $journalId) + ->whereIn('name', $fields) + ->whereNull('deleted_at') + ->get(['name', 'data']); $return = []; foreach ($query as $row) { @@ -337,19 +365,18 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface /** * Return object with all found meta field things. * - * @param int $journalId - * @param array $fields + * @param int $journalId + * @param array $fields * * @return NullArrayObject */ public function getMetaFields(int $journalId, array $fields): NullArrayObject { - $query = DB - ::table('journal_meta') - ->where('transaction_journal_id', $journalId) - ->whereIn('name', $fields) - ->whereNull('deleted_at') - ->get(['name', 'data']); + $query = DB::table('journal_meta') + ->where('transaction_journal_id', $journalId) + ->whereIn('name', $fields) + ->whereNull('deleted_at') + ->get(['name', 'data']); $return = []; foreach ($query as $row) { @@ -359,55 +386,32 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface return new NullArrayObject($return); } - /** - * Get the note text for a journal (by ID). - * - * @param int $journalId - * - * @return string|null - */ - public function getNoteText(int $journalId): ?string - { - /** @var Note|null $note */ - $note = Note - ::where('noteable_id', $journalId) - ->where('noteable_type', TransactionJournal::class) - ->first(); - if (null === $note) { - return null; - } - - return $note->text; - } - /** * Return all piggy bank events for all journals in the group. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return array * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ public function getPiggyEvents(TransactionGroup $group): array { $return = []; $journals = $group->transactionJournals->pluck('id')->toArray(); $currency = app('amount')->getDefaultCurrencyByUser($this->user); - $data = PiggyBankEvent - ::whereIn('transaction_journal_id', $journals) - ->with('piggyBank', 'piggyBank.account') - ->get(['piggy_bank_events.*']); + $data = PiggyBankEvent::whereIn('transaction_journal_id', $journals) + ->with('piggyBank', 'piggyBank.account') + ->get(['piggy_bank_events.*']); /** @var PiggyBankEvent $row */ foreach ($data as $row) { if (null === $row->piggyBank) { continue; } // get currency preference. - $currencyPreference = AccountMeta - ::where('account_id', $row->piggyBank->account_id) - ->where('name', 'currency_id') - ->first(); + $currencyPreference = AccountMeta::where('account_id', $row->piggyBank->account_id) + ->where('name', 'currency_id') + ->first(); if (null !== $currencyPreference) { $currency = TransactionCurrency::where('id', $currencyPreference->data)->first(); } @@ -415,7 +419,7 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface $currencyCode = app('preferences')->getForUser($this->user, 'currencyPreference', 'EUR')->data; $currency = TransactionCurrency::where('code', $currencyCode)->first(); } - $journalId = (int) $row->transaction_journal_id; + $journalId = (int)$row->transaction_journal_id; $return[$journalId] = $return[$journalId] ?? []; $return[$journalId][] = [ @@ -442,32 +446,23 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface /** * Get the tags for a journal (by ID). * - * @param int $journalId + * @param int $journalId * * @return array */ public function getTags(int $journalId): array { - $result = DB - ::table('tag_transaction_journal') - ->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id') - ->where('tag_transaction_journal.transaction_journal_id', $journalId) - ->orderBy('tags.tag', 'ASC') - ->get(['tags.tag']); + $result = DB::table('tag_transaction_journal') + ->leftJoin('tags', 'tag_transaction_journal.tag_id', '=', 'tags.id') + ->where('tag_transaction_journal.transaction_journal_id', $journalId) + ->orderBy('tags.tag', 'ASC') + ->get(['tags.tag']); return $result->pluck('tag')->toArray(); } /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - - /** - * @param array $data + * @param array $data * * @return TransactionGroup * @throws DuplicateTransactionException @@ -481,10 +476,10 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface try { return $factory->create($data); } catch (DuplicateTransactionException $e) { - Log::warning('Group repository caught group factory with a duplicate exception!'); + app('log')->warning('Group repository caught group factory with a duplicate exception!'); throw new DuplicateTransactionException($e->getMessage(), 0, $e); } catch (FireflyException $e) { - Log::warning('Group repository caught group factory with an exception!'); + app('log')->warning('Group repository caught group factory with an exception!'); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); throw new FireflyException($e->getMessage(), 0, $e); @@ -492,8 +487,8 @@ class TransactionGroupRepository implements TransactionGroupRepositoryInterface } /** - * @param TransactionGroup $transactionGroup - * @param array $data + * @param TransactionGroup $transactionGroup + * @param array $data * * @return TransactionGroup * diff --git a/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php b/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php index fed0bca69c..36a1186d4c 100644 --- a/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php +++ b/app/Repositories/TransactionGroup/TransactionGroupRepositoryInterface.php @@ -37,21 +37,21 @@ use Illuminate\Support\Collection; interface TransactionGroupRepositoryInterface { /** - * @param int $journalId + * @param int $journalId * * @return int */ public function countAttachments(int $journalId): int; /** - * @param TransactionGroup $group + * @param TransactionGroup $group */ public function destroy(TransactionGroup $group): void; /** * Return a group and expand all meta data etc. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return array */ @@ -60,7 +60,7 @@ interface TransactionGroupRepositoryInterface /** * Find a transaction group by its ID. * - * @param int $groupId + * @param int $groupId * * @return TransactionGroup|null */ @@ -69,7 +69,7 @@ interface TransactionGroupRepositoryInterface /** * Return all attachments for all journals in the group. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return array */ @@ -78,7 +78,7 @@ interface TransactionGroupRepositoryInterface /** * Return all journal links for all journals in the group. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return array */ @@ -87,7 +87,7 @@ interface TransactionGroupRepositoryInterface /** * Get the location of a journal or NULL. * - * @param int $journalId + * @param int $journalId * * @return Location|null */ @@ -96,8 +96,8 @@ interface TransactionGroupRepositoryInterface /** * Return object with all found meta field things as Carbon objects. * - * @param int $journalId - * @param array $fields + * @param int $journalId + * @param array $fields * * @return NullArrayObject */ @@ -106,8 +106,8 @@ interface TransactionGroupRepositoryInterface /** * Return object with all found meta field things. * - * @param int $journalId - * @param array $fields + * @param int $journalId + * @param array $fields * * @return NullArrayObject */ @@ -116,7 +116,7 @@ interface TransactionGroupRepositoryInterface /** * Get the note text for a journal (by ID). * - * @param int $journalId + * @param int $journalId * * @return string|null */ @@ -125,7 +125,7 @@ interface TransactionGroupRepositoryInterface /** * Return all piggy bank events for all journals in the group. * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return array */ @@ -134,7 +134,7 @@ interface TransactionGroupRepositoryInterface /** * Get the tags for a journal (by ID) as Tag objects. * - * @param int $journalId + * @param int $journalId * * @return Collection */ @@ -143,7 +143,7 @@ interface TransactionGroupRepositoryInterface /** * Get the tags for a journal (by ID). * - * @param int $journalId + * @param int $journalId * * @return array */ @@ -152,14 +152,14 @@ interface TransactionGroupRepositoryInterface /** * Set the user. * - * @param User $user + * @param User $user */ public function setUser(User $user): void; /** * Create a new transaction group. * - * @param array $data + * @param array $data * * @return TransactionGroup * @throws DuplicateTransactionException @@ -170,11 +170,10 @@ interface TransactionGroupRepositoryInterface /** * Update an existing transaction group. * - * @param TransactionGroup $transactionGroup - * @param array $data + * @param TransactionGroup $transactionGroup + * @param array $data * * @return TransactionGroup */ public function update(TransactionGroup $transactionGroup, array $data): TransactionGroup; - } diff --git a/app/Repositories/TransactionType/TransactionTypeRepository.php b/app/Repositories/TransactionType/TransactionTypeRepository.php index 68db902f6f..40f8edb19b 100644 --- a/app/Repositories/TransactionType/TransactionTypeRepository.php +++ b/app/Repositories/TransactionType/TransactionTypeRepository.php @@ -32,10 +32,9 @@ use Log; */ class TransactionTypeRepository implements TransactionTypeRepositoryInterface { - /** - * @param TransactionType|null $type - * @param string|null $typeString + * @param TransactionType|null $type + * @param string|null $typeString * * @return TransactionType */ @@ -58,7 +57,7 @@ class TransactionTypeRepository implements TransactionTypeRepositoryInterface } /** - * @param string $type + * @param string $type * * @return TransactionType|null */ @@ -70,8 +69,8 @@ class TransactionTypeRepository implements TransactionTypeRepositoryInterface } /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ diff --git a/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php b/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php index ff4c4b296f..f0a1e4c19a 100644 --- a/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php +++ b/app/Repositories/TransactionType/TransactionTypeRepositoryInterface.php @@ -32,23 +32,23 @@ use Illuminate\Support\Collection; interface TransactionTypeRepositoryInterface { /** - * @param string $type + * @param string $type * * @return TransactionType|null */ public function findByType(string $type): ?TransactionType; /** - * @param TransactionType|null $type - * @param string|null $typeString + * @param TransactionType|null $type + * @param string|null $typeString * * @return TransactionType */ public function findTransactionType(?TransactionType $type, ?string $typeString): TransactionType; /** - * @param string $query - * @param int $limit + * @param string $query + * @param int $limit * * @return Collection */ diff --git a/app/Repositories/User/UserRepository.php b/app/Repositories/User/UserRepository.php index d841a6bc46..3a49eb1893 100644 --- a/app/Repositories/User/UserRepository.php +++ b/app/Repositories/User/UserRepository.php @@ -1,4 +1,5 @@ setForUser($user, 'previous_email_latest', $oldEmail); - app('preferences')->setForUser($user, 'previous_email_' . date('Y-m-d-H-i-s'), $oldEmail); + app('preferences')->setForUser($user, 'previous_email_'.date('Y-m-d-H-i-s'), $oldEmail); // set undo and confirm token: app('preferences')->setForUser($user, 'email_change_undo_token', bin2hex(random_bytes(16))); @@ -73,8 +76,8 @@ class UserRepository implements UserRepositoryInterface } /** - * @param User $user - * @param string $password + * @param User $user + * @param string $password * * @return bool */ @@ -87,9 +90,9 @@ class UserRepository implements UserRepositoryInterface } /** - * @param User $user - * @param bool $isBlocked - * @param string $code + * @param User $user + * @param bool $isBlocked + * @param string $code * * @return bool */ @@ -104,25 +107,9 @@ class UserRepository implements UserRepositoryInterface } /** - * @return int - */ - public function count(): int - { - return $this->all()->count(); - } - - /** - * @return Collection - */ - public function all(): Collection - { - return User::orderBy('id', 'DESC')->get(['users.*']); - } - - /** - * @param string $name - * @param string $displayName - * @param string $description + * @param string $name + * @param string $displayName + * @param string $description * * @return Role */ @@ -132,7 +119,7 @@ class UserRepository implements UserRepositoryInterface } /** - * @param User $user + * @param User $user * * @return bool * @throws Exception @@ -165,7 +152,23 @@ class UserRepository implements UserRepositoryInterface } /** - * @param int $userId + * @return int + */ + public function count(): int + { + return $this->all()->count(); + } + + /** + * @return Collection + */ + public function all(): Collection + { + return User::orderBy('id', 'DESC')->get(['users.*']); + } + + /** + * @param int $userId * * @return User|null */ @@ -175,7 +178,7 @@ class UserRepository implements UserRepositoryInterface } /** - * @param string $email + * @param string $email * * @return User|null */ @@ -195,7 +198,15 @@ class UserRepository implements UserRepositoryInterface } /** - * @param User $user + * @inheritDoc + */ + public function getInvitedUsers(): Collection + { + return InvitedUser::with('user')->get(); + } + + /** + * @param User $user * * @return string|null */ @@ -213,7 +224,7 @@ class UserRepository implements UserRepositoryInterface /** * Return basic user information. * - * @param User $user + * @param User $user * * @return array */ @@ -224,7 +235,7 @@ class UserRepository implements UserRepositoryInterface // two factor: $return['has_2fa'] = $user->mfa_secret !== null; $return['is_admin'] = $this->hasRole($user, 'owner'); - $return['blocked'] = 1 === (int) $user->blocked; + $return['blocked'] = 1 === (int)$user->blocked; $return['blocked_code'] = $user->blocked_code; $return['accounts'] = $user->accounts()->count(); $return['journals'] = $user->transactionJournals()->count(); @@ -248,8 +259,8 @@ class UserRepository implements UserRepositoryInterface } /** - * @param User $user - * @param string $role + * @param User $user + * @param string $role * * @return bool */ @@ -265,11 +276,41 @@ class UserRepository implements UserRepositoryInterface return false; } + /** + * @inheritDoc + */ + public function inviteUser(User $user, string $email): InvitedUser + { + $now = Carbon::now(); + $now->addDays(2); + $invitee = new InvitedUser(); + $invitee->user()->associate($user); + $invitee->invite_code = Str::random(64); + $invitee->email = $email; + $invitee->redeemed = false; + $invitee->expires = $now; + $invitee->save(); + + return $invitee; + } + + /** + * @inheritDoc + */ + public function redeemCode(string $code): void + { + $obj = InvitedUser::where('invite_code', $code)->where('redeemed', 0)->first(); + if ($obj) { + $obj->redeemed = true; + $obj->save(); + } + } + /** * Set MFA code. * - * @param User $user - * @param string|null $code + * @param User $user + * @param string|null $code */ public function setMFACode(User $user, ?string $code): void { @@ -278,7 +319,7 @@ class UserRepository implements UserRepositoryInterface } /** - * @param array $data + * @param array $data * * @return User */ @@ -301,8 +342,8 @@ class UserRepository implements UserRepositoryInterface } /** - * @param User $user - * @param string $role + * @param User $user + * @param string $role * * @return bool */ @@ -326,21 +367,20 @@ class UserRepository implements UserRepositoryInterface } /** - * @param User $user + * @param User $user */ public function unblockUser(User $user): void { $user->blocked = false; $user->blocked_code = ''; $user->save(); - } /** * Update user info. * - * @param User $user - * @param array $data + * @param User $user + * @param array $data * * @return User * @throws FireflyException @@ -368,8 +408,8 @@ class UserRepository implements UserRepositoryInterface * This updates the users email address. Same as changeEmail just without most logging. This makes sure that the undo/confirm routine can't catch this one. * The user is NOT blocked. * - * @param User $user - * @param string $newEmail + * @param User $user + * @param string $newEmail * * @return bool * @throws FireflyException @@ -384,7 +424,7 @@ class UserRepository implements UserRepositoryInterface // save old email as pref app('preferences')->setForUser($user, 'admin_previous_email_latest', $oldEmail); - app('preferences')->setForUser($user, 'admin_previous_email_' . date('Y-m-d-H-i-s'), $oldEmail); + app('preferences')->setForUser($user, 'admin_previous_email_'.date('Y-m-d-H-i-s'), $oldEmail); $user->email = $newEmail; $user->save(); @@ -395,8 +435,8 @@ class UserRepository implements UserRepositoryInterface /** * Remove any role the user has. * - * @param User $user - * @param string $role + * @param User $user + * @param string $role */ public function removeRole(User $user, string $role): void { @@ -408,7 +448,7 @@ class UserRepository implements UserRepositoryInterface } /** - * @param string $role + * @param string $role * * @return Role|null */ @@ -416,4 +456,14 @@ class UserRepository implements UserRepositoryInterface { return Role::where('name', $role)->first(); } + + /** + * @inheritDoc + */ + public function validateInviteCode(string $code): bool + { + $now = Carbon::now(); + $invitee = InvitedUser::where('invite_code', $code)->where('expires', '>', $now->format('Y-m-d H:i:s'))->where('redeemed', 0)->first(); + return null !== $invitee; + } } diff --git a/app/Repositories/User/UserRepositoryInterface.php b/app/Repositories/User/UserRepositoryInterface.php index 410162b2e4..cd5aeb4f24 100644 --- a/app/Repositories/User/UserRepositoryInterface.php +++ b/app/Repositories/User/UserRepositoryInterface.php @@ -1,4 +1,5 @@ check()) { return true; } - $attribute = (string) $attribute; + $attribute = (string)$attribute; Log::debug(sprintf('Going to validate %s', $attribute)); return match ($attribute) { - 'piggy_bank_id' => $this->validatePiggyBankId((int) $value), + 'piggy_bank_id' => $this->validatePiggyBankId((int)$value), 'piggy_bank_name' => $this->validatePiggyBankName($value), - 'bill_id' => $this->validateBillId((int) $value), - 'transaction_journal_id' => $this->validateJournalId((int) $value), + 'bill_id' => $this->validateBillId((int)$value), + 'transaction_journal_id' => $this->validateJournalId((int)$value), 'bill_name' => $this->validateBillName($value), - 'budget_id' => $this->validateBudgetId((int) $value), - 'category_id' => $this->validateCategoryId((int) $value), + 'budget_id' => $this->validateBudgetId((int)$value), + 'category_id' => $this->validateCategoryId((int)$value), 'budget_name' => $this->validateBudgetName($value), - 'source_id', 'destination_id' => $this->validateAccountId((int) $value), + 'source_id', 'destination_id' => $this->validateAccountId((int)$value), default => throw new FireflyException(sprintf('Rule BelongUser cannot handle "%s"', $attribute)), }; } /** - * @param string $attribute + * @param string $attribute * * @return string */ @@ -113,7 +113,7 @@ class BelongsUser implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -127,7 +127,7 @@ class BelongsUser implements Rule } /** - * @param string $value + * @param string $value * * @return bool */ @@ -139,9 +139,9 @@ class BelongsUser implements Rule } /** - * @param string $class - * @param string $field - * @param string $value + * @param string $class + * @param string $field + * @param string $value * * @return int * @@ -154,14 +154,13 @@ class BelongsUser implements Rule if (PiggyBank::class === $class) { $objects = PiggyBank::leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id') ->where('accounts.user_id', '=', auth()->user()->id)->get(['piggy_banks.*']); - } if (PiggyBank::class !== $class) { $objects = $class::where('user_id', '=', auth()->user()->id)->get(); } $count = 0; foreach ($objects as $object) { - $objectValue = trim((string) $object->$field); + $objectValue = trim((string)$object->$field); Log::debug(sprintf('Comparing object "%s" with value "%s"', $objectValue, $value)); if ($objectValue === $value) { $count++; @@ -173,7 +172,7 @@ class BelongsUser implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -188,7 +187,7 @@ class BelongsUser implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -203,7 +202,7 @@ class BelongsUser implements Rule } /** - * @param string $value + * @param string $value * * @return bool */ @@ -216,7 +215,7 @@ class BelongsUser implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -231,7 +230,7 @@ class BelongsUser implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -243,7 +242,7 @@ class BelongsUser implements Rule } /** - * @param string $value + * @param string $value * * @return bool */ @@ -255,7 +254,7 @@ class BelongsUser implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ diff --git a/app/Rules/IsAssetAccountId.php b/app/Rules/IsAssetAccountId.php index f30a327b58..7eb32b0d9d 100644 --- a/app/Rules/IsAssetAccountId.php +++ b/app/Rules/IsAssetAccountId.php @@ -1,4 +1,5 @@ find($accountId); if (null === $account) { return false; diff --git a/app/Rules/IsBoolean.php b/app/Rules/IsBoolean.php index cf8331948f..5ccea1498b 100644 --- a/app/Rules/IsBoolean.php +++ b/app/Rules/IsBoolean.php @@ -39,14 +39,14 @@ class IsBoolean implements Rule */ public function message(): string { - return (string) trans('validation.boolean'); + return (string)trans('validation.boolean'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool */ @@ -61,7 +61,7 @@ class IsBoolean implements Rule if (is_int($value) && 1 === $value) { return true; } - if (is_string($value) && in_array($value, ['0', '1', 'true', 'false', 'on', 'off', 'yes', 'no', 'y', 'n'])) { + if (is_string($value) && in_array($value, ['0', '1', 'true', 'false', 'on', 'off', 'yes', 'no', 'y', 'n'], true)) { return true; } diff --git a/app/Rules/IsDateOrTime.php b/app/Rules/IsDateOrTime.php index cd888864b5..0fb9fff6b6 100644 --- a/app/Rules/IsDateOrTime.php +++ b/app/Rules/IsDateOrTime.php @@ -35,7 +35,6 @@ use Log; */ class IsDateOrTime implements Rule { - /** * Get the validation error message. * @@ -44,20 +43,20 @@ class IsDateOrTime implements Rule */ public function message() { - return (string) trans('validation.date_or_time'); + return (string)trans('validation.date_or_time'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool */ public function passes($attribute, $value): bool { - $value = (string) $value; + $value = (string)$value; if ('' === $value) { return false; } diff --git a/app/Rules/IsTransferAccount.php b/app/Rules/IsTransferAccount.php index 27103b1c8d..7cf7f00e0d 100644 --- a/app/Rules/IsTransferAccount.php +++ b/app/Rules/IsTransferAccount.php @@ -41,14 +41,14 @@ class IsTransferAccount implements Rule */ public function message(): string { - return (string) trans('validation.not_transfer_account'); + return (string)trans('validation.not_transfer_account'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool */ @@ -60,15 +60,15 @@ class IsTransferAccount implements Rule $validator->setTransactionType(TransactionType::TRANSFER); $validator->setUser(auth()->user()); - $validAccount = $validator->validateSource(['name' => (string) $value,]); + $validAccount = $validator->validateSource(['name' => (string)$value,]); if (true === $validAccount) { Log::debug('Found account based on name. Return true.'); // found by name, use repos to return. return true; } - $validAccount = $validator->validateSource(['id' => (int) $value,]); - Log::debug(sprintf('Search by id (%d), result is %s.', (int) $value, var_export($validAccount, true))); + $validAccount = $validator->validateSource(['id' => (int)$value,]); + Log::debug(sprintf('Search by id (%d), result is %s.', (int)$value, var_export($validAccount, true))); return false !== $validAccount; } diff --git a/app/Rules/IsValidAttachmentModel.php b/app/Rules/IsValidAttachmentModel.php index 1b6ec0dd56..8de8a7205f 100644 --- a/app/Rules/IsValidAttachmentModel.php +++ b/app/Rules/IsValidAttachmentModel.php @@ -55,7 +55,7 @@ class IsValidAttachmentModel implements Rule * * @codeCoverageIgnore * - * @param string $model + * @param string $model */ public function __construct(string $model) { @@ -64,7 +64,7 @@ class IsValidAttachmentModel implements Rule } /** - * @param string $model + * @param string $model * * @return string */ @@ -85,14 +85,14 @@ class IsValidAttachmentModel implements Rule */ public function message(): string { - return (string) trans('validation.model_id_invalid'); + return (string)trans('validation.model_id_invalid'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool */ @@ -118,11 +118,11 @@ class IsValidAttachmentModel implements Rule } $method = $methods[$this->model]; - return $this->$method((int) $value); + return $this->$method((int)$value); } /** - * @param int $value + * @param int $value * * @return bool */ @@ -136,7 +136,7 @@ class IsValidAttachmentModel implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -150,7 +150,7 @@ class IsValidAttachmentModel implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -164,7 +164,7 @@ class IsValidAttachmentModel implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -178,7 +178,7 @@ class IsValidAttachmentModel implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -191,7 +191,7 @@ class IsValidAttachmentModel implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -205,7 +205,7 @@ class IsValidAttachmentModel implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -219,7 +219,7 @@ class IsValidAttachmentModel implements Rule } /** - * @param int $value + * @param int $value * * @return bool */ @@ -229,6 +229,6 @@ class IsValidAttachmentModel implements Rule $repository = app(JournalAPIRepositoryInterface::class); $repository->setUser(auth()->user()); - return null !== $repository->findTransaction((int) $value); + return null !== $repository->findTransaction((int)$value); } } diff --git a/app/Rules/IsValidBulkClause.php b/app/Rules/IsValidBulkClause.php index 9b35893fb8..6211463fca 100644 --- a/app/Rules/IsValidBulkClause.php +++ b/app/Rules/IsValidBulkClause.php @@ -37,12 +37,12 @@ class IsValidBulkClause implements Rule private array $rules; /** - * @param string $type + * @param string $type */ public function __construct(string $type) { $this->rules = config(sprintf('bulk.%s', $type)); - $this->error = (string) trans('firefly.belongs_user'); + $this->error = (string)trans('firefly.belongs_user'); } /** @@ -54,14 +54,14 @@ class IsValidBulkClause implements Rule } /** - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool */ public function passes($attribute, $value): bool { - $result = $this->basicValidation((string) $value); + $result = $this->basicValidation((string)$value); if (false === $result) { return false; } @@ -72,7 +72,7 @@ class IsValidBulkClause implements Rule /** * Does basic rule based validation. * - * @param string $value + * @param string $value * * @return bool */ @@ -81,24 +81,24 @@ class IsValidBulkClause implements Rule try { $array = json_decode($value, true, 8, JSON_THROW_ON_ERROR); } catch (JsonException $e) { - $this->error = (string) trans('validation.json'); + $this->error = (string)trans('validation.json'); return false; } $clauses = ['where', 'update']; foreach ($clauses as $clause) { if (!array_key_exists($clause, $array)) { - $this->error = (string) trans(sprintf('validation.missing_%s', $clause)); + $this->error = (string)trans(sprintf('validation.missing_%s', $clause)); return false; } /** * @var string $arrayKey - * @var mixed $arrayValue + * @var mixed $arrayValue */ foreach ($array[$clause] as $arrayKey => $arrayValue) { if (!array_key_exists($arrayKey, $this->rules[$clause])) { - $this->error = (string) trans(sprintf('validation.invalid_%s_key', $clause)); + $this->error = (string)trans(sprintf('validation.invalid_%s_key', $clause)); return false; } diff --git a/app/Rules/LessThanPiggyTarget.php b/app/Rules/LessThanPiggyTarget.php index 9e4567ec55..8ac44f63f5 100644 --- a/app/Rules/LessThanPiggyTarget.php +++ b/app/Rules/LessThanPiggyTarget.php @@ -38,14 +38,14 @@ class LessThanPiggyTarget implements Rule */ public function message(): string { - return (string) trans('validation.current_target_amount'); + return (string)trans('validation.current_target_amount'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool */ diff --git a/app/Rules/UniqueAccountNumber.php b/app/Rules/UniqueAccountNumber.php index 94a2354a43..4bc92a4c44 100644 --- a/app/Rules/UniqueAccountNumber.php +++ b/app/Rules/UniqueAccountNumber.php @@ -42,8 +42,8 @@ class UniqueAccountNumber implements Rule * * @codeCoverageIgnore * - * @param Account|null $account - * @param string|null $expectedType + * @param Account|null $account + * @param string|null $expectedType */ public function __construct(?Account $account, ?string $expectedType) { @@ -72,14 +72,14 @@ class UniqueAccountNumber implements Rule */ public function message(): string { - return (string) trans('validation.unique_account_number_for_user'); + return (string)trans('validation.unique_account_number_for_user'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool * @@ -101,7 +101,10 @@ class UniqueAccountNumber implements Rule Log::debug( sprintf( 'account number "%s" is in use with %d account(s) of type "%s", which is too much for expected type "%s"', - $value, $count, $type, $this->expectedType + $value, + $count, + $type, + $this->expectedType ) ); @@ -140,20 +143,19 @@ class UniqueAccountNumber implements Rule } /** - * @param string $type - * @param string $accountNumber + * @param string $type + * @param string $accountNumber * * @return int */ private function countHits(string $type, string $accountNumber): int { - $query = AccountMeta - ::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') - ->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') - ->where('accounts.user_id', auth()->user()->id) - ->where('account_types.type', $type) - ->where('account_meta.name', '=', 'account_number') - ->where('account_meta.data', json_encode($accountNumber)); + $query = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') + ->leftJoin('account_types', 'account_types.id', '=', 'accounts.account_type_id') + ->where('accounts.user_id', auth()->user()->id) + ->where('account_types.type', $type) + ->where('account_meta.name', '=', 'account_number') + ->where('account_meta.data', json_encode($accountNumber)); if (null !== $this->account) { $query->where('accounts.id', '!=', $this->account->id); diff --git a/app/Rules/UniqueIban.php b/app/Rules/UniqueIban.php index ae94b4f528..5edebb1199 100644 --- a/app/Rules/UniqueIban.php +++ b/app/Rules/UniqueIban.php @@ -41,8 +41,8 @@ class UniqueIban implements Rule * * @codeCoverageIgnore * - * @param Account|null $account - * @param string|null $expectedType + * @param Account|null $account + * @param string|null $expectedType */ public function __construct(?Account $account, ?string $expectedType) { @@ -69,14 +69,14 @@ class UniqueIban implements Rule */ public function message(): string { - return (string) trans('validation.unique_iban_for_user'); + return (string)trans('validation.unique_iban_for_user'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool * @@ -98,7 +98,10 @@ class UniqueIban implements Rule Log::debug( sprintf( 'IBAN "%s" is in use with %d account(s) of type "%s", which is too much for expected type "%s"', - $value, $count, $type, $this->expectedType + $value, + $count, + $type, + $this->expectedType ) ); @@ -136,8 +139,8 @@ class UniqueIban implements Rule } /** - * @param string $type - * @param string $iban + * @param string $type + * @param string $iban * * @return int */ diff --git a/app/Rules/ValidJournals.php b/app/Rules/ValidJournals.php index e9575a4bc8..5618fbfe98 100644 --- a/app/Rules/ValidJournals.php +++ b/app/Rules/ValidJournals.php @@ -42,14 +42,14 @@ class ValidJournals implements Rule */ public function message(): string { - return (string) trans('validation.invalid_selection'); + return (string)trans('validation.invalid_selection'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool * diff --git a/app/Rules/ValidRecurrenceRepetitionType.php b/app/Rules/ValidRecurrenceRepetitionType.php index bbe95af3b2..74af36d979 100644 --- a/app/Rules/ValidRecurrenceRepetitionType.php +++ b/app/Rules/ValidRecurrenceRepetitionType.php @@ -32,7 +32,6 @@ use Illuminate\Contracts\Validation\Rule; */ class ValidRecurrenceRepetitionType implements Rule { - /** * Get the validation error message. * @@ -40,27 +39,27 @@ class ValidRecurrenceRepetitionType implements Rule */ public function message(): string { - return (string) trans('validation.valid_recurrence_rep_type'); + return (string)trans('validation.valid_recurrence_rep_type'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool * */ public function passes($attribute, $value): bool { - $value = (string) $value; + $value = (string)$value; if ('daily' === $value) { return true; } //monthly,17 //ndom,3,7 - if (in_array(substr($value, 0, 6), ['yearly', 'weekly'])) { + if (in_array(substr($value, 0, 6), ['yearly', 'weekly'], true)) { return true; } if (str_starts_with($value, 'monthly')) { diff --git a/app/Rules/ValidRecurrenceRepetitionValue.php b/app/Rules/ValidRecurrenceRepetitionValue.php index f9a4f8b50f..8860d5a6d8 100644 --- a/app/Rules/ValidRecurrenceRepetitionValue.php +++ b/app/Rules/ValidRecurrenceRepetitionValue.php @@ -35,7 +35,6 @@ use Log; */ class ValidRecurrenceRepetitionValue implements Rule { - /** * Get the validation error message. * @@ -43,21 +42,21 @@ class ValidRecurrenceRepetitionValue implements Rule */ public function message(): string { - return (string) trans('validation.valid_recurrence_rep_type'); + return (string)trans('validation.valid_recurrence_rep_type'); } /** * Determine if the validation rule passes. * - * @param string $attribute - * @param mixed $value + * @param string $attribute + * @param mixed $value * * @return bool * */ public function passes($attribute, $value): bool { - $value = (string) $value; + $value = (string)$value; if ('daily' === $value) { return true; @@ -87,19 +86,19 @@ class ValidRecurrenceRepetitionValue implements Rule } /** - * @param string $value + * @param string $value * * @return bool */ private function validateMonthly(string $value): bool { - $dayOfMonth = (int) substr($value, 8); + $dayOfMonth = (int)substr($value, 8); return $dayOfMonth > 0 && $dayOfMonth < 32; } /** - * @param string $value + * @param string $value * * @return bool * @@ -110,8 +109,8 @@ class ValidRecurrenceRepetitionValue implements Rule if (2 !== count($parameters)) { return false; } - $nthDay = (int) ($parameters[0] ?? 0.0); - $dayOfWeek = (int) ($parameters[1] ?? 0.0); + $nthDay = (int)($parameters[0] ?? 0.0); + $dayOfWeek = (int)($parameters[1] ?? 0.0); if ($nthDay < 1 || $nthDay > 5) { return false; } @@ -120,19 +119,19 @@ class ValidRecurrenceRepetitionValue implements Rule } /** - * @param string $value + * @param string $value * * @return bool */ private function validateWeekly(string $value): bool { - $dayOfWeek = (int) substr($value, 7); + $dayOfWeek = (int)substr($value, 7); return $dayOfWeek > 0 && $dayOfWeek < 8; } /** - * @param string $value + * @param string $value * * @return bool */ diff --git a/app/Services/FireflyIIIOrg/Update/UpdateRequest.php b/app/Services/FireflyIIIOrg/Update/UpdateRequest.php index 6a25fa44ee..d8d5b24ebe 100644 --- a/app/Services/FireflyIIIOrg/Update/UpdateRequest.php +++ b/app/Services/FireflyIIIOrg/Update/UpdateRequest.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Services\FireflyIIIOrg\Update; use Carbon\Carbon; +use FireflyIII\Events\NewVersionAvailable; use GuzzleHttp\Client; use GuzzleHttp\Exception\GuzzleException; use JsonException; @@ -35,9 +36,8 @@ use Log; */ class UpdateRequest implements UpdateRequestInterface { - /** - * @param string $channel + * @param string $channel * * @return array */ @@ -46,7 +46,7 @@ class UpdateRequest implements UpdateRequestInterface Log::debug(sprintf('Now in getUpdateInformation(%s)', $channel)); $information = [ 'level' => 'error', - 'message' => (string) trans('firefly.unknown_error'), + 'message' => (string)trans('firefly.unknown_error'), ]; // try get array from update server: @@ -64,7 +64,7 @@ class UpdateRequest implements UpdateRequestInterface } /** - * @param string $channel + * @param string $channel * * @return array */ @@ -76,13 +76,13 @@ class UpdateRequest implements UpdateRequestInterface 'version' => config('firefly.version'), 'date' => Carbon::today()->startOfDay(), 'level' => 'error', - 'message' => (string) trans('firefly.unknown_error'), + 'message' => (string)trans('firefly.unknown_error'), ]; $url = config('firefly.update_endpoint'); Log::debug(sprintf('Going to call %s', $url)); try { - $client = new Client; + $client = new Client(); $options = [ 'headers' => [ 'User-Agent' => sprintf('FireflyIII/%s/%s', config('firefly.version'), $channel), @@ -101,15 +101,14 @@ class UpdateRequest implements UpdateRequestInterface if (200 !== $res->getStatusCode()) { Log::error(sprintf('Response status from server is %d.', $res->getStatusCode())); - Log::error((string) $res->getBody()); + Log::error((string)$res->getBody()); $return['message'] = sprintf('Error: %d', $res->getStatusCode()); return $return; } - $body = (string) $res->getBody(); + $body = (string)$res->getBody(); try { $json = json_decode($body, true, 512, JSON_THROW_ON_ERROR); - } catch (JsonException $e) { Log::error('Body is not valid JSON'); Log::error($body); @@ -135,7 +134,7 @@ class UpdateRequest implements UpdateRequestInterface } /** - * @param array $information + * @param array $information * * @return array */ @@ -144,7 +143,7 @@ class UpdateRequest implements UpdateRequestInterface Log::debug('Now in parseResult()', $information); $return = [ 'level' => 'error', - 'message' => (string) trans('firefly.unknown_error'), + 'message' => (string)trans('firefly.unknown_error'), ]; $current = config('firefly.version'); $latest = $information['version']; @@ -155,7 +154,7 @@ class UpdateRequest implements UpdateRequestInterface // -1: you're running a newer version: if (-1 === $compare) { $return['level'] = 'info'; - $return['message'] = (string) trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]); + $return['message'] = (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]); Log::debug('User is running a newer version', $return); return $return; @@ -163,11 +162,12 @@ class UpdateRequest implements UpdateRequestInterface // running the current version: if (0 === $compare) { $return['level'] = 'info'; - $return['message'] = (string) trans('firefly.update_current_version_alert', ['version' => $current]); + $return['message'] = (string)trans('firefly.update_current_version_alert', ['version' => $current]); Log::debug('User is the current version.', $return); return $return; } + // a newer version is available! /** @var Carbon $released */ $released = $information['date']; @@ -177,11 +177,12 @@ class UpdateRequest implements UpdateRequestInterface // it's still very fresh, and user wants a stable release: if ($diff <= $expectedDiff) { $return['level'] = 'info'; - $return['message'] = (string) trans( + $return['message'] = (string)trans( 'firefly.just_new_release', - ['version' => $latest, - 'date' => $released->isoFormat((string) trans('config.month_and_day_js')), - 'days' => $expectedDiff, + [ + 'version' => $latest, + 'date' => $released->isoFormat((string)trans('config.month_and_day_js')), + 'days' => $expectedDiff, ] ); Log::debug('Release is very fresh.', $return); @@ -189,14 +190,15 @@ class UpdateRequest implements UpdateRequestInterface return $return; } - // its been around for a while: + // it's been around for a while: $return['level'] = 'success'; - $return['message'] = (string) trans( + $return['message'] = (string)trans( 'firefly.update_new_version_alert', [ 'your_version' => $current, 'new_version' => $latest, - 'date' => $released->isoFormat((string) trans('config.month_and_day_js'))] + 'date' => $released->isoFormat((string)trans('config.month_and_day_js')), + ] ); Log::debug('New release is old enough.'); @@ -215,6 +217,9 @@ class UpdateRequest implements UpdateRequestInterface } Log::debug('New release is here!', $return); + // send event, this may result in a notification. + event(new NewVersionAvailable($return['message'])); + return $return; } } diff --git a/app/Services/FireflyIIIOrg/Update/UpdateRequestInterface.php b/app/Services/FireflyIIIOrg/Update/UpdateRequestInterface.php index 779fc05b46..e616837222 100644 --- a/app/Services/FireflyIIIOrg/Update/UpdateRequestInterface.php +++ b/app/Services/FireflyIIIOrg/Update/UpdateRequestInterface.php @@ -30,10 +30,9 @@ namespace FireflyIII\Services\FireflyIIIOrg\Update; interface UpdateRequestInterface { /** - * @param string $channel + * @param string $channel * * @return array */ public function getUpdateInformation(string $channel): array; - } diff --git a/app/Services/Internal/Destroy/AccountDestroyService.php b/app/Services/Internal/Destroy/AccountDestroyService.php index ee5aafe5b0..a579ee0783 100644 --- a/app/Services/Internal/Destroy/AccountDestroyService.php +++ b/app/Services/Internal/Destroy/AccountDestroyService.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Destroy; use DB; -use Exception; use FireflyIII\Models\Account; use FireflyIII\Models\PiggyBank; use FireflyIII\Models\RecurrenceTransaction; @@ -41,8 +40,8 @@ use stdClass; class AccountDestroyService { /** - * @param Account $account - * @param Account|null $moveTo + * @param Account $account + * @param Account|null $moveTo * * @return void */ @@ -68,15 +67,11 @@ class AccountDestroyService // delete account meta: $account->accountMeta()->delete(); // delete account. - try { - $account->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $account->delete(); } /** - * @param Account $account + * @param Account $account */ private function destroyOpeningBalance(Account $account): void { @@ -87,14 +82,13 @@ class AccountDestroyService ->where('transaction_types.type', TransactionType::OPENING_BALANCE) ->get(['transactions.transaction_journal_id']); if ($set->count() > 0) { - $journalId = (int) $set->first()->transaction_journal_id; + $journalId = (int)$set->first()->transaction_journal_id; Log::debug(sprintf('Found opening balance journal with ID #%d', $journalId)); // get transactions with this journal (should be just one): - $transactions = Transaction - ::where('transaction_journal_id', $journalId) - ->where('account_id', '!=', $account->id) - ->get(); + $transactions = Transaction::where('transaction_journal_id', $journalId) + ->where('account_id', '!=', $account->id) + ->get(); /** @var Transaction $transaction */ foreach ($transactions as $transaction) { Log::debug(sprintf('Found transaction with ID #%d', $transaction->id)); @@ -113,8 +107,8 @@ class AccountDestroyService } /** - * @param Account $account - * @param Account $moveTo + * @param Account $account + * @param Account $moveTo */ public function moveTransactions(Account $account, Account $moveTo): void { @@ -123,7 +117,7 @@ class AccountDestroyService $collection = Transaction::groupBy('transaction_journal_id', 'account_id') ->where('account_id', $moveTo->id) - ->get(['transaction_journal_id', 'account_id', DB::raw('count(*) as the_count')]); // @phpstan-ignore-line + ->get(['transaction_journal_id', 'account_id', DB::raw('count(*) as the_count')]); if (0 === $collection->count()) { return; } @@ -133,8 +127,8 @@ class AccountDestroyService $user = $account->user; /** @var stdClass $row */ foreach ($collection as $row) { - if ((int) $row->the_count > 1) { - $journalId = (int) $row->transaction_journal_id; + if ((int)$row->the_count > 1) { + $journalId = (int)$row->transaction_journal_id; $journal = $user->transactionJournals()->find($journalId); if (null !== $journal) { Log::debug(sprintf('Deleted journal #%d because it has the same source as destination.', $journal->id)); @@ -145,8 +139,8 @@ class AccountDestroyService } /** - * @param Account $account - * @param Account $moveTo + * @param Account $account + * @param Account $moveTo */ private function updateRecurrences(Account $account, Account $moveTo): void { @@ -155,34 +149,32 @@ class AccountDestroyService } /** - * @param Account $account + * @param Account $account */ private function destroyJournals(Account $account): void { - /** @var JournalDestroyService $service */ $service = app(JournalDestroyService::class); - Log::debug('Now trigger account delete response #' . $account->id); + Log::debug('Now trigger account delete response #'.$account->id); /** @var Transaction $transaction */ foreach ($account->transactions()->get() as $transaction) { - Log::debug('Now at transaction #' . $transaction->id); + Log::debug('Now at transaction #'.$transaction->id); /** @var TransactionJournal $journal */ $journal = $transaction->transactionJournal()->first(); if (null !== $journal) { - Log::debug('Call for deletion of journal #' . $journal->id); + Log::debug('Call for deletion of journal #'.$journal->id); $service->destroy($journal); } } } /** - * @param Account $account + * @param Account $account */ private function destroyRecurrences(Account $account): void { - $recurrences = RecurrenceTransaction:: - where( + $recurrences = RecurrenceTransaction::where( static function (Builder $q) use ($account) { $q->where('source_id', $account->id); $q->orWhere('destination_id', $account->id); @@ -192,8 +184,7 @@ class AccountDestroyService /** @var RecurrenceDestroyService $destroyService */ $destroyService = app(RecurrenceDestroyService::class); foreach ($recurrences as $recurrenceId) { - $destroyService->destroyById((int) $recurrenceId); + $destroyService->destroyById((int)$recurrenceId); } } - } diff --git a/app/Services/Internal/Destroy/BillDestroyService.php b/app/Services/Internal/Destroy/BillDestroyService.php index bc97716159..d2b2522584 100644 --- a/app/Services/Internal/Destroy/BillDestroyService.php +++ b/app/Services/Internal/Destroy/BillDestroyService.php @@ -33,15 +33,10 @@ use FireflyIII\Models\Bill; class BillDestroyService { /** - * @param Bill $bill + * @param Bill $bill */ public function destroy(Bill $bill): void { - try { - $bill->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $bill->delete(); } - } diff --git a/app/Services/Internal/Destroy/BudgetDestroyService.php b/app/Services/Internal/Destroy/BudgetDestroyService.php index e7b1deb515..cea4e6fd3e 100644 --- a/app/Services/Internal/Destroy/BudgetDestroyService.php +++ b/app/Services/Internal/Destroy/BudgetDestroyService.php @@ -35,16 +35,11 @@ use FireflyIII\Models\Budget; class BudgetDestroyService { /** - * @param Budget $budget + * @param Budget $budget */ public function destroy(Budget $budget): void { - - try { - $budget->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $budget->delete(); // also delete auto budget: foreach ($budget->autoBudgets()->get() as $autoBudget) { @@ -52,10 +47,10 @@ class BudgetDestroyService } // also delete all relations between categories and transaction journals: - DB::table('budget_transaction_journal')->where('budget_id', (int) $budget->id)->delete(); + DB::table('budget_transaction_journal')->where('budget_id', (int)$budget->id)->delete(); // also delete all relations between categories and transactions: - DB::table('budget_transaction')->where('budget_id', (int) $budget->id)->delete(); + DB::table('budget_transaction')->where('budget_id', (int)$budget->id)->delete(); // also delete all budget limits $budget->budgetlimits()->delete(); diff --git a/app/Services/Internal/Destroy/CategoryDestroyService.php b/app/Services/Internal/Destroy/CategoryDestroyService.php index 63c97ec7a2..ee00647357 100644 --- a/app/Services/Internal/Destroy/CategoryDestroyService.php +++ b/app/Services/Internal/Destroy/CategoryDestroyService.php @@ -35,20 +35,16 @@ use FireflyIII\Models\Category; class CategoryDestroyService { /** - * @param Category $category + * @param Category $category */ public function destroy(Category $category): void { - try { - $category->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $category->delete(); // also delete all relations between categories and transaction journals: - DB::table('category_transaction_journal')->where('category_id', (int) $category->id)->delete(); + DB::table('category_transaction_journal')->where('category_id', (int)$category->id)->delete(); // also delete all relations between categories and transactions: - DB::table('category_transaction')->where('category_id', (int) $category->id)->delete(); + DB::table('category_transaction')->where('category_id', (int)$category->id)->delete(); } } diff --git a/app/Services/Internal/Destroy/CurrencyDestroyService.php b/app/Services/Internal/Destroy/CurrencyDestroyService.php index a655c82919..70ecf99d43 100644 --- a/app/Services/Internal/Destroy/CurrencyDestroyService.php +++ b/app/Services/Internal/Destroy/CurrencyDestroyService.php @@ -34,16 +34,10 @@ use FireflyIII\Models\TransactionCurrency; class CurrencyDestroyService { /** - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency */ public function destroy(TransactionCurrency $currency): void { - - try { - $currency->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $currency->delete(); } - } diff --git a/app/Services/Internal/Destroy/JournalDestroyService.php b/app/Services/Internal/Destroy/JournalDestroyService.php index a005d2d061..994f066a5b 100644 --- a/app/Services/Internal/Destroy/JournalDestroyService.php +++ b/app/Services/Internal/Destroy/JournalDestroyService.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Destroy; use DB; -use Exception; use FireflyIII\Models\Attachment; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionJournal; @@ -39,68 +38,62 @@ use Log; class JournalDestroyService { /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal */ public function destroy(TransactionJournal $journal): void { - try { - /** @var Transaction $transaction */ - foreach ($journal->transactions()->get() as $transaction) { - Log::debug(sprintf('Will now delete transaction #%d', $transaction->id)); - $transaction->delete(); - } - - // also delete journal_meta entries. - /** @var TransactionJournalMeta $meta */ - foreach ($journal->transactionJournalMeta()->get() as $meta) { - Log::debug(sprintf('Will now delete meta-entry #%d', $meta->id)); - $meta->delete(); - } - - // also delete attachments. - /** @var Attachment $attachment */ - foreach ($journal->attachments()->get() as $attachment) { - $attachment->delete(); - } - - // delete all from 'budget_transaction_journal' - DB::table('budget_transaction_journal') - ->where('transaction_journal_id', $journal->id)->delete(); - - // delete all from 'category_transaction_journal' - DB::table('category_transaction_journal') - ->where('transaction_journal_id', $journal->id)->delete(); - - // delete all from 'tag_transaction_journal' - DB::table('tag_transaction_journal') - ->where('transaction_journal_id', $journal->id)->delete(); - - // delete all links: - TransactionJournalLink::where('source_id', $journal->id)->delete(); - TransactionJournalLink::where('destination_id', $journal->id)->delete(); - - // delete all notes - $journal->notes()->delete(); - - // update events - // TODO move to repository - $journal->piggyBankEvents()->update(['transaction_journal_id' => null]); - - $journal->delete(); - - // delete group, if group is empty: - $group = $journal->transactionGroup; - if (null !== $group) { - $count = $group->transactionJournals->count(); - if (0 === $count) { - $group->delete(); - } - } - - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException + Log::debug(sprintf('Now in %s', __METHOD__)); + /** @var Transaction $transaction */ + foreach ($journal->transactions()->get() as $transaction) { + Log::debug(sprintf('Will now delete transaction #%d', $transaction->id)); + $transaction->delete(); } - } + // also delete journal_meta entries. + /** @var TransactionJournalMeta $meta */ + foreach ($journal->transactionJournalMeta()->get() as $meta) { + Log::debug(sprintf('Will now delete meta-entry #%d', $meta->id)); + $meta->delete(); + } + // also delete attachments. + /** @var Attachment $attachment */ + foreach ($journal->attachments()->get() as $attachment) { + $attachment->delete(); + } + + // delete all from 'budget_transaction_journal' + DB::table('budget_transaction_journal') + ->where('transaction_journal_id', $journal->id)->delete(); + + // delete all from 'category_transaction_journal' + DB::table('category_transaction_journal') + ->where('transaction_journal_id', $journal->id)->delete(); + + // delete all from 'tag_transaction_journal' + DB::table('tag_transaction_journal') + ->where('transaction_journal_id', $journal->id)->delete(); + + // delete all links: + TransactionJournalLink::where('source_id', $journal->id)->delete(); + TransactionJournalLink::where('destination_id', $journal->id)->delete(); + + // delete all notes + $journal->notes()->delete(); + + // update events + // TODO move to repository + $journal->piggyBankEvents()->update(['transaction_journal_id' => null]); + + $journal->delete(); + + // delete group, if group is empty: + $group = $journal->transactionGroup; + if (null !== $group) { + $count = $group->transactionJournals->count(); + if (0 === $count) { + $group->delete(); + } + } + } } diff --git a/app/Services/Internal/Destroy/RecurrenceDestroyService.php b/app/Services/Internal/Destroy/RecurrenceDestroyService.php index 5a4ac788c5..88fbb27376 100644 --- a/app/Services/Internal/Destroy/RecurrenceDestroyService.php +++ b/app/Services/Internal/Destroy/RecurrenceDestroyService.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Destroy; -use Exception; use FireflyIII\Models\Recurrence; use FireflyIII\Models\RecurrenceTransaction; @@ -36,7 +35,7 @@ class RecurrenceDestroyService /** * Delete recurrence by ID * - * @param int $recurrenceId + * @param int $recurrenceId */ public function destroyById(int $recurrenceId): void { @@ -45,42 +44,28 @@ class RecurrenceDestroyService return; } $this->destroy($recurrence); - } /** * Delete recurrence. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * */ public function destroy(Recurrence $recurrence): void { - try { - // delete all meta data - $recurrence->recurrenceMeta()->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + // delete all meta data + $recurrence->recurrenceMeta()->delete(); // delete all transactions. /** @var RecurrenceTransaction $transaction */ foreach ($recurrence->recurrenceTransactions as $transaction) { $transaction->recurrenceTransactionMeta()->delete(); - try { - $transaction->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $transaction->delete(); } // delete all repetitions $recurrence->recurrenceRepetitions()->delete(); // delete recurrence - try { - $recurrence->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $recurrence->delete(); } - } diff --git a/app/Services/Internal/Destroy/TransactionGroupDestroyService.php b/app/Services/Internal/Destroy/TransactionGroupDestroyService.php index 9e7c9d0717..d18cb35c29 100644 --- a/app/Services/Internal/Destroy/TransactionGroupDestroyService.php +++ b/app/Services/Internal/Destroy/TransactionGroupDestroyService.php @@ -23,9 +23,9 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Destroy; -use Exception; use FireflyIII\Events\DestroyedTransactionGroup; use FireflyIII\Models\TransactionGroup; +use Illuminate\Support\Facades\Log; /** * Class TransactionGroupDestroyService @@ -34,24 +34,19 @@ use FireflyIII\Models\TransactionGroup; */ class TransactionGroupDestroyService { - /** - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup */ public function destroy(TransactionGroup $transactionGroup): void { + Log::debug(sprintf('Now in %s', __METHOD__)); /** @var JournalDestroyService $service */ $service = app(JournalDestroyService::class); foreach ($transactionGroup->transactionJournals as $journal) { $service->destroy($journal); } - try { - $transactionGroup->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $transactionGroup->delete(); // trigger just after destruction event(new DestroyedTransactionGroup($transactionGroup)); } - } diff --git a/app/Services/Internal/Support/AccountServiceTrait.php b/app/Services/Internal/Support/AccountServiceTrait.php index 23e40c8018..3f9507ee46 100644 --- a/app/Services/Internal/Support/AccountServiceTrait.php +++ b/app/Services/Internal/Support/AccountServiceTrait.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Support; use Carbon\Carbon; -use Exception; use FireflyIII\Exceptions\DuplicateTransactionException; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\AccountMetaFactory; @@ -39,6 +38,7 @@ use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Services\Internal\Destroy\TransactionGroupDestroyService; +use JsonException; use Log; use Validator; @@ -51,7 +51,7 @@ trait AccountServiceTrait protected AccountRepositoryInterface $accountRepository; /** - * @param null|string $iban + * @param null|string $iban * * @return null|string */ @@ -76,7 +76,7 @@ trait AccountServiceTrait /** * Returns true if the data in the array is submitted but empty. * - * @param array $data + * @param array $data * * @return bool */ @@ -100,12 +100,12 @@ trait AccountServiceTrait } /** - * Update meta data for account. Depends on type which fields are valid. + * Update metadata for account. Depends on type which fields are valid. * - * See reference nr. 97 + * TODO this method treats expense accounts and liabilities the same way (tries to save interest) * - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * */ public function updateMetaData(Account $account, array $data): void @@ -118,8 +118,8 @@ trait AccountServiceTrait // remove currency_id if necessary. $type = $account->accountType->type; $list = config('firefly.valid_currency_account_types'); - if(!in_array($type, $list, true)) { - $pos = array_search('currency_id', $fields); + if (!in_array($type, $list, true)) { + $pos = array_search('currency_id', $fields, true); if ($pos !== false) { unset($fields[$pos]); } @@ -147,7 +147,6 @@ trait AccountServiceTrait // if the field is set but NULL, skip it. // if the field is set but "", update it. if (array_key_exists($field, $data) && null !== $data[$field]) { - // convert boolean value: if (is_bool($data[$field]) && false === $data[$field]) { $data[$field] = 0; @@ -156,14 +155,14 @@ trait AccountServiceTrait $data[$field] = 1; } - $factory->crud($account, $field, (string) $data[$field]); + $factory->crud($account, $field, (string)$data[$field]); } } } /** - * @param Account $account - * @param string $note + * @param Account $account + * @param string $note * * @codeCoverageIgnore * @return bool @@ -173,18 +172,14 @@ trait AccountServiceTrait if ('' === $note) { $dbNote = $account->notes()->first(); if (null !== $dbNote) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $dbNote->delete(); } return true; } $dbNote = $account->notes()->first(); if (null === $dbNote) { - $dbNote = new Note; + $dbNote = new Note(); $dbNote->noteable()->associate($account); } $dbNote->text = trim($note); @@ -196,13 +191,13 @@ trait AccountServiceTrait /** * Verify if array contains valid data to possibly store or update the opening balance. * - * @param array $data + * @param array $data * * @return bool */ public function validOBData(array $data): bool { - $data['opening_balance'] = (string) ($data['opening_balance'] ?? ''); + $data['opening_balance'] = (string)($data['opening_balance'] ?? ''); if ('' !== $data['opening_balance'] && 0 === bccomp($data['opening_balance'], '0')) { $data['opening_balance'] = ''; } @@ -218,8 +213,8 @@ trait AccountServiceTrait } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @return TransactionGroup * @throws FireflyException @@ -312,7 +307,7 @@ trait AccountServiceTrait /** * Delete TransactionGroup with liability credit in it. * - * @param Account $account + * @param Account $account */ protected function deleteCreditTransaction(Account $account): void { @@ -330,7 +325,7 @@ trait AccountServiceTrait /** * Returns the credit transaction group, or NULL if it does not exist. * - * @param Account $account + * @param Account $account * * @return TransactionGroup|null */ @@ -344,7 +339,7 @@ trait AccountServiceTrait /** * Delete TransactionGroup with opening balance in it. * - * @param Account $account + * @param Account $account */ protected function deleteOBGroup(Account $account): void { @@ -363,7 +358,7 @@ trait AccountServiceTrait /** * Returns the opening balance group, or NULL if it does not exist. * - * @param Account $account + * @param Account $account * * @return TransactionGroup|null */ @@ -373,12 +368,12 @@ trait AccountServiceTrait } /** - * @param int $currencyId - * @param string $currencyCode + * @param int $currencyId + * @param string $currencyCode * * @return TransactionCurrency * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ protected function getCurrency(int $currencyId, string $currencyCode): TransactionCurrency { @@ -401,20 +396,29 @@ trait AccountServiceTrait /** * Create the opposing "credit liability" transaction for credit liabilities. * - * @param Account $account - * @param string $openingBalance - * @param Carbon $openingBalanceDate + * @param Account $account + * @param string $openingBalance + * @param Carbon $openingBalanceDate * * @return TransactionGroup * @throws FireflyException */ - protected function updateCreditTransaction(Account $account, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup + protected function updateCreditTransaction(Account $account, string $direction, string $openingBalance, Carbon $openingBalanceDate): TransactionGroup { Log::debug(sprintf('Now in %s', __METHOD__)); if (0 === bccomp($openingBalance, '0')) { - Log::debug('Amount is zero, so will not update liability credit group.'); - throw new FireflyException('Amount for update liability credit was unexpectedly 0.'); + Log::debug('Amount is zero, so will not update liability credit/debit group.'); + throw new FireflyException('Amount for update liability credit/debit was unexpectedly 0.'); + } + // if direction is "debit" (i owe this debt), amount is negative. + // which means the liability will have a negative balance which the user must fill. + $openingBalance = app('steam')->negative($openingBalance); + + // if direction is "credit" (I am owed this debt), amount is positive. + // which means the liability will have a positive balance which is drained when its paid back into any asset. + if ('credit' === $direction) { + $openingBalance = app('steam')->positive($openingBalance); } // create if not exists: @@ -452,9 +456,9 @@ trait AccountServiceTrait } /** - * @param Account $account - * @param string $openingBalance - * @param Carbon $openingBalanceDate + * @param Account $account + * @param string $openingBalance + * @param Carbon $openingBalanceDate * * @return TransactionGroup * @throws FireflyException @@ -469,7 +473,24 @@ trait AccountServiceTrait } $language = app('preferences')->getForUser($account->user, 'language', 'en_US')->data; - $amount = app('steam')->positive($openingBalance); + + // set source and/or destination based on whether the amount is positive or negative. + // first, assume the amount is positive and go from there: + // if amount is positive ("I am owed this debt"), source is special account, destination is the liability. + $sourceId = null; + $sourceName = trans('firefly.liability_credit_description', ['account' => $account->name], $language); + $destId = $account->id; + $destName = null; + if (-1 === bccomp($openingBalance, '0')) { + // amount is negative, reverse it + $sourceId = $account->id; + $sourceName = null; + $destId = null; + $destName = trans('firefly.liability_credit_description', ['account' => $account->name], $language); + } + + // amount must be positive for the transaction to work. + $amount = app('steam')->positive($openingBalance); // get or grab currency: $currency = $this->accountRepository->getAccountCurrency($account); @@ -485,10 +506,10 @@ trait AccountServiceTrait [ 'type' => 'Liability credit', 'date' => $openingBalanceDate, - 'source_id' => null, - 'source_name' => trans('firefly.liability_credit_description', ['account' => $account->name], $language), - 'destination_id' => $account->id, - 'destination_name' => null, + 'source_id' => $sourceId, + 'source_name' => $sourceName, + 'destination_id' => $destId, + 'destination_name' => $destName, 'user' => $account->user_id, 'currency_id' => $currency->id, 'order' => 0, @@ -525,9 +546,9 @@ trait AccountServiceTrait } /** - * See reference nr. 99 + * TODO refactor to "getfirstjournal" * - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return TransactionJournal * @throws FireflyException @@ -544,10 +565,10 @@ trait AccountServiceTrait } /** - * See reference nr. 98 + * TODO Rename to getOpposingTransaction * - * @param TransactionJournal $journal - * @param Account $account + * @param TransactionJournal $journal + * @param Account $account * * @return Transaction * @throws FireflyException @@ -564,8 +585,8 @@ trait AccountServiceTrait } /** - * @param TransactionJournal $journal - * @param Account $account + * @param TransactionJournal $journal + * @param Account $account * * @return Transaction * @throws FireflyException @@ -585,9 +606,9 @@ trait AccountServiceTrait * Update or create the opening balance group. * Since opening balance and date can still be empty strings, it may fail. * - * @param Account $account - * @param string $openingBalance - * @param Carbon $openingBalanceDate + * @param Account $account + * @param string $openingBalance + * @param Carbon $openingBalanceDate * * @return TransactionGroup * @throws FireflyException @@ -647,9 +668,9 @@ trait AccountServiceTrait } /** - * @param Account $account - * @param string $openingBalance - * @param Carbon $openingBalanceDate + * @param Account $account + * @param string $openingBalance + * @param Carbon $openingBalanceDate * * @return TransactionGroup * @throws FireflyException diff --git a/app/Services/Internal/Support/BillServiceTrait.php b/app/Services/Internal/Support/BillServiceTrait.php index c992e0b4e7..b790330ff4 100644 --- a/app/Services/Internal/Support/BillServiceTrait.php +++ b/app/Services/Internal/Support/BillServiceTrait.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Support; -use Exception; use FireflyIII\Models\Bill; use FireflyIII\Models\Note; use FireflyIII\Models\RuleAction; @@ -36,11 +35,10 @@ use Log; */ trait BillServiceTrait { - /** - * @param Bill $bill - * @param string $oldName - * @param string $newName + * @param Bill $bill + * @param string $oldName + * @param string $newName */ public function updateBillActions(Bill $bill, string $oldName, string $newName): void { @@ -61,8 +59,8 @@ trait BillServiceTrait } /** - * @param Bill $bill - * @param string $note + * @param Bill $bill + * @param string $note * * @return bool */ @@ -71,11 +69,7 @@ trait BillServiceTrait if ('' === $note) { $dbNote = $bill->notes()->first(); if (null !== $dbNote) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $dbNote->delete(); } return true; @@ -90,5 +84,4 @@ trait BillServiceTrait return true; } - } diff --git a/app/Services/Internal/Support/CreditRecalculateService.php b/app/Services/Internal/Support/CreditRecalculateService.php index 4147714aa6..c37dbf181d 100644 --- a/app/Services/Internal/Support/CreditRecalculateService.php +++ b/app/Services/Internal/Support/CreditRecalculateService.php @@ -22,10 +22,8 @@ declare(strict_types=1); - namespace FireflyIII\Services\Internal\Support; - use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\AccountMetaFactory; use FireflyIII\Models\Account; @@ -64,13 +62,15 @@ class CreditRecalculateService return; } if (null !== $this->group && null === $this->account) { + Log::debug('Have to handle a group.'); $this->processGroup(); } if (null !== $this->account && null === $this->group) { + Log::debug('Have to handle an account.'); // work based on account. $this->processAccount(); } - if (empty($this->work)) { + if (0 === count($this->work)) { Log::debug('No work accounts, do not do CreditRecalculationService'); return; @@ -86,7 +86,7 @@ class CreditRecalculateService { /** @var TransactionJournal $journal */ foreach ($this->group->transactionJournals as $journal) { - if (empty($this->work)) { + if (0 === count($this->work)) { try { $this->findByJournal($journal); } catch (FireflyException $e) { @@ -110,11 +110,11 @@ class CreditRecalculateService // destination or source must be liability. $valid = config('firefly.valid_liabilities'); - if (in_array($destination->accountType->type, $valid)) { + if (in_array($destination->accountType->type, $valid, true)) { Log::debug(sprintf('Dest account type is "%s", include it.', $destination->accountType->type)); $this->work[] = $destination; } - if (in_array($source->accountType->type, $valid)) { + if (in_array($source->accountType->type, $valid, true)) { Log::debug(sprintf('Src account type is "%s", include it.', $source->accountType->type)); $this->work[] = $source; } @@ -170,7 +170,7 @@ class CreditRecalculateService private function processAccount(): void { $valid = config('firefly.valid_liabilities'); - if (in_array($this->account->accountType->type, $valid)) { + if (in_array($this->account->accountType->type, $valid, true)) { Log::debug(sprintf('Account type is "%s", include it.', $this->account->accountType->type)); $this->work[] = $this->account; } @@ -215,7 +215,6 @@ class CreditRecalculateService } $factory->crud($account, 'current_debt', $leftOfDebt); - Log::debug(sprintf('Done with %s(#%d)', __METHOD__, $account->id)); } @@ -254,28 +253,32 @@ class CreditRecalculateService Log::debug(sprintf('Processing group #%d, journal #%d of type "%s"', $journal->id, $groupId, $type)); // it's a withdrawal into this liability (from asset). - // if it's a credit, we don't care, because sending more money - // to a credit-liability doesn't increase the amount (yet) + // if it's a credit ("I am owed"), this increases the amount due, + // because we're lending person X more money if ( $type === TransactionType::WITHDRAWAL && (int)$account->id === (int)$transaction->account_id && 1 === bccomp($usedAmount, '0') && 'credit' === $direction ) { - Log::debug(sprintf('Is withdrawal into credit liability #%d, does not influence the amount due.', $transaction->account_id)); - + $amount = bcadd($amount, app('steam')->positive($usedAmount)); + Log::debug( + sprintf('Is withdrawal (%s) into credit liability #%d, will increase amount due to %s.', $transaction->account_id, $usedAmount, $amount) + ); return $amount; } - // likewise deposit into a credit debt does not change the amount + // it's a deposit out of this liability (to asset). + // if it's a credit ("I am owed") this decreases the amount due. + // because the person is paying us back. if ( $type === TransactionType::DEPOSIT && (int)$account->id === (int)$transaction->account_id && -1 === bccomp($usedAmount, '0') && 'credit' === $direction ) { - Log::debug(sprintf('Is deposit from liability #%d,does not influence the amount left.', $transaction->account_id)); - + $amount = bcsub($amount, app('steam')->positive($usedAmount)); + Log::debug(sprintf('Is deposit (%s) from credit liability #%d, will decrease amount due to %s.', $transaction->account_id, $usedAmount, $amount)); return $amount; } @@ -302,6 +305,4 @@ class CreditRecalculateService { $this->group = $group; } - - } diff --git a/app/Services/Internal/Support/JournalServiceTrait.php b/app/Services/Internal/Support/JournalServiceTrait.php index 24777d11e1..ba96fffa78 100644 --- a/app/Services/Internal/Support/JournalServiceTrait.php +++ b/app/Services/Internal/Support/JournalServiceTrait.php @@ -23,7 +23,6 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Support; -use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\AccountMetaFactory; use FireflyIII\Factory\TagFactory; @@ -50,15 +49,15 @@ trait JournalServiceTrait private TagFactory $tagFactory; /** - * @param string $transactionType - * @param string $direction - * @param array $data + * @param string $transactionType + * @param string $direction + * @param array $data * - * @return Account + * @return Account|null * @codeCoverageIgnore * @throws FireflyException */ - protected function getAccount(string $transactionType, string $direction, array $data): Account + protected function getAccount(string $transactionType, string $direction, array $data): ?Account { // some debug logging: Log::debug(sprintf('Now in getAccount(%s)', $direction), $data); @@ -88,8 +87,8 @@ trait JournalServiceTrait } /** - * @param array $data - * @param array $types + * @param array $data + * @param array $types * * @return Account|null */ @@ -98,7 +97,7 @@ trait JournalServiceTrait $search = null; // first attempt, find by ID. if (null !== $data['id']) { - $search = $this->accountRepository->find((int) $data['id']); + $search = $this->accountRepository->find((int)$data['id']); if (null !== $search && in_array($search->accountType->type, $types, true)) { Log::debug( sprintf('Found "account_id" object: #%d, "%s" of type %s', $search->id, $search->name, $search->accountType->type) @@ -110,9 +109,9 @@ trait JournalServiceTrait } /** - * @param Account|null $account - * @param array $data - * @param array $types + * @param Account|null $account + * @param array $data + * @param array $types * * @return Account|null */ @@ -137,22 +136,22 @@ trait JournalServiceTrait } /** - * @param Account|null $account - * @param array $data - * @param array $types + * @param Account|null $account + * @param array $data + * @param array $types * * @return Account|null */ private function findAccountByNumber(?Account $account, array $data, array $types): ?Account { // third attempt, find by account number - if (null === $account && null !== $data['number'] && '' !== (string) $data['number']) { + if (null === $account && null !== $data['number'] && '' !== (string)$data['number']) { Log::debug(sprintf('Searching for account number "%s".', $data['number'])); // find by preferred type. - $source = $this->accountRepository->findByAccountNumber((string) $data['number'], [$types[0]]); + $source = $this->accountRepository->findByAccountNumber((string)$data['number'], [$types[0]]); // or any expected type. - $source = $source ?? $this->accountRepository->findByAccountNumber((string) $data['number'], $types); + $source = $source ?? $this->accountRepository->findByAccountNumber((string)$data['number'], $types); if (null !== $source) { Log::debug(sprintf('Found account: #%d, %s', $source->id, $source->name)); @@ -165,9 +164,9 @@ trait JournalServiceTrait } /** - * @param Account|null $account - * @param array $data - * @param array $types + * @param Account|null $account + * @param array $data + * @param array $types * * @return Account|null */ @@ -191,9 +190,9 @@ trait JournalServiceTrait } /** - * @param Account|null $account - * @param array $data - * @param string $preferredType + * @param Account|null $account + * @param array $data + * @param string $preferredType * * @return Account|null * @throws FireflyException @@ -206,32 +205,33 @@ trait JournalServiceTrait Log::debug( sprintf( 'Was given %s account #%d ("%s") so will simply return that.', - $account->accountType->type, $account->id, $account->name - + $account->accountType->type, + $account->id, + $account->name ) ); } if (null === $account) { - // final attempt, create it. if (AccountType::ASSET === $preferredType) { throw new FireflyException(sprintf('TransactionFactory: Cannot create asset account with these values: %s', json_encode($data))); } // fix name of account if only IBAN is given: - if ('' === (string) $data['name'] && '' !== (string) $data['iban']) { + if ('' === (string)$data['name'] && '' !== (string)$data['iban']) { Log::debug(sprintf('Account name is now IBAN ("%s")', $data['iban'])); $data['name'] = $data['iban']; } // fix name of account if only number is given: - if ('' === (string) $data['name'] && '' !== (string) $data['number']) { + if ('' === (string)$data['name'] && '' !== (string)$data['number']) { Log::debug(sprintf('Account name is now account number ("%s")', $data['number'])); $data['name'] = $data['number']; } // if name is still NULL, return NULL. - if (null === $data['name']) { + if ('' === (string)$data['name']) { + Log::debug('Account name is still NULL, return NULL.'); return null; } - $data['name'] = $data['name'] ?? '(no name)'; + //$data['name'] = $data['name'] ?? '(no name)'; $account = $this->accountRepository->store( [ @@ -257,32 +257,31 @@ trait JournalServiceTrait $metaFactory = app(AccountMetaFactory::class); $metaFactory->create(['account_id' => $account->id, 'name' => 'account_number', 'data' => $data['number']]); } - } return $account; } /** - * @param Account|null $account - * @param array $data - * @param array $types + * @param Account|null $account + * @param array $data + * @param array $types * * @return Account|null */ private function getCashAccount(?Account $account, array $data, array $types): ?Account { // return cash account. - if (null === $account && null === $data['name'] + if (null === $account && '' === (string)$data['name'] && in_array(AccountType::CASH, $types, true)) { $account = $this->accountRepository->getCashAccount(); } - + Log::debug('Cannot return cash account, return input instead.'); return $account; } /** - * @param string $amount + * @param string $amount * * @return string * @throws FireflyException @@ -302,7 +301,7 @@ trait JournalServiceTrait } /** - * @param string|null $amount + * @param string|null $amount * * @return string|null * @codeCoverageIgnore @@ -330,8 +329,8 @@ trait JournalServiceTrait } /** - * @param TransactionJournal $journal - * @param NullArrayObject $data + * @param TransactionJournal $journal + * @param NullArrayObject $data * * @codeCoverageIgnore */ @@ -354,8 +353,8 @@ trait JournalServiceTrait } /** - * @param TransactionJournal $journal - * @param NullArrayObject $data + * @param TransactionJournal $journal + * @param NullArrayObject $data * * @codeCoverageIgnore */ @@ -373,18 +372,18 @@ trait JournalServiceTrait } /** - * @param TransactionJournal $journal - * @param string|null $notes + * @param TransactionJournal $journal + * @param string|null $notes * * @codeCoverageIgnore */ protected function storeNotes(TransactionJournal $journal, ?string $notes): void { - $notes = (string) $notes; + $notes = (string)$notes; $note = $journal->notes()->first(); if ('' !== $notes) { if (null === $note) { - $note = new Note; + $note = new Note(); $note->noteable()->associate($journal); } $note->text = $notes; @@ -395,19 +394,15 @@ trait JournalServiceTrait } if ('' === $notes && null !== $note) { // try to delete existing notes. - try { - $note->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $note->delete(); } } /** * Link tags to journal. * - * @param TransactionJournal $journal - * @param array|null $tags + * @param TransactionJournal $journal + * @param array|null $tags * * @codeCoverageIgnore */ @@ -423,7 +418,7 @@ trait JournalServiceTrait } Log::debug('Start of loop.'); foreach ($tags as $string) { - $string = (string) $string; + $string = (string)$string; Log::debug(sprintf('Now at tag "%s"', $string)); if ('' !== $string) { $tag = $this->tagFactory->findOrCreate($string); diff --git a/app/Services/Internal/Support/LocationServiceTrait.php b/app/Services/Internal/Support/LocationServiceTrait.php index 74b4e6cdf0..4652928a2b 100644 --- a/app/Services/Internal/Support/LocationServiceTrait.php +++ b/app/Services/Internal/Support/LocationServiceTrait.php @@ -33,8 +33,8 @@ use Illuminate\Database\Eloquent\Model; trait LocationServiceTrait { /** - * @param Model $model - * @param array $data + * @param Model $model + * @param array $data * * @return Location|null */ @@ -42,7 +42,7 @@ trait LocationServiceTrait { $data['store_location'] = $data['store_location'] ?? false; if ($data['store_location']) { - $location = new Location; + $location = new Location(); $location->latitude = $data['latitude'] ?? config('firefly.default_location.latitude'); $location->longitude = $data['longitude'] ?? config('firefly.default_location.longitude'); $location->zoom_level = $data['zoom_level'] ?? config('firefly.default_location.zoom_level'); @@ -54,5 +54,4 @@ trait LocationServiceTrait return null; } - } diff --git a/app/Services/Internal/Support/RecurringTransactionTrait.php b/app/Services/Internal/Support/RecurringTransactionTrait.php index c78e035be8..bb7157aa5e 100644 --- a/app/Services/Internal/Support/RecurringTransactionTrait.php +++ b/app/Services/Internal/Support/RecurringTransactionTrait.php @@ -41,6 +41,7 @@ use FireflyIII\Models\RecurrenceTransaction; use FireflyIII\Models\RecurrenceTransactionMeta; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Validation\AccountValidator; +use JsonException; use Log; /** @@ -50,8 +51,8 @@ use Log; trait RecurringTransactionTrait { /** - * @param Recurrence $recurrence - * @param string $note + * @param Recurrence $recurrence + * @param string $note * * @return bool */ @@ -60,11 +61,7 @@ trait RecurringTransactionTrait if ('' === $note) { $dbNote = $recurrence->notes()->first(); if (null !== $dbNote) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $dbNote->delete(); } return true; @@ -81,8 +78,8 @@ trait RecurringTransactionTrait } /** - * @param Recurrence $recurrence - * @param array $repetitions + * @param Recurrence $recurrence + * @param array $repetitions */ protected function createRepetitions(Recurrence $recurrence, array $repetitions): void { @@ -97,18 +94,17 @@ trait RecurringTransactionTrait 'weekend' => $array['weekend'] ?? 1, ] ); - } } /** * Store transactions of a recurring transactions. It's complex but readable. * - * @param Recurrence $recurrence - * @param array $transactions + * @param Recurrence $recurrence + * @param array $transactions * * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ protected function createTransactions(Recurrence $recurrence, array $transactions): void { @@ -145,10 +141,10 @@ trait RecurringTransactionTrait if (!$validator->validateDestination(['id' => $destination->id])) { throw new FireflyException(sprintf('Destination invalid: %s', $validator->destError)); } - if (array_key_exists('foreign_amount', $array) && '' === (string) $array['foreign_amount']) { + if (array_key_exists('foreign_amount', $array) && '' === (string)$array['foreign_amount']) { unset($array['foreign_amount']); } - // See reference nr. 100 + // TODO typeOverrule. The account validator may have a different opinion on the type of the transaction. $transaction = new RecurrenceTransaction( [ 'recurrence_id' => $recurrence->id, @@ -157,52 +153,51 @@ trait RecurringTransactionTrait 'source_id' => $source->id, 'destination_id' => $destination->id, 'amount' => $array['amount'], - 'foreign_amount' => array_key_exists('foreign_amount', $array) ? (string) $array['foreign_amount'] : null, + 'foreign_amount' => array_key_exists('foreign_amount', $array) ? (string)$array['foreign_amount'] : null, 'description' => $array['description'], ] ); $transaction->save(); if (array_key_exists('budget_id', $array)) { - $this->setBudget($transaction, (int) $array['budget_id']); + $this->setBudget($transaction, (int)$array['budget_id']); } if (array_key_exists('bill_id', $array)) { - $this->setBill($transaction, (int) $array['bill_id']); + $this->setBill($transaction, (int)$array['bill_id']); } if (array_key_exists('category_id', $array)) { - $this->setCategory($transaction, (int) $array['category_id']); + $this->setCategory($transaction, (int)$array['category_id']); } // same for piggy bank if (array_key_exists('piggy_bank_id', $array)) { - $this->updatePiggyBank($transaction, (int) $array['piggy_bank_id']); + $this->updatePiggyBank($transaction, (int)$array['piggy_bank_id']); } if (array_key_exists('tags', $array) && is_array($array['tags'])) { $this->updateTags($transaction, $array['tags']); } - } } /** - * @param array $expectedTypes - * @param int|null $accountId - * @param string|null $accountName + * @param array $expectedTypes + * @param int|null $accountId + * @param string|null $accountName * * @return Account */ protected function findAccount(array $expectedTypes, ?int $accountId, ?string $accountName): Account { $result = null; - $accountId = (int) $accountId; - $accountName = (string) $accountName; + $accountId = (int)$accountId; + $accountName = (string)$accountName; /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $repository->setUser($this->user); // if user has submitted an account ID, search for it. - $result = $repository->find((int) $accountId); + $result = $repository->find((int)$accountId); if (null !== $result) { return $result; } @@ -226,11 +221,9 @@ trait RecurringTransactionTrait if (!in_array($expectedType, $cannotCreate, true)) { try { $result = $factory->findOrCreate($accountName, $expectedType); - } catch (FireflyException $e) { Log::error($e->getMessage()); } - } } @@ -238,8 +231,8 @@ trait RecurringTransactionTrait } /** - * @param RecurrenceTransaction $transaction - * @param int $budgetId + * @param RecurrenceTransaction $transaction + * @param int $budgetId */ private function setBudget(RecurrenceTransaction $transaction, int $budgetId): void { @@ -252,7 +245,7 @@ trait RecurringTransactionTrait $meta = $transaction->recurrenceTransactionMeta()->where('name', 'budget_id')->first(); if (null === $meta) { - $meta = new RecurrenceTransactionMeta; + $meta = new RecurrenceTransactionMeta(); $meta->rt_id = $transaction->id; $meta->name = 'budget_id'; } @@ -261,8 +254,8 @@ trait RecurringTransactionTrait } /** - * @param RecurrenceTransaction $transaction - * @param int $billId + * @param RecurrenceTransaction $transaction + * @param int $billId */ private function setBill(RecurrenceTransaction $transaction, int $billId): void { @@ -275,7 +268,7 @@ trait RecurringTransactionTrait $meta = $transaction->recurrenceTransactionMeta()->where('name', 'bill_id')->first(); if (null === $meta) { - $meta = new RecurrenceTransactionMeta; + $meta = new RecurrenceTransactionMeta(); $meta->rt_id = $transaction->id; $meta->name = 'bill_id'; } @@ -284,8 +277,8 @@ trait RecurringTransactionTrait } /** - * @param RecurrenceTransaction $transaction - * @param int $categoryId + * @param RecurrenceTransaction $transaction + * @param int $categoryId * * @throws FireflyException */ @@ -304,7 +297,7 @@ trait RecurringTransactionTrait $meta = $transaction->recurrenceTransactionMeta()->where('name', 'category_id')->first(); if (null === $meta) { - $meta = new RecurrenceTransactionMeta; + $meta = new RecurrenceTransactionMeta(); $meta->rt_id = $transaction->id; $meta->name = 'category_id'; } @@ -313,8 +306,8 @@ trait RecurringTransactionTrait } /** - * @param RecurrenceTransaction $transaction - * @param int $piggyId + * @param RecurrenceTransaction $transaction + * @param int $piggyId */ protected function updatePiggyBank(RecurrenceTransaction $transaction, int $piggyId): void { @@ -338,12 +331,12 @@ trait RecurringTransactionTrait } /** - * @param RecurrenceTransaction $transaction - * @param array $tags + * @param RecurrenceTransaction $transaction + * @param array $tags */ protected function updateTags(RecurrenceTransaction $transaction, array $tags): void { - if (!empty($tags)) { + if (0 !== count($tags)) { /** @var RecurrenceMeta|null $entry */ $entry = $transaction->recurrenceTransactionMeta()->where('name', 'tags')->first(); if (null === $entry) { @@ -352,14 +345,14 @@ trait RecurringTransactionTrait $entry->value = json_encode($tags); $entry->save(); } - if (empty($tags)) { + if (0 === count($tags)) { // delete if present $transaction->recurrenceTransactionMeta()->where('name', 'tags')->delete(); } } /** - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @codeCoverageIgnore */ @@ -369,7 +362,7 @@ trait RecurringTransactionTrait } /** - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @codeCoverageIgnore */ @@ -379,11 +372,8 @@ trait RecurringTransactionTrait /** @var RecurrenceTransaction $transaction */ foreach ($recurrence->recurrenceTransactions as $transaction) { $transaction->recurrenceTransactionMeta()->delete(); - try { - $transaction->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + + $transaction->delete(); } } } diff --git a/app/Services/Internal/Support/TransactionTypeTrait.php b/app/Services/Internal/Support/TransactionTypeTrait.php index b21f9f03dc..518f06a327 100644 --- a/app/Services/Internal/Support/TransactionTypeTrait.php +++ b/app/Services/Internal/Support/TransactionTypeTrait.php @@ -38,7 +38,7 @@ trait TransactionTypeTrait * Get the transaction type. Since this is mandatory, will throw an exception when nothing comes up. Will always * use TransactionType repository. * - * @param string $type + * @param string $type * * @return TransactionType * @throws FireflyException diff --git a/app/Services/Internal/Update/AccountUpdateService.php b/app/Services/Internal/Update/AccountUpdateService.php index 2adaf3c1da..8c177f7732 100644 --- a/app/Services/Internal/Update/AccountUpdateService.php +++ b/app/Services/Internal/Update/AccountUpdateService.php @@ -35,7 +35,7 @@ use Log; /** * Class AccountUpdateService - * See reference nr. 90 + * TODO this service is messy and convoluted. */ class AccountUpdateService { @@ -62,19 +62,11 @@ class AccountUpdateService $this->accountRepository = app(AccountRepositoryInterface::class); } - /** - * @param User $user - */ - public function setUser(User $user): void - { - $this->user = $user; - } - /** * Update account data. * - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @return Account * @throws FireflyException @@ -89,7 +81,7 @@ class AccountUpdateService // find currency, or use default currency instead. if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { - $currency = $this->getCurrency((int) ($data['currency_id'] ?? null), (string) ($data['currency_code'] ?? null)); + $currency = $this->getCurrency((int)($data['currency_id'] ?? null), (string)($data['currency_code'] ?? null)); unset($data['currency_code'], $data['currency_id']); $data['currency_id'] = $currency->id; } @@ -108,7 +100,7 @@ class AccountUpdateService // update note: if (array_key_exists('notes', $data) && null !== $data['notes']) { - $this->updateNote($account, (string) $data['notes']); + $this->updateNote($account, (string)$data['notes']); } // update preferences if inactive: @@ -120,8 +112,16 @@ class AccountUpdateService } /** - * @param Account $account - * @param array $data + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + + /** + * @param Account $account + * @param array $data * * @return Account */ @@ -135,19 +135,19 @@ class AccountUpdateService $account->active = $data['active']; } if (array_key_exists('iban', $data)) { - $account->iban = app('steam')->filterSpaces((string) $data['iban']); + $account->iban = app('steam')->filterSpaces((string)$data['iban']); } // set liability, but account must already be a liability. //$liabilityType = $data['liability_type'] ?? ''; if ($this->isLiability($account) && array_key_exists('liability_type', $data)) { - $type = $this->getAccountType($data['liability_type']); + $type = $this->getAccountType($data['liability_type']); $account->account_type_id = $type->id; } // set liability, alternative method used in v1 layout: if ($this->isLiability($account) && array_key_exists('account_type_id', $data)) { - $type = AccountType::find((int) $data['account_type_id']); + $type = AccountType::find((int)$data['account_type_id']); if (null !== $type && in_array($type->type, config('firefly.valid_liabilities'), true)) { $account->account_type_id = $type->id; @@ -165,7 +165,7 @@ class AccountUpdateService } /** - * @param Account $account + * @param Account $account * * @return bool */ @@ -177,7 +177,7 @@ class AccountUpdateService } /** - * @param string $type + * @param string $type * * @return AccountType */ @@ -187,8 +187,8 @@ class AccountUpdateService } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @return Account */ @@ -208,7 +208,7 @@ class AccountUpdateService return $account; } // get account type ID's because a join and an update is hard: - $oldOrder = (int) $account->order; + $oldOrder = (int)$account->order; $newOrder = $data['order']; Log::debug(sprintf('Order is set to be updated from %s to %s', $oldOrder, $newOrder)); $list = $this->getTypeIds([AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT]); @@ -246,15 +246,15 @@ class AccountUpdateService foreach ($array as $type) { /** @var AccountType $type */ $type = AccountType::whereType($type)->first(); - $return[] = (int) $type->id; + $return[] = (int)$type->id; } return $return; } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data */ private function updateLocation(Account $account, array $data): void { @@ -270,7 +270,7 @@ class AccountUpdateService if (!(null === $data['latitude'] && null === $data['longitude'] && null === $data['zoom_level'])) { $location = $this->accountRepository->getLocation($account); if (null === $location) { - $location = new Location; + $location = new Location(); $location->locatable()->associate($account); } @@ -283,8 +283,8 @@ class AccountUpdateService } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @throws FireflyException */ @@ -308,8 +308,8 @@ class AccountUpdateService } /** - * @param Account $account - * @param array $data + * @param Account $account + * @param array $data * * @throws FireflyException */ @@ -324,7 +324,7 @@ class AccountUpdateService $openingBalance = $data['opening_balance']; $openingBalanceDate = $data['opening_balance_date']; if ('credit' === $direction) { - $this->updateCreditTransaction($account, $openingBalance, $openingBalanceDate); + $this->updateCreditTransaction($account, $direction, $openingBalance, $openingBalanceDate); } } @@ -338,7 +338,7 @@ class AccountUpdateService } /** - * @param Account $account + * @param Account $account * * @throws FireflyException */ @@ -355,12 +355,12 @@ class AccountUpdateService $array = $preference->data; Log::debug('Old array is: ', $array); Log::debug(sprintf('Must remove : %d', $account->id)); - $removeAccountId = (int) $account->id; + $removeAccountId = (int)$account->id; $new = []; foreach ($array as $value) { - if ((int) $value !== $removeAccountId) { + if ((int)$value !== $removeAccountId) { Log::debug(sprintf('Will include: %d', $value)); - $new[] = (int) $value; + $new[] = (int)$value; } } Log::debug('Final new array is', $new); diff --git a/app/Services/Internal/Update/BillUpdateService.php b/app/Services/Internal/Update/BillUpdateService.php index 500538cc44..af0b98644c 100644 --- a/app/Services/Internal/Update/BillUpdateService.php +++ b/app/Services/Internal/Update/BillUpdateService.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Update; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\TransactionCurrencyFactory; use FireflyIII\Models\Bill; use FireflyIII\Models\Rule; @@ -32,6 +33,7 @@ use FireflyIII\Repositories\ObjectGroup\CreatesObjectGroups; use FireflyIII\Services\Internal\Support\BillServiceTrait; use FireflyIII\User; use Illuminate\Support\Collection; +use JsonException; use Log; /** @@ -40,17 +42,18 @@ use Log; */ class BillUpdateService { - use BillServiceTrait, CreatesObjectGroups; + use BillServiceTrait; + use CreatesObjectGroups; protected User $user; /** - * @param Bill $bill - * @param array $data + * @param Bill $bill + * @param array $data * * @return Bill - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException + * @throws FireflyException + * @throws JsonException */ public function update(Bill $bill, array $data): Bill { @@ -58,7 +61,7 @@ class BillUpdateService if (array_key_exists('currency_id', $data) || array_key_exists('currency_code', $data)) { $factory = app(TransactionCurrencyFactory::class); - $currency = $factory->find((int) ($data['currency_id'] ?? null), $data['currency_code'] ?? null) ?? + $currency = $factory->find((int)($data['currency_id'] ?? null), $data['currency_code'] ?? null) ?? app('amount')->getDefaultCurrencyByUser($bill->user); // enable the currency if it isn't. @@ -80,14 +83,14 @@ class BillUpdateService ]; // update note: if (array_key_exists('notes', $data)) { - $this->updateNote($bill, (string) $data['notes']); + $this->updateNote($bill, (string)$data['notes']); } // update order. if (array_key_exists('order', $data)) { // update the order of the piggy bank: - $oldOrder = (int) $bill->order; - $newOrder = (int) ($data['order'] ?? $oldOrder); + $oldOrder = (int)$bill->order; + $newOrder = (int)($data['order'] ?? $oldOrder); if ($oldOrder !== $newOrder) { $this->updateOrder($bill, $oldOrder, $newOrder); } @@ -119,7 +122,7 @@ class BillUpdateService } if (array_key_exists('object_group_id', $data)) { // try also with ID: - $objectGroupId = (int) ($data['object_group_id'] ?? 0); + $objectGroupId = (int)($data['object_group_id'] ?? 0); if (0 !== $objectGroupId) { $objectGroup = $this->findObjectGroupById($objectGroupId); if (null !== $objectGroup) { @@ -139,27 +142,27 @@ class BillUpdateService } /** - * @param Bill $bill - * @param array $data + * @param Bill $bill + * @param array $data * * @return Bill */ private function updateBillProperties(Bill $bill, array $data): Bill { - if (array_key_exists('name', $data) && '' !== (string) $data['name']) { + if (array_key_exists('name', $data) && '' !== (string)$data['name']) { $bill->name = $data['name']; } - if (array_key_exists('amount_min', $data) && '' !== (string) $data['amount_min']) { + if (array_key_exists('amount_min', $data) && '' !== (string)$data['amount_min']) { $bill->amount_min = $data['amount_min']; } - if (array_key_exists('amount_max', $data) && '' !== (string) $data['amount_max']) { + if (array_key_exists('amount_max', $data) && '' !== (string)$data['amount_max']) { $bill->amount_max = $data['amount_max']; } - if (array_key_exists('date', $data) && '' !== (string) $data['date']) { + if (array_key_exists('date', $data) && '' !== (string)$data['date']) { $bill->date = $data['date']; } - if (array_key_exists('repeat_freq', $data) && '' !== (string) $data['repeat_freq']) { + if (array_key_exists('repeat_freq', $data) && '' !== (string)$data['repeat_freq']) { $bill->repeat_freq = $data['repeat_freq']; } if (array_key_exists('skip', $data)) { @@ -183,9 +186,9 @@ class BillUpdateService } /** - * @param Bill $bill - * @param int $oldOrder - * @param int $newOrder + * @param Bill $bill + * @param int $oldOrder + * @param int $newOrder */ private function updateOrder(Bill $bill, int $oldOrder, int $newOrder): void { @@ -203,13 +206,12 @@ class BillUpdateService $bill->order = $newOrder; $bill->save(); } - } /** - * @param Bill $bill - * @param array $oldData - * @param array $newData + * @param Bill $bill + * @param array $oldData + * @param array $newData */ private function updateBillTriggers(Bill $bill, array $oldData, array $newData): void { @@ -228,7 +230,8 @@ class BillUpdateService 'name' => 'description_contains', 'amount_min' => 'amount_more', 'amount_max' => 'amount_less', - 'transaction_currency_name' => 'currency_is']; + 'transaction_currency_name' => 'currency_is', + ]; foreach ($fields as $field => $ruleTriggerKey) { if (!array_key_exists($field, $newData)) { continue; @@ -239,14 +242,13 @@ class BillUpdateService } $this->updateRules($rules, $ruleTriggerKey, $oldData[$field], $newData[$field]); } - } /** - * @param Collection $rules - * @param string $key - * @param string $oldValue - * @param string $newValue + * @param Collection $rules + * @param string $key + * @param string $oldValue + * @param string $newValue */ private function updateRules(Collection $rules, string $key, string $oldValue, string $newValue): void { @@ -269,8 +271,8 @@ class BillUpdateService } /** - * @param Rule $rule - * @param string $key + * @param Rule $rule + * @param string $key * * @return RuleTrigger|null */ diff --git a/app/Services/Internal/Update/CategoryUpdateService.php b/app/Services/Internal/Update/CategoryUpdateService.php index 95128dba5c..e8bc406803 100644 --- a/app/Services/Internal/Update/CategoryUpdateService.php +++ b/app/Services/Internal/Update/CategoryUpdateService.php @@ -51,7 +51,7 @@ class CategoryUpdateService } /** - * @param mixed $user + * @param mixed $user */ public function setUser($user): void { @@ -59,8 +59,8 @@ class CategoryUpdateService } /** - * @param Category $category - * @param array $data + * @param Category $category + * @param array $data * * @return Category * @throws Exception @@ -83,8 +83,8 @@ class CategoryUpdateService } /** - * @param string $oldName - * @param string $newName + * @param string $oldName + * @param string $newName */ private function updateRuleTriggers(string $oldName, string $newName): void { @@ -104,8 +104,8 @@ class CategoryUpdateService } /** - * @param string $oldName - * @param string $newName + * @param string $oldName + * @param string $newName */ private function updateRuleActions(string $oldName, string $newName): void { @@ -125,23 +125,22 @@ class CategoryUpdateService } /** - * @param string $oldName - * @param string $newName + * @param string $oldName + * @param string $newName */ private function updateRecurrences(string $oldName, string $newName): void { - RecurrenceTransactionMeta - ::leftJoin('recurrences_transactions', 'rt_meta.rt_id', '=', 'recurrences_transactions.id') - ->leftJoin('recurrences', 'recurrences.id', '=', 'recurrences_transactions.recurrence_id') - ->where('recurrences.user_id', $this->user->id) - ->where('rt_meta.name', 'category_name') - ->where('rt_meta.value', $oldName) - ->update(['rt_meta.value' => $newName]); + RecurrenceTransactionMeta::leftJoin('recurrences_transactions', 'rt_meta.rt_id', '=', 'recurrences_transactions.id') + ->leftJoin('recurrences', 'recurrences.id', '=', 'recurrences_transactions.recurrence_id') + ->where('recurrences.user_id', $this->user->id) + ->where('rt_meta.name', 'category_name') + ->where('rt_meta.value', $oldName) + ->update(['rt_meta.value' => $newName]); } /** - * @param Category $category - * @param array $data + * @param Category $category + * @param array $data * * @throws Exception */ @@ -154,22 +153,17 @@ class CategoryUpdateService if ('' === $note) { $dbNote = $category->notes()->first(); if (null !== $dbNote) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $dbNote->delete(); } return; } $dbNote = $category->notes()->first(); if (null === $dbNote) { - $dbNote = new Note; + $dbNote = new Note(); $dbNote->noteable()->associate($category); } $dbNote->text = trim($note); $dbNote->save(); } - } diff --git a/app/Services/Internal/Update/CurrencyUpdateService.php b/app/Services/Internal/Update/CurrencyUpdateService.php index 4c6219d97c..bc8372a744 100644 --- a/app/Services/Internal/Update/CurrencyUpdateService.php +++ b/app/Services/Internal/Update/CurrencyUpdateService.php @@ -33,22 +33,22 @@ use FireflyIII\Models\TransactionCurrency; class CurrencyUpdateService { /** - * @param TransactionCurrency $currency - * @param array $data + * @param TransactionCurrency $currency + * @param array $data * * @return TransactionCurrency */ public function update(TransactionCurrency $currency, array $data): TransactionCurrency { - if (array_key_exists('code', $data) && '' !== (string) $data['code']) { + if (array_key_exists('code', $data) && '' !== (string)$data['code']) { $currency->code = $data['code']; } - if (array_key_exists('symbol', $data) && '' !== (string) $data['symbol']) { + if (array_key_exists('symbol', $data) && '' !== (string)$data['symbol']) { $currency->symbol = $data['symbol']; } - if (array_key_exists('name', $data) && '' !== (string) $data['name']) { + if (array_key_exists('name', $data) && '' !== (string)$data['name']) { $currency->name = $data['name']; } @@ -64,5 +64,4 @@ class CurrencyUpdateService return $currency; } - } diff --git a/app/Services/Internal/Update/GroupCloneService.php b/app/Services/Internal/Update/GroupCloneService.php index 5950f62095..3957164e92 100644 --- a/app/Services/Internal/Update/GroupCloneService.php +++ b/app/Services/Internal/Update/GroupCloneService.php @@ -41,7 +41,7 @@ use FireflyIII\Models\TransactionJournalMeta; class GroupCloneService { /** - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return TransactionGroup */ @@ -50,16 +50,16 @@ class GroupCloneService $newGroup = $group->replicate(); $newGroup->save(); foreach ($group->transactionJournals as $journal) { - $this->cloneJournal($journal, $newGroup, (int) $group->id); + $this->cloneJournal($journal, $newGroup, (int)$group->id); } return $newGroup; } /** - * @param TransactionJournal $journal - * @param TransactionGroup $newGroup - * @param int $originalGroup + * @param TransactionJournal $journal + * @param TransactionGroup $newGroup + * @param int $originalGroup */ private function cloneJournal(TransactionJournal $journal, TransactionGroup $newGroup, int $originalGroup): void { @@ -107,17 +107,17 @@ class GroupCloneService // add relation. // TODO clone ALL linked piggy banks /** @var PiggyBankEvent $event */ - $event = $journal->piggyBankEvents()->first(); - if(null !== $event) { + $event = $journal->piggyBankEvents()->first(); + if (null !== $event) { $piggyBank = $event->piggyBank; - $factory = app(PiggyBankEventFactory::class); + $factory = app(PiggyBankEventFactory::class); $factory->create($newJournal, $piggyBank); } } /** - * @param Transaction $transaction - * @param TransactionJournal $newJournal + * @param Transaction $transaction + * @param TransactionJournal $newJournal */ private function cloneTransaction(Transaction $transaction, TransactionJournal $newJournal): void { @@ -128,24 +128,24 @@ class GroupCloneService } /** - * @param Note $note - * @param TransactionJournal $newJournal - * @param int $oldGroupId + * @param Note $note + * @param TransactionJournal $newJournal + * @param int $oldGroupId */ private function cloneNote(Note $note, TransactionJournal $newJournal, int $oldGroupId): void { $newNote = $note->replicate(); $newNote->text .= sprintf( - "\n\n%s", trans('firefly.clones_journal_x', ['description' => $newJournal->description, 'id' => $oldGroupId]) + "\n\n%s", + trans('firefly.clones_journal_x', ['description' => $newJournal->description, 'id' => $oldGroupId]) ); $newNote->noteable_id = $newJournal->id; $newNote->save(); - } /** - * @param TransactionJournalMeta $meta - * @param TransactionJournal $newJournal + * @param TransactionJournalMeta $meta + * @param TransactionJournal $newJournal */ private function cloneMeta(TransactionJournalMeta $meta, TransactionJournal $newJournal): void { diff --git a/app/Services/Internal/Update/GroupUpdateService.php b/app/Services/Internal/Update/GroupUpdateService.php index 9a7e1151d2..7eeb574321 100644 --- a/app/Services/Internal/Update/GroupUpdateService.php +++ b/app/Services/Internal/Update/GroupUpdateService.php @@ -29,6 +29,7 @@ use FireflyIII\Factory\TransactionJournalFactory; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; use FireflyIII\Services\Internal\Destroy\JournalDestroyService; +use JsonException; use Log; /** @@ -39,8 +40,8 @@ class GroupUpdateService /** * Update a transaction group. * - * @param TransactionGroup $transactionGroup - * @param array $data + * @param TransactionGroup $transactionGroup + * @param array $data * * @return TransactionGroup * @throws DuplicateTransactionException @@ -60,7 +61,7 @@ class GroupUpdateService } - if (empty($transactions)) { + if (0 === count($transactions)) { Log::debug('No transactions submitted, do nothing.'); return $transactionGroup; @@ -96,7 +97,7 @@ class GroupUpdateService /** @var string $deletedId */ foreach ($result as $deletedId) { /** @var TransactionJournal $journal */ - $journal = $transactionGroup->transactionJournals()->find((int) $deletedId); + $journal = $transactionGroup->transactionJournals()->find((int)$deletedId); /** @var JournalDestroyService $service */ $service = app(JournalDestroyService::class); $service->destroy($journal); @@ -112,14 +113,14 @@ class GroupUpdateService /** * Update single journal. * - * @param TransactionGroup $transactionGroup - * @param TransactionJournal $journal - * @param array $data + * @param TransactionGroup $transactionGroup + * @param TransactionJournal $journal + * @param array $data */ private function updateTransactionJournal(TransactionGroup $transactionGroup, TransactionJournal $journal, array $data): void { Log::debug(sprintf('Now in %s', __METHOD__)); - if (empty($data)) { + if (0 === count($data)) { return; } if (1 === count($data) && array_key_exists('transaction_journal_id', $data)) { @@ -134,8 +135,8 @@ class GroupUpdateService } /** - * @param TransactionGroup $transactionGroup - * @param array $transactions + * @param TransactionGroup $transactionGroup + * @param array $transactions * * @return array * @throws DuplicateTransactionException @@ -147,12 +148,12 @@ class GroupUpdateService // updated or created transaction journals: $updated = []; /** - * @var int $index + * @var int $index * @var array $transaction */ foreach ($transactions as $index => $transaction) { Log::debug(sprintf('Now at #%d of %d', ($index + 1), count($transactions)), $transaction); - $journalId = (int) ($transaction['transaction_journal_id'] ?? 0); + $journalId = (int)($transaction['transaction_journal_id'] ?? 0); /** @var TransactionJournal|null $journal */ $journal = $transactionGroup->transactionJournals()->find($journalId); if (null === $journal) { @@ -190,14 +191,14 @@ class GroupUpdateService } /** - * @param TransactionGroup $transactionGroup - * @param array $data + * @param TransactionGroup $transactionGroup + * @param array $data * * @return TransactionJournal|null * * @throws DuplicateTransactionException * @throws FireflyException - * @throws \JsonException + * @throws JsonException */ private function createTransactionJournal(TransactionGroup $transactionGroup, array $data): ?TransactionJournal { @@ -227,5 +228,4 @@ class GroupUpdateService return $collection->first(); } - } diff --git a/app/Services/Internal/Update/JournalUpdateService.php b/app/Services/Internal/Update/JournalUpdateService.php index adb6525aaa..4b06e72366 100644 --- a/app/Services/Internal/Update/JournalUpdateService.php +++ b/app/Services/Internal/Update/JournalUpdateService.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Services\Internal\Update; use Carbon\Carbon; +use Carbon\Exceptions\InvalidDateException; use Exception; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\TagFactory; @@ -82,14 +83,26 @@ class JournalUpdateService $this->tagFactory = app(TagFactory::class); $this->accountRepository = app(AccountRepositoryInterface::class); $this->currencyRepository = app(CurrencyRepositoryInterface::class); - $this->metaString = ['sepa_cc', 'sepa_ct_op', 'sepa_ct_id', 'sepa_db', 'sepa_country', 'sepa_ep', 'sepa_ci', 'sepa_batch_id', - 'recurrence_id', - 'internal_reference', 'bunq_payment_id', 'external_id', 'external_url']; + $this->metaString = [ + 'sepa_cc', + 'sepa_ct_op', + 'sepa_ct_id', + 'sepa_db', + 'sepa_country', + 'sepa_ep', + 'sepa_ci', + 'sepa_batch_id', + 'recurrence_id', + 'internal_reference', + 'bunq_payment_id', + 'external_id', + 'external_url', + ]; $this->metaDate = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date',]; } /** - * @param array $data + * @param array $data */ public function setData(array $data): void { @@ -97,7 +110,7 @@ class JournalUpdateService } /** - * @param TransactionGroup $transactionGroup + * @param TransactionGroup $transactionGroup */ public function setTransactionGroup(TransactionGroup $transactionGroup): void { @@ -114,7 +127,7 @@ class JournalUpdateService } /** - * @param TransactionJournal $transactionJournal + * @param TransactionJournal $transactionJournal */ public function setTransactionJournal(TransactionJournal $transactionJournal): void { @@ -219,14 +232,14 @@ class JournalUpdateService $result = $validator->validateSource(['id' => $sourceId]); Log::debug(sprintf('hasValidSourceAccount(%d, "%s") will return %s', $sourceId, $sourceName, var_export($result, true))); - // See reference nr. 95 + // TODO typeoverrule the account validator may have a different opinion on the transaction type. // validate submitted info: return $result; } /** - * @param array $fields + * @param array $fields * * @return bool */ @@ -313,7 +326,7 @@ class JournalUpdateService $result = $validator->validateDestination(['id' => $destId]); Log::debug(sprintf('hasValidDestinationAccount(%d, "%s") will return %s', $destId, $destName, var_export($result, true))); - // See reference nr. 96 + // TODO typeOverrule: the account validator may have another opinion on the transaction type. // validate submitted info: return $result; @@ -360,7 +373,7 @@ class JournalUpdateService } $sourceInfo = [ - 'id' => (int) ($this->data['source_id'] ?? null), + 'id' => (int)($this->data['source_id'] ?? null), 'name' => $this->data['source_name'] ?? null, 'iban' => $this->data['source_iban'] ?? null, 'number' => $this->data['source_number'] ?? null, @@ -425,7 +438,7 @@ class JournalUpdateService } $destInfo = [ - 'id' => (int) ($this->data['destination_id'] ?? null), + 'id' => (int)($this->data['destination_id'] ?? null), 'name' => $this->data['destination_name'] ?? null, 'iban' => $this->data['destination_iban'] ?? null, 'number' => $this->data['destination_number'] ?? null, @@ -456,7 +469,9 @@ class JournalUpdateService Log::debug( sprintf( 'Trying to change journal #%d from a %s to a %s.', - $this->transactionJournal->id, $this->transactionJournal->transactionType->type, $type + $this->transactionJournal->id, + $this->transactionJournal->transactionType->type, + $type ) ); @@ -483,13 +498,13 @@ class JournalUpdateService { $type = $this->transactionJournal->transactionType->type; if (( - array_key_exists('bill_id', $this->data) - || array_key_exists('bill_name', $this->data) - ) - && TransactionType::WITHDRAWAL === $type + array_key_exists('bill_id', $this->data) + || array_key_exists('bill_name', $this->data) + ) + && TransactionType::WITHDRAWAL === $type ) { - $billId = (int) ($this->data['bill_id'] ?? 0); - $billName = (string) ($this->data['bill_name'] ?? ''); + $billId = (int)($this->data['bill_id'] ?? 0); + $billName = (string)($this->data['bill_name'] ?? ''); $bill = $this->billRepository->findBill($billId, $billName); $this->transactionJournal->bill_id = $bill?->id; Log::debug('Updated bill ID'); @@ -499,11 +514,11 @@ class JournalUpdateService /** * Update journal generic field. Cannot be set to NULL. * - * @param string $fieldName + * @param string $fieldName */ private function updateField(string $fieldName): void { - if (array_key_exists($fieldName, $this->data) && '' !== (string) $this->data[$fieldName]) { + if (array_key_exists($fieldName, $this->data) && '' !== (string)$this->data[$fieldName]) { $value = $this->data[$fieldName]; if ('date' === $fieldName) { @@ -580,7 +595,7 @@ class JournalUpdateService { // update notes. if ($this->hasFields(['notes'])) { - $notes = '' === (string) $this->data['notes'] ? null : $this->data['notes']; + $notes = '' === (string)$this->data['notes'] ? null : $this->data['notes']; $this->storeNotes($this->transactionJournal, $notes); } } @@ -637,10 +652,9 @@ class JournalUpdateService foreach ($this->metaDate as $field) { if ($this->hasFields([$field])) { try { - $value = '' === (string) $this->data[$field] ? null : new Carbon($this->data[$field]); - } catch (Exception $e) { // @phpstan-ignore-line + $value = '' === (string)$this->data[$field] ? null : new Carbon($this->data[$field]); + } catch (InvalidDateException $e) { Log::debug(sprintf('%s is not a valid date value: %s', $this->data[$field], $e->getMessage())); - return; } Log::debug(sprintf('Field "%s" is present ("%s"), try to update it.', $field, $value)); diff --git a/app/Services/Internal/Update/RecurrenceUpdateService.php b/app/Services/Internal/Update/RecurrenceUpdateService.php index f099d2ec09..dfce5f715f 100644 --- a/app/Services/Internal/Update/RecurrenceUpdateService.php +++ b/app/Services/Internal/Update/RecurrenceUpdateService.php @@ -42,17 +42,18 @@ use Log; */ class RecurrenceUpdateService { - use TransactionTypeTrait, RecurringTransactionTrait; + use TransactionTypeTrait; + use RecurringTransactionTrait; private User $user; /** * Updates a recurrence. * - * See reference nr. 88 + * TODO if the user updates the type, the accounts must be validated again. * - * @param Recurrence $recurrence - * @param array $data + * @param Recurrence $recurrence + * @param array $data * * @return Recurrence * @throws FireflyException @@ -78,7 +79,7 @@ class RecurrenceUpdateService $recurrence->repetitions = 0; } if (array_key_exists('nr_of_repetitions', $info)) { - if (0 !== (int) $info['nr_of_repetitions']) { + if (0 !== (int)$info['nr_of_repetitions']) { $recurrence->repeat_until = null; } $recurrence->repetitions = $info['nr_of_repetitions']; @@ -114,8 +115,8 @@ class RecurrenceUpdateService } /** - * @param Recurrence $recurrence - * @param string $text + * @param Recurrence $recurrence + * @param string $text */ private function setNoteText(Recurrence $recurrence, string $text): void { @@ -131,25 +132,21 @@ class RecurrenceUpdateService return; } if (null !== $dbNote && '' === $text) { - try { - $dbNote->delete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + $dbNote->delete(); } } /** * - * @param Recurrence $recurrence - * @param array $repetitions + * @param Recurrence $recurrence + * @param array $repetitions * * @throws FireflyException */ private function updateRepetitions(Recurrence $recurrence, array $repetitions): void { $originalCount = $recurrence->recurrenceRepetitions()->count(); - if (empty($repetitions)) { + if (0 === count($repetitions)) { // wont drop repetition, rather avoid. return; } @@ -186,8 +183,8 @@ class RecurrenceUpdateService } /** - * @param Recurrence $recurrence - * @param array $data + * @param Recurrence $recurrence + * @param array $data * * @return RecurrenceRepetition|null */ @@ -200,11 +197,12 @@ class RecurrenceUpdateService return $recurrence->recurrenceRepetitions()->first(); } // find it: - $fields = ['id' => 'id', - 'type' => 'repetition_type', - 'moment' => 'repetition_moment', - 'skip' => 'repetition_skip', - 'weekend' => 'weekend', + $fields = [ + 'id' => 'id', + 'type' => 'repetition_type', + 'moment' => 'repetition_moment', + 'skip' => 'repetition_skip', + 'weekend' => 'weekend', ]; $query = $recurrence->recurrenceRepetitions(); foreach ($fields as $field => $column) { @@ -217,17 +215,17 @@ class RecurrenceUpdateService } /** - * See reference nr. 89 + * TODO this method is very complex. * - * @param Recurrence $recurrence - * @param array $transactions + * @param Recurrence $recurrence + * @param array $transactions * * @throws FireflyException */ private function updateTransactions(Recurrence $recurrence, array $transactions): void { $originalCount = $recurrence->recurrenceTransactions()->count(); - if (empty($transactions)) { + if (0 === count($transactions)) { // wont drop transactions, rather avoid. return; } @@ -257,7 +255,7 @@ class RecurrenceUpdateService unset($current['currency_id'], $current['currency_code']); } if (null !== $currency) { - $current['currency_id'] = (int) $currency->id; + $current['currency_id'] = (int)$currency->id; } if (array_key_exists('foreign_currency_id', $current) || array_key_exists('foreign_currency_code', $current)) { $foreignCurrency = $currencyFactory->find($current['foreign_currency_id'] ?? null, $currency['foreign_currency_code'] ?? null); @@ -266,7 +264,7 @@ class RecurrenceUpdateService unset($current['foreign_currency_id'], $currency['foreign_currency_code']); } if (null !== $foreignCurrency) { - $current['foreign_currency_id'] = (int) $foreignCurrency->id; + $current['foreign_currency_id'] = (int)$foreignCurrency->id; } // update fields @@ -287,35 +285,35 @@ class RecurrenceUpdateService } // update meta data if (array_key_exists('budget_id', $current)) { - $this->setBudget($match, (int) $current['budget_id']); + $this->setBudget($match, (int)$current['budget_id']); } if (array_key_exists('bill_id', $current)) { - $this->setBill($match, (int) $current['bill_id']); + $this->setBill($match, (int)$current['bill_id']); } // reset category if name is set but empty: // can be removed when v1 is retired. - if (array_key_exists('category_name', $current) && '' === (string) $current['category_name']) { + if (array_key_exists('category_name', $current) && '' === (string)$current['category_name']) { $current['category_name'] = null; $current['category_id'] = 0; } if (array_key_exists('category_id', $current)) { - $this->setCategory($match, (int) $current['category_id']); + $this->setCategory($match, (int)$current['category_id']); } if (array_key_exists('tags', $current) && is_array($current['tags'])) { $this->updateTags($match, $current['tags']); } if (array_key_exists('piggy_bank_id', $current)) { - $this->updatePiggyBank($match, (int) $current['piggy_bank_id']); + $this->updatePiggyBank($match, (int)$current['piggy_bank_id']); } } } } /** - * @param Recurrence $recurrence - * @param array $data + * @param Recurrence $recurrence + * @param array $data * * @return RecurrenceTransaction|null */ diff --git a/app/Services/Password/PwndVerifierV2.php b/app/Services/Password/PwndVerifierV2.php index 8dc0f56784..c4396f4cae 100644 --- a/app/Services/Password/PwndVerifierV2.php +++ b/app/Services/Password/PwndVerifierV2.php @@ -1,4 +1,5 @@ sprintf('Firefly III v%s', config('firefly.version')), 'Add-Padding' => 'true', ], - 'timeout' => 3.1415]; + 'timeout' => 3.1415, + ]; Log::debug(sprintf('hash prefix is %s', $prefix)); Log::debug(sprintf('rest is %s', $rest)); @@ -71,12 +72,7 @@ class PwndVerifierV2 implements Verifier if (404 === $res->getStatusCode()) { return true; } - try { - $strpos = stripos($res->getBody()->getContents(), $rest); - } catch (RuntimeException $e) { // @phpstan-ignore-line - Log::error(sprintf('Could not get body from Pwnd result: %s', $e->getMessage())); - $strpos = false; - } + $strpos = stripos($res->getBody()->getContents(), $rest); if (false === $strpos) { Log::debug(sprintf('%s was not found in result body. Return true.', $rest)); diff --git a/app/Services/Password/Verifier.php b/app/Services/Password/Verifier.php index 0883aeaf64..ac688d7d6d 100644 --- a/app/Services/Password/Verifier.php +++ b/app/Services/Password/Verifier.php @@ -1,4 +1,5 @@ message->sent = true; + $this->message->save(); try { $signature = $signatureGenerator->generate($this->message); } catch (FireflyException $e) { Log::error('Did not send message because of a Firefly III Exception.'); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); - $attempt = new WebhookAttempt; + $attempt = new WebhookAttempt(); $attempt->webhookMessage()->associate($this->message); $attempt->status_code = 0; $attempt->logs = sprintf('Exception: %s', $e->getMessage()); @@ -83,7 +85,7 @@ class StandardWebhookSender implements WebhookSenderInterface Log::error('Did not send message because of a JSON error.'); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); - $attempt = new WebhookAttempt; + $attempt = new WebhookAttempt(); $attempt->webhookMessage()->associate($this->message); $attempt->status_code = 0; $attempt->logs = sprintf('Json error: %s', $e->getMessage()); @@ -105,11 +107,10 @@ class StandardWebhookSender implements WebhookSenderInterface 'timeout' => 10, ], ]; - $client = new Client; + $client = new Client(); try { $res = $client->request('POST', $this->message->webhook->url, $options); - $this->message->sent = true; - } catch (RequestException $e) { + } catch (RequestException|ConnectException $e) { Log::error($e->getMessage()); Log::error($e->getTraceAsString()); @@ -119,7 +120,7 @@ class StandardWebhookSender implements WebhookSenderInterface $this->message->sent = false; $this->message->save(); - $attempt = new WebhookAttempt; + $attempt = new WebhookAttempt(); $attempt->webhookMessage()->associate($this->message); $attempt->status_code = $e->hasResponse() ? $e->getResponse()->getStatusCode() : 0; $attempt->logs = $logs; @@ -127,6 +128,7 @@ class StandardWebhookSender implements WebhookSenderInterface return; } + $this->message->sent = true; $this->message->save(); Log::debug(sprintf('Webhook message #%d was sent. Status code %d', $this->message->id, $res->getStatusCode())); diff --git a/app/Services/Webhook/WebhookSenderInterface.php b/app/Services/Webhook/WebhookSenderInterface.php index 6b827fa9d0..e60aaf1fca 100644 --- a/app/Services/Webhook/WebhookSenderInterface.php +++ b/app/Services/Webhook/WebhookSenderInterface.php @@ -41,7 +41,7 @@ interface WebhookSenderInterface public function send(): void; /** - * @param WebhookMessage $message + * @param WebhookMessage $message */ public function setMessage(WebhookMessage $message): void; } diff --git a/app/Support/Amount.php b/app/Support/Amount.php index 6ed95c2833..22afd97785 100644 --- a/app/Support/Amount.php +++ b/app/Support/Amount.php @@ -29,8 +29,9 @@ use FireflyIII\Models\TransactionCurrency; use FireflyIII\User; use Illuminate\Contracts\Encryption\DecryptException; use Illuminate\Support\Collection; -use JsonException; use NumberFormatter; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class Amount. @@ -67,7 +68,6 @@ class Amount * @return string * * @throws FireflyException - * @noinspection MoreThanThreeArgumentsInspection */ public function formatFlat(string $symbol, int $decimalPlaces, string $amount, bool $coloured = null): string { @@ -114,12 +114,12 @@ class Amount /** * @return string * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function getCurrencyCode(): string { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('getCurrencyCode'); if ($cache->has()) { return $cache->get(); @@ -140,7 +140,6 @@ class Amount /** * @return TransactionCurrency * @throws FireflyException - * @throws JsonException */ public function getDefaultCurrency(): TransactionCurrency { @@ -158,7 +157,7 @@ class Amount */ public function getDefaultCurrencyByUser(User $user): TransactionCurrency { - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty('getDefaultCurrency'); $cache->addProperty($user->id); if ($cache->has()) { diff --git a/app/Support/Authentication/RemoteUserGuard.php b/app/Support/Authentication/RemoteUserGuard.php index b5b0235b62..b22453f967 100644 --- a/app/Support/Authentication/RemoteUserGuard.php +++ b/app/Support/Authentication/RemoteUserGuard.php @@ -48,8 +48,7 @@ class RemoteUserGuard implements Guard * @param UserProvider $provider * @param Application $app */ - // @phpstan-ignore-next-line - public function __construct(UserProvider $provider, Application $app) // @phpstan-ignore-line + public function __construct(UserProvider $provider, Application $app) { /** @var Request $request */ $request = $app->get('request'); @@ -144,7 +143,7 @@ class RemoteUserGuard implements Guard /** * @inheritDoc */ - public function hasUser() + public function hasUser(): bool { Log::debug(sprintf('Now at %s', __METHOD__)); // TODO: Implement hasUser() method. diff --git a/app/Support/Authentication/RemoteUserProvider.php b/app/Support/Authentication/RemoteUserProvider.php index c67555b5a9..835fd0a500 100644 --- a/app/Support/Authentication/RemoteUserProvider.php +++ b/app/Support/Authentication/RemoteUserProvider.php @@ -37,7 +37,6 @@ use Str; */ class RemoteUserProvider implements UserProvider { - /** * @inheritDoc */ @@ -65,7 +64,7 @@ class RemoteUserProvider implements UserProvider ] ); // if this is the first user, give them admin as well. - if(1 === User::count()) { + if (1 === User::count()) { $roleObject = Role::where('name', 'owner')->first(); $user->roles()->attach($roleObject); } diff --git a/app/Support/Binder/AccountList.php b/app/Support/Binder/AccountList.php index b6f09d676b..4d2c2b9e43 100644 --- a/app/Support/Binder/AccountList.php +++ b/app/Support/Binder/AccountList.php @@ -1,4 +1,5 @@ check()) { - $collection = new Collection; + $collection = new Collection(); if ('allAssetAccounts' === $value) { /** @var Collection $collection */ $collection = auth()->user()->accounts() @@ -70,6 +70,6 @@ class AccountList implements BinderInterface } } Log::error(sprintf('Trying to show account list (%s), but user is not logged in or list is empty.', $route->uri)); - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } } diff --git a/app/Support/Binder/BinderInterface.php b/app/Support/Binder/BinderInterface.php index 1aaefe4c30..e0b42449d1 100644 --- a/app/Support/Binder/BinderInterface.php +++ b/app/Support/Binder/BinderInterface.php @@ -1,4 +1,5 @@ check()) { - if ('allBudgets' === $value) { return auth()->user()->budgets()->where('active', true) ->orderBy('order', 'ASC') @@ -55,9 +54,9 @@ class BudgetList implements BinderInterface $list = array_unique(array_map('\intval', explode(',', $value))); - if (empty($list)) { - Log::warning('Budget list count is zero, return 404.'); - throw new NotFoundHttpException; + if (0 === count($list)) { + app('log')->warning('Budget list count is zero, return 404.'); + throw new NotFoundHttpException(); } @@ -69,15 +68,14 @@ class BudgetList implements BinderInterface // add empty budget if applicable. if (in_array(0, $list, true)) { - $collection->push(new Budget); + $collection->push(new Budget()); } if ($collection->count() > 0) { - return $collection; } } - Log::warning('BudgetList fallback to 404.'); - throw new NotFoundHttpException; + app('log')->warning('BudgetList fallback to 404.'); + throw new NotFoundHttpException(); } } diff --git a/app/Support/Binder/CLIToken.php b/app/Support/Binder/CLIToken.php index 7877c20280..e26a775aae 100644 --- a/app/Support/Binder/CLIToken.php +++ b/app/Support/Binder/CLIToken.php @@ -34,10 +34,9 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; */ class CLIToken implements BinderInterface { - /** - * @param string $value - * @param Route $route + * @param string $value + * @param Route $route * * @return mixed * @throws FireflyException @@ -49,7 +48,7 @@ class CLIToken implements BinderInterface $users = $repository->all(); // check for static token - if ($value === config('firefly.static_cron_token') && 32 === strlen((string) config('firefly.static_cron_token'))) { + if ($value === config('firefly.static_cron_token') && 32 === strlen((string)config('firefly.static_cron_token'))) { return $value; } @@ -62,6 +61,6 @@ class CLIToken implements BinderInterface } } Log::error(sprintf('Recognized no users by access token "%s"', $value)); - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } } diff --git a/app/Support/Binder/CategoryList.php b/app/Support/Binder/CategoryList.php index 56c2f0ce34..e37c23b8a0 100644 --- a/app/Support/Binder/CategoryList.php +++ b/app/Support/Binder/CategoryList.php @@ -1,4 +1,5 @@ push(new Category); + $collection->push(new Category()); } if ($collection->count() > 0) { return $collection; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } } diff --git a/app/Support/Binder/CurrencyCode.php b/app/Support/Binder/CurrencyCode.php index 50ecd16b34..7afbfc238b 100644 --- a/app/Support/Binder/CurrencyCode.php +++ b/app/Support/Binder/CurrencyCode.php @@ -1,4 +1,5 @@ user()->id, $e->getMessage())); - throw new NotFoundHttpException; + } catch (InvalidDateException $e) { + $message = sprintf('Could not parse date "%s" for user #%d: %s', $value, auth()->user()->id, $e->getMessage()); + Log::error($message); + throw new NotFoundHttpException($message, $e); } return $result; diff --git a/app/Support/Binder/DynamicConfigKey.php b/app/Support/Binder/DynamicConfigKey.php index a9a6bc0730..03d5c58133 100644 --- a/app/Support/Binder/DynamicConfigKey.php +++ b/app/Support/Binder/DynamicConfigKey.php @@ -31,7 +31,6 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; */ class DynamicConfigKey { - public static array $accepted = [ 'configuration.is_demo_site', @@ -41,8 +40,8 @@ class DynamicConfigKey ]; /** - * @param string $value - * @param Route $route + * @param string $value + * @param Route $route * * @return string * @throws NotFoundHttpException @@ -52,7 +51,6 @@ class DynamicConfigKey if (in_array($value, self::$accepted, true)) { return $value; } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } - } diff --git a/app/Support/Binder/EitherConfigKey.php b/app/Support/Binder/EitherConfigKey.php index 476ac8613e..a1638f7dfe 100644 --- a/app/Support/Binder/EitherConfigKey.php +++ b/app/Support/Binder/EitherConfigKey.php @@ -57,8 +57,8 @@ class EitherConfigKey ]; /** - * @param string $value - * @param Route $route + * @param string $value + * @param Route $route * * @return string * @throws NotFoundHttpException @@ -68,6 +68,6 @@ class EitherConfigKey if (in_array($value, self::$static, true) || in_array($value, DynamicConfigKey::$accepted, true)) { return $value; } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } } diff --git a/app/Support/Binder/JournalList.php b/app/Support/Binder/JournalList.php index cda7cc3c17..4efbbf2c09 100644 --- a/app/Support/Binder/JournalList.php +++ b/app/Support/Binder/JournalList.php @@ -1,4 +1,5 @@ withCategoryInformation()->withBudgetInformation()->withTagInformation()->withAccountInformation(); $collector->setJournalIds($list); $result = $collector->getExtractedJournals(); - if (empty($result)) { - throw new NotFoundHttpException; + if (0 === count($result)) { + throw new NotFoundHttpException(); } return $result; } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** - * @param string $value + * @param string $value * * @return array */ protected static function parseList(string $value): array { $list = array_unique(array_map('\intval', explode(',', $value))); - if (empty($list)) { - throw new NotFoundHttpException; + if (0 === count($list)) { + throw new NotFoundHttpException(); } return $list; diff --git a/app/Support/Binder/TagList.php b/app/Support/Binder/TagList.php index daa29e434e..8b432a07d0 100644 --- a/app/Support/Binder/TagList.php +++ b/app/Support/Binder/TagList.php @@ -1,4 +1,5 @@ check()) { - if ('allTags' === $value) { return auth()->user()->tags() ->orderBy('tag', 'ASC') @@ -53,9 +53,9 @@ class TagList implements BinderInterface $list = array_unique(array_map('\strtolower', explode(',', $value))); Log::debug('List of tags is', $list); - if (empty($list)) { + if (0 === count($list)) { Log::error('Tag list is empty.'); - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } @@ -69,7 +69,7 @@ class TagList implements BinderInterface if (in_array(strtolower($tag->tag), $list, true)) { return true; } - if (in_array((string) $tag->id, $list, true)) { + if (in_array((string)$tag->id, $list, true)) { return true; } @@ -82,6 +82,6 @@ class TagList implements BinderInterface } } Log::error('TagList: user is not logged in.'); - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } } diff --git a/app/Support/Binder/TagOrId.php b/app/Support/Binder/TagOrId.php index 42e33edd0e..12ecd26c0f 100644 --- a/app/Support/Binder/TagOrId.php +++ b/app/Support/Binder/TagOrId.php @@ -1,4 +1,5 @@ findByTag($value); if (null === $result) { - $result = $repository->find((int) $value); + $result = $repository->find((int)$value); } if (null !== $result) { return $result; } Log::error('TagOrId: tag not found.'); - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } Log::error('TagOrId: user is not logged in.'); - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } } diff --git a/app/Support/CacheProperties.php b/app/Support/CacheProperties.php index 37a1db4cb3..df7adf5809 100644 --- a/app/Support/CacheProperties.php +++ b/app/Support/CacheProperties.php @@ -1,4 +1,5 @@ properties = new Collection; + $this->properties = new Collection(); if (auth()->check()) { $this->addProperty(auth()->user()->id); $this->addProperty(app('preferences')->lastActivity()); @@ -49,7 +50,7 @@ class CacheProperties } /** - * @param mixed $property + * @param mixed $property */ public function addProperty($property): void { @@ -95,14 +96,14 @@ class CacheProperties $content .= json_encode($property, JSON_THROW_ON_ERROR); } catch (JsonException $e) { // @ignoreException - $content .= hash('sha256', (string) time()); + $content .= hash('sha256', (string)time()); } } $this->hash = substr(hash('sha256', $content), 0, 16); } /** - * @param mixed $data + * @param mixed $data */ public function store($data): void { diff --git a/app/Support/Chart/Budget/FrontpageChartGenerator.php b/app/Support/Chart/Budget/FrontpageChartGenerator.php index 0163a4b30d..633b339ddf 100644 --- a/app/Support/Chart/Budget/FrontpageChartGenerator.php +++ b/app/Support/Chart/Budget/FrontpageChartGenerator.php @@ -1,4 +1,5 @@ budgetRepository->getActiveBudgets(); $data = [ - ['label' => (string) trans('firefly.spent_in_budget'), 'entries' => [], 'type' => 'bar'], - ['label' => (string) trans('firefly.left_to_spend'), 'entries' => [], 'type' => 'bar'], - ['label' => (string) trans('firefly.overspent'), 'entries' => [], 'type' => 'bar'], + ['label' => (string)trans('firefly.spent_in_budget'), 'entries' => [], 'type' => 'bar'], + ['label' => (string)trans('firefly.left_to_spend'), 'entries' => [], 'type' => 'bar'], + ['label' => (string)trans('firefly.overspent'), 'entries' => [], 'type' => 'bar'], ]; // loop al budgets: @@ -83,8 +85,8 @@ class FrontpageChartGenerator * When no limits are present, the time range is used to collect information on money spent. * If limits are present, each limit is processed individually. * - * @param array $data - * @param Budget $budget + * @param array $data + * @param Budget $budget * * @return array */ @@ -105,8 +107,8 @@ class FrontpageChartGenerator * When no limits are present, the expenses of the whole period are collected and grouped. * This is grouped per currency. Because there is no limit set, "left to spend" and "overspent" are empty. * - * @param array $data - * @param Budget $budget + * @param array $data + * @param Budget $budget * * @return array */ @@ -127,9 +129,9 @@ class FrontpageChartGenerator /** * If a budget has budget limit, each limit is processed individually. * - * @param array $data - * @param Budget $budget - * @param Collection $limits + * @param array $data + * @param Budget $budget + * @param Collection $limits * * @return array */ @@ -146,9 +148,9 @@ class FrontpageChartGenerator /** * For each limit, the expenses from the time range of the limit are collected. Each row from the result is processed individually. * - * @param array $data - * @param Budget $budget - * @param BudgetLimit $limit + * @param array $data + * @param Budget $budget + * @param BudgetLimit $limit * * @return array */ @@ -158,7 +160,7 @@ class FrontpageChartGenerator /** @var array $entry */ foreach ($spent as $entry) { // only spent the entry where the entry's currency matches the budget limit's currency - if ($entry['currency_id'] === (int) $limit->transaction_currency_id) { + if ($entry['currency_id'] === (int)$limit->transaction_currency_id) { $data = $this->processRow($data, $budget, $limit, $entry); } } @@ -172,10 +174,10 @@ class FrontpageChartGenerator * Each one is added to the $data array. If the limit's date range is different from the global $start and $end dates, * for example when a limit only partially falls into this month, the title is expanded to clarify. * - * @param array $data - * @param Budget $budget - * @param BudgetLimit $limit - * @param array $entry + * @param array $data + * @param Budget $budget + * @param BudgetLimit $limit + * @param array $entry * * @return array */ @@ -201,7 +203,7 @@ class FrontpageChartGenerator } /** - * @param Carbon $end + * @param Carbon $end */ public function setEnd(Carbon $end): void { @@ -209,7 +211,7 @@ class FrontpageChartGenerator } /** - * @param Carbon $start + * @param Carbon $start */ public function setStart(Carbon $start): void { @@ -219,8 +221,8 @@ class FrontpageChartGenerator /** * A basic setter for the user. Also updates the repositories with the right user. * - * @param User $user - * @throws \FireflyIII\Exceptions\FireflyException + * @param User $user + * @throws FireflyException */ public function setUser(User $user): void { @@ -230,6 +232,6 @@ class FrontpageChartGenerator $this->opsRepository->setUser($user); $locale = app('steam')->getLocale(); - $this->monthAndDayFormat = (string) trans('config.month_and_day_js', [], $locale); + $this->monthAndDayFormat = (string)trans('config.month_and_day_js', [], $locale); } } diff --git a/app/Support/Chart/Category/FrontpageChartGenerator.php b/app/Support/Chart/Category/FrontpageChartGenerator.php index ad397bff9c..ab1a9985f9 100644 --- a/app/Support/Chart/Category/FrontpageChartGenerator.php +++ b/app/Support/Chart/Category/FrontpageChartGenerator.php @@ -52,8 +52,8 @@ class FrontpageChartGenerator /** * FrontpageChartGenerator constructor. * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end */ public function __construct(Carbon $start, Carbon $end) { @@ -64,7 +64,6 @@ class FrontpageChartGenerator $this->accountRepos = app(AccountRepositoryInterface::class); $this->opsRepos = app(OperationsRepositoryInterface::class); $this->noCatRepos = app(NoCategoryRepositoryInterface::class); - } /** @@ -100,8 +99,8 @@ class FrontpageChartGenerator } /** - * @param Category $category - * @param Collection $accounts + * @param Category $category + * @param Collection $accounts * * @return array */ @@ -114,8 +113,8 @@ class FrontpageChartGenerator $tempData[] = [ 'name' => $category->name, 'sum' => $currency['sum'], - 'sum_float' => round((float) $currency['sum'], $currency['currency_decimal_places']), - 'currency_id' => (int) $currency['currency_id'], + 'sum_float' => round((float)$currency['sum'], $currency['currency_decimal_places']), + 'currency_id' => (int)$currency['currency_id'], ]; } @@ -123,23 +122,23 @@ class FrontpageChartGenerator } /** - * @param array $currency + * @param array $currency */ private function addCurrency(array $currency): void { - $currencyId = (int) $currency['currency_id']; + $currencyId = (int)$currency['currency_id']; $this->currencies[$currencyId] = $this->currencies[$currencyId] ?? [ - 'currency_id' => $currencyId, - 'currency_name' => $currency['currency_name'], - 'currency_symbol' => $currency['currency_symbol'], - 'currency_code' => $currency['currency_code'], - 'currency_decimal_places' => $currency['currency_decimal_places'], - ]; + 'currency_id' => $currencyId, + 'currency_name' => $currency['currency_name'], + 'currency_symbol' => $currency['currency_symbol'], + 'currency_code' => $currency['currency_code'], + 'currency_decimal_places' => $currency['currency_decimal_places'], + ]; } /** - * @param Collection $accounts + * @param Collection $accounts * * @return array */ @@ -152,8 +151,8 @@ class FrontpageChartGenerator $tempData[] = [ 'name' => trans('firefly.no_category'), 'sum' => $currency['sum'], - 'sum_float' => round((float) $currency['sum'], $currency['currency_decimal_places'] ?? 2), // intentional float - 'currency_id' => (int) $currency['currency_id'], + 'sum_float' => round((float)$currency['sum'], $currency['currency_decimal_places'] ?? 2), // intentional float + 'currency_id' => (int)$currency['currency_id'], ]; } @@ -161,7 +160,7 @@ class FrontpageChartGenerator } /** - * @param array $data + * @param array $data * * @return array */ @@ -175,7 +174,7 @@ class FrontpageChartGenerator foreach ($this->currencies as $currencyId => $currency) { $key = sprintf('spent-%d', $currencyId); $return[$key] = [ - 'label' => sprintf('%s (%s)', (string) trans('firefly.spent'), $currency['currency_name']), + 'label' => sprintf('%s (%s)', (string)trans('firefly.spent'), $currency['currency_name']), 'type' => 'bar', 'currency_symbol' => $currency['currency_symbol'], 'entries' => $names, @@ -186,8 +185,8 @@ class FrontpageChartGenerator } /** - * @param array $currencyData - * @param array $monetaryData + * @param array $currencyData + * @param array $monetaryData * * @return array */ @@ -200,10 +199,8 @@ class FrontpageChartGenerator $category = $array['name']; $amount = $array['sum_float'] < 0 ? $array['sum_float'] * -1 : $array['sum_float']; $currencyData[$key]['entries'][$category] = $amount; - } return $currencyData; } - } diff --git a/app/Support/Chart/Category/WholePeriodChartGenerator.php b/app/Support/Chart/Category/WholePeriodChartGenerator.php index ebd0974f55..4b4e500b52 100644 --- a/app/Support/Chart/Category/WholePeriodChartGenerator.php +++ b/app/Support/Chart/Category/WholePeriodChartGenerator.php @@ -36,9 +36,9 @@ use Illuminate\Support\Collection; class WholePeriodChartGenerator { /** - * @param Category $category - * @param Carbon $start - * @param Carbon $end + * @param Category $category + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -77,14 +77,14 @@ class WholePeriodChartGenerator $code = $currency['currency_code']; $name = $currency['currency_name']; $chartData[sprintf('spent-in-%s', $code)] = [ - 'label' => (string) trans('firefly.box_spent_in_currency', ['currency' => $name]), + 'label' => (string)trans('firefly.box_spent_in_currency', ['currency' => $name]), 'entries' => [], 'type' => 'bar', 'backgroundColor' => 'rgba(219, 68, 55, 0.5)', // red ]; $chartData[sprintf('earned-in-%s', $code)] = [ - 'label' => (string) trans('firefly.box_earned_in_currency', ['currency' => $name]), + 'label' => (string)trans('firefly.box_earned_in_currency', ['currency' => $name]), 'entries' => [], 'type' => 'bar', 'backgroundColor' => 'rgba(0, 141, 76, 0.5)', // green @@ -115,16 +115,15 @@ class WholePeriodChartGenerator } /** - * See reference nr. 32 + * TODO this method is duplicated * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return string */ protected function calculateStep(Carbon $start, Carbon $end): string { - $step = '1D'; $months = $start->diffInMonths($end); if ($months > 3) { @@ -144,7 +143,7 @@ class WholePeriodChartGenerator * Loop array of spent/earned info, and extract which currencies are present. * Key is the currency ID. * - * @param array $array + * @param array $array * * @return array */ @@ -154,16 +153,15 @@ class WholePeriodChartGenerator foreach ($array as $block) { foreach ($block as $currencyId => $currencyRow) { $return[$currencyId] = $return[$currencyId] ?? [ - 'currency_id' => $currencyId, - 'currency_name' => $currencyRow['currency_name'], - 'currency_symbol' => $currencyRow['currency_symbol'], - 'currency_code' => $currencyRow['currency_code'], - 'currency_decimal_places' => $currencyRow['currency_decimal_places'], - ]; + 'currency_id' => $currencyId, + 'currency_name' => $currencyRow['currency_name'], + 'currency_symbol' => $currencyRow['currency_symbol'], + 'currency_code' => $currencyRow['currency_code'], + 'currency_decimal_places' => $currencyRow['currency_decimal_places'], + ]; } } return $return; } - } diff --git a/app/Support/ChartColour.php b/app/Support/ChartColour.php index 2969a496d3..82dbb2d238 100644 --- a/app/Support/ChartColour.php +++ b/app/Support/ChartColour.php @@ -1,4 +1,5 @@ force = $force; } - } diff --git a/app/Support/Cronjobs/AutoBudgetCronjob.php b/app/Support/Cronjobs/AutoBudgetCronjob.php index 615d5b5789..bff4d6d96e 100644 --- a/app/Support/Cronjobs/AutoBudgetCronjob.php +++ b/app/Support/Cronjobs/AutoBudgetCronjob.php @@ -34,7 +34,6 @@ use Log; */ class AutoBudgetCronjob extends AbstractCronjob { - /** * @inheritDoc */ @@ -42,7 +41,7 @@ class AutoBudgetCronjob extends AbstractCronjob { /** @var Configuration $config */ $config = app('fireflyconfig')->get('last_ab_job', 0); - $lastTime = (int) $config->data; + $lastTime = (int)$config->data; $diff = time() - $lastTime; $diffForHumans = Carbon::now()->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true); if (0 === $lastTime) { @@ -89,7 +88,7 @@ class AutoBudgetCronjob extends AbstractCronjob $this->jobSucceeded = true; $this->message = 'Auto-budget cron job fired successfully.'; - app('fireflyconfig')->set('last_ab_job', (int) $this->date->format('U')); + app('fireflyconfig')->set('last_ab_job', (int)$this->date->format('U')); Log::info('Done with auto budget cron job task.'); } } diff --git a/app/Support/Cronjobs/BillWarningCronjob.php b/app/Support/Cronjobs/BillWarningCronjob.php index 79ce30f5af..70c84c0bcf 100644 --- a/app/Support/Cronjobs/BillWarningCronjob.php +++ b/app/Support/Cronjobs/BillWarningCronjob.php @@ -28,6 +28,8 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Jobs\WarnAboutBills; use FireflyIII\Models\Configuration; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class BillWarningCronjob @@ -36,15 +38,15 @@ class BillWarningCronjob extends AbstractCronjob { /** * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function fire(): void { Log::debug(sprintf('Now in %s', __METHOD__)); /** @var Configuration $config */ $config = app('fireflyconfig')->get('last_bw_job', 0); - $lastTime = (int) $config->data; + $lastTime = (int)$config->data; $diff = time() - $lastTime; $diffForHumans = Carbon::now()->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true); @@ -97,8 +99,8 @@ class BillWarningCronjob extends AbstractCronjob $this->jobSucceeded = true; $this->message = 'Bill warning cron job fired successfully.'; - app('fireflyconfig')->set('last_bw_job', (int) $this->date->format('U')); - Log::info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int) $this->date->format('U'))); + app('fireflyconfig')->set('last_bw_job', (int)$this->date->format('U')); + Log::info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int)$this->date->format('U'))); Log::info('Done with bill warning cron job task.'); } } diff --git a/app/Support/Cronjobs/ExchangeRatesCronjob.php b/app/Support/Cronjobs/ExchangeRatesCronjob.php new file mode 100644 index 0000000000..91a946b806 --- /dev/null +++ b/app/Support/Cronjobs/ExchangeRatesCronjob.php @@ -0,0 +1,94 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Support\Cronjobs; + +use Carbon\Carbon; +use FireflyIII\Jobs\DownloadExchangeRates; +use FireflyIII\Models\Configuration; +use Log; + +/** + * Class ExchangeRatesCronjob + */ +class ExchangeRatesCronjob extends AbstractCronjob +{ + /** + * @inheritDoc + */ + public function fire(): void + { + /** @var Configuration $config */ + $config = app('fireflyconfig')->get('last_cer_job', 0); + $lastTime = (int)$config->data; + $diff = time() - $lastTime; + $diffForHumans = Carbon::now()->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true); + if (0 === $lastTime) { + Log::info('Exchange rates cron-job has never fired before.'); + } + // less than half a day ago: + if ($lastTime > 0 && $diff <= 43200) { + Log::info(sprintf('It has been %s since the exchange rates cron-job has fired.', $diffForHumans)); + if (false === $this->force) { + Log::info('The exchange rates cron-job will not fire now.'); + $this->message = sprintf('It has been %s since the exchange rates cron-job has fired. It will not fire now.', $diffForHumans); + + return; + } + + // fire job regardless. + if (true === $this->force) { + Log::info('Execution of the exchange rates cron-job has been FORCED.'); + } + } + + if ($lastTime > 0 && $diff > 43200) { + Log::info(sprintf('It has been %s since the exchange rates cron-job has fired. It will fire now!', $diffForHumans)); + } + + $this->fireExchangeRateJob(); + app('preferences')->mark(); + } + + /** + * + */ + private function fireExchangeRateJob(): void + { + Log::info(sprintf('Will now fire exchange rates cron job task for date "%s".', $this->date->format('Y-m-d'))); + /** @var DownloadExchangeRates $job */ + $job = app(DownloadExchangeRates::class); + $job->setDate($this->date); + $job->handle(); + + // get stuff from job: + $this->jobFired = true; + $this->jobErrored = false; + $this->jobSucceeded = true; + $this->message = 'Exchange rates cron job fired successfully.'; + + app('fireflyconfig')->set('last_cer_job', (int)$this->date->format('U')); + Log::info('Done with exchange rates job task.'); + } +} diff --git a/app/Support/Cronjobs/RecurringCronjob.php b/app/Support/Cronjobs/RecurringCronjob.php index b71bdf4f3d..cba3e594cb 100644 --- a/app/Support/Cronjobs/RecurringCronjob.php +++ b/app/Support/Cronjobs/RecurringCronjob.php @@ -28,6 +28,8 @@ use FireflyIII\Exceptions\FireflyException; use FireflyIII\Jobs\CreateRecurringTransactions; use FireflyIII\Models\Configuration; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class RecurringCronjob @@ -36,15 +38,15 @@ class RecurringCronjob extends AbstractCronjob { /** * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function fire(): void { Log::debug(sprintf('Now in %s', __METHOD__)); /** @var Configuration $config */ $config = app('fireflyconfig')->get('last_rt_job', 0); - $lastTime = (int) $config->data; + $lastTime = (int)$config->data; $diff = time() - $lastTime; $diffForHumans = Carbon::now()->diffForHumans(Carbon::createFromTimestamp($lastTime), null, true); @@ -97,8 +99,8 @@ class RecurringCronjob extends AbstractCronjob $this->jobSucceeded = true; $this->message = 'Recurring transactions cron job fired successfully.'; - app('fireflyconfig')->set('last_rt_job', (int) $this->date->format('U')); - Log::info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int) $this->date->format('U'))); + app('fireflyconfig')->set('last_rt_job', (int)$this->date->format('U')); + Log::info(sprintf('Marked the last time this job has run as "%s" (%d)', $this->date->format('Y-m-d H:i:s'), (int)$this->date->format('U'))); Log::info('Done with recurring cron job task.'); } } diff --git a/app/Support/Domain.php b/app/Support/Domain.php index ced5cd7ae7..6422919533 100644 --- a/app/Support/Domain.php +++ b/app/Support/Domain.php @@ -1,4 +1,5 @@ render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render amountNoCurrency(): %s', $e->getMessage())); $html = 'Could not render amountNoCurrency.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param int|null $value - * @param mixed $checked - * @param array|null $options + * @param string $name + * @param int|null $value + * @param mixed $checked + * @param array|null $options * * @return string */ @@ -98,18 +101,19 @@ class ExpandedForm unset($options['placeholder'], $options['autocomplete'], $options['class']); try { $html = view('form.checkbox', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render checkbox(): %s', $e->getMessage())); $html = 'Could not render checkbox.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -122,17 +126,18 @@ class ExpandedForm unset($options['placeholder']); try { $html = view('form.date', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render date(): %s', $e->getMessage())); $html = 'Could not render date.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param array|null $options + * @param string $name + * @param array|null $options * * @return string */ @@ -144,18 +149,19 @@ class ExpandedForm $classes = $this->getHolderClasses($name); try { $html = view('form.file', compact('classes', 'name', 'label', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render file(): %s', $e->getMessage())); $html = 'Could not render file.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -169,18 +175,19 @@ class ExpandedForm $options['step'] = '1'; try { $html = view('form.integer', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render integer(): %s', $e->getMessage())); $html = 'Could not render integer.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -193,16 +200,17 @@ class ExpandedForm $value = $this->fillFieldValue($name, $value); try { $html = view('form.location', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render location(): %s', $e->getMessage())); $html = 'Could not render location.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param Collection $set + * @param Collection $set * * @return array * @@ -214,12 +222,13 @@ class ExpandedForm $fields = ['title', 'name', 'description']; /** @var Eloquent $entry */ foreach ($set as $entry) { - $entryId = (int) $entry->id; // @phpstan-ignore-line + // All Eloquent models have an ID + $entryId = (int)$entry->id; // @phpstan-ignore-line $current = $entry->toArray(); $title = null; foreach ($fields as $field) { if (array_key_exists($field, $current) && null === $title) { - $title = $current[$field]; // @phpstan-ignore-line + $title = $current[$field]; } } $selectList[$entryId] = $title; @@ -229,9 +238,9 @@ class ExpandedForm } /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -251,18 +260,19 @@ class ExpandedForm } try { $html = view('form.non-selectable-amount', compact('selectedCurrency', 'classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render nonSelectableAmount(): %s', $e->getMessage())); $html = 'Could not render nonSelectableAmount.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -276,17 +286,18 @@ class ExpandedForm unset($options['placeholder']); try { $html = view('form.number', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render number(): %s', $e->getMessage())); $html = 'Could not render number.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param null $value - * @param array|null $options + * @param null $value + * @param array|null $options * * @return string */ @@ -305,17 +316,18 @@ class ExpandedForm try { $html = view('form.object_group', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render objectGroup(): %s', $e->getMessage())); $html = 'Could not render objectGroup.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $type - * @param string $name + * @param string $type + * @param string $name * * @return string * @@ -324,31 +336,32 @@ class ExpandedForm { try { $html = view('form.options', compact('type', 'name'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render select(): %s', $e->getMessage())); $html = 'Could not render optionsList.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param array|null $options + * @param string $name + * @param array|null $options * * @return string */ public function password(string $name, array $options = null): string { - $label = $this->label($name, $options); $options = $this->expandOptionArray($name, $label, $options); $classes = $this->getHolderClasses($name); try { $html = view('form.password', compact('classes', 'name', 'label', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render password(): %s', $e->getMessage())); $html = 'Could not render password.'; + throw new FireflyException($html, 0, $e); } return $html; @@ -357,9 +370,9 @@ class ExpandedForm /** * Function to render a percentage. * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -373,18 +386,19 @@ class ExpandedForm unset($options['placeholder']); try { $html = view('form.percentage', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render percentage(): %s', $e->getMessage())); $html = 'Could not render percentage.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -395,18 +409,19 @@ class ExpandedForm $classes = $this->getHolderClasses($name); try { $html = view('form.static', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render staticText(): %s', $e->getMessage())); $html = 'Could not render staticText.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -418,18 +433,19 @@ class ExpandedForm $value = $this->fillFieldValue($name, $value); try { $html = view('form.text', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render text(): %s', $e->getMessage())); $html = 'Could not render text.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -447,9 +463,10 @@ class ExpandedForm try { $html = view('form.textarea', compact('classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render textarea(): %s', $e->getMessage())); $html = 'Could not render textarea.'; + throw new FireflyException($html, 0, $e); } return $html; diff --git a/app/Support/Export/ExportDataGenerator.php b/app/Support/Export/ExportDataGenerator.php index 84ed59c54a..a8b11f1552 100644 --- a/app/Support/Export/ExportDataGenerator.php +++ b/app/Support/Export/ExportDataGenerator.php @@ -53,9 +53,12 @@ use FireflyIII\Repositories\TransactionGroup\TransactionGroupRepositoryInterface use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\User; use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; use League\Csv\CannotInsertRecord; use League\Csv\Exception; use League\Csv\Writer; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Class ExportDataGenerator @@ -82,7 +85,7 @@ class ExportDataGenerator public function __construct() { - $this->accounts = new Collection; + $this->accounts = new Collection(); $this->start = today(config('app.timezone')); $this->start->subYear(); $this->end = today(config('app.timezone')); @@ -141,8 +144,25 @@ class ExportDataGenerator */ private function exportAccounts(): string { - $header = ['user_id', 'account_id', 'created_at', 'updated_at', 'type', 'name', 'virtual_balance', 'iban', 'number', 'active', 'currency_code', 'role', - 'cc_type', 'cc_payment_date', 'in_net_worth', 'interest', 'interest_period',]; + $header = [ + 'user_id', + 'account_id', + 'created_at', + 'updated_at', + 'type', + 'name', + 'virtual_balance', + 'iban', + 'number', + 'active', + 'currency_code', + 'role', + 'cc_type', + 'cc_payment_date', + 'in_net_worth', + 'interest', + 'interest_period', + ]; /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $repository->setUser($this->user); @@ -187,13 +207,22 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } return $string; } + /** + * @param User $user + */ + public function setUser(User $user): void + { + $this->user = $user; + } + /** * @return string * @throws FireflyException @@ -204,8 +233,20 @@ class ExportDataGenerator $repository = app(BillRepositoryInterface::class); $repository->setUser($this->user); $bills = $repository->getBills(); - $header = ['user_id', 'bill_id', 'created_at', 'updated_at', 'currency_code', 'name', 'amount_min', 'amount_max', 'date', 'repeat_freq', 'skip', - 'active',]; + $header = [ + 'user_id', + 'bill_id', + 'created_at', + 'updated_at', + 'currency_code', + 'name', + 'amount_min', + 'amount_max', + 'date', + 'repeat_freq', + 'skip', + 'active', + ]; $records = []; /** @var Bill $bill */ @@ -241,7 +282,8 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } @@ -305,12 +347,12 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } return $string; - } /** @@ -354,7 +396,8 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } @@ -375,9 +418,22 @@ class ExportDataGenerator $accountRepos = app(AccountRepositoryInterface::class); $accountRepos->setUser($this->user); - $header = ['user_id', 'piggy_bank_id', 'created_at', 'updated_at', 'account_name', 'account_type', 'name', - 'currency_code', 'target_amount', 'current_amount', 'start_date', 'target_date', 'order', - 'active']; + $header = [ + 'user_id', + 'piggy_bank_id', + 'created_at', + 'updated_at', + 'account_name', + 'account_type', + 'name', + 'currency_code', + 'target_amount', + 'current_amount', + 'start_date', + 'target_date', + 'order', + 'active', + ]; $records = []; $piggies = $piggyRepos->getPiggyBanks(); @@ -418,7 +474,8 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } @@ -436,14 +493,39 @@ class ExportDataGenerator $recurringRepos->setUser($this->user); $header = [ // recurrence: - 'user_id', 'recurrence_id', 'row_contains', 'created_at', 'updated_at', 'type', 'title', 'description', 'first_date', 'repeat_until', - 'latest_date', 'repetitions', 'apply_rules', 'active', + 'user_id', + 'recurrence_id', + 'row_contains', + 'created_at', + 'updated_at', + 'type', + 'title', + 'description', + 'first_date', + 'repeat_until', + 'latest_date', + 'repetitions', + 'apply_rules', + 'active', // repetition info: - 'type', 'moment', 'skip', 'weekend', + 'type', + 'moment', + 'skip', + 'weekend', // transactions + meta: - 'currency_code', 'foreign_currency_code', 'source_name', 'source_type', 'destination_name', 'destination_type', 'amount', 'foreign_amount', - 'category', 'budget', 'piggy_bank', 'tags', + 'currency_code', + 'foreign_currency_code', + 'source_name', + 'source_type', + 'destination_name', + 'destination_type', + 'amount', + 'foreign_amount', + 'category', + 'budget', + 'piggy_bank', + 'tags', ]; $records = []; $recurrences = $recurringRepos->getAll(); @@ -472,15 +554,30 @@ class ExportDataGenerator $records[] = [ // recurrence $this->user->id, - $recurrence->id, 'repetition', null, null, null, null, null, null, null, null, null, null, null, + $recurrence->id, + 'repetition', + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, // repetition: - $repetition->repetition_type, $repetition->repetition_moment, $repetition->repetition_skip, $repetition->weekend, + $repetition->repetition_type, + $repetition->repetition_moment, + $repetition->repetition_skip, + $repetition->weekend, ]; } /** @var RecurrenceTransaction $transaction */ foreach ($recurrence->recurrenceTransactions as $transaction) { - $categoryName = $recurringRepos->getCategory($transaction); + $categoryName = $recurringRepos->getCategoryName($transaction); $budgetId = $recurringRepos->getBudget($transaction); $piggyBankId = $recurringRepos->getPiggyBank($transaction); $tags = $recurringRepos->getTags($transaction); @@ -488,16 +585,39 @@ class ExportDataGenerator $records[] = [ // recurrence $this->user->id, - $recurrence->id, 'transaction', null, null, null, null, null, null, null, null, null, null, null, + $recurrence->id, + 'transaction', + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, // repetition: - null, null, null, null, + null, + null, + null, + null, // transaction: - $transaction->transactionCurrency->code, $transaction->foreignCurrency?->code, - $transaction->sourceAccount->name, $transaction->sourceAccount->accountType->type, $transaction->destinationAccount->name, - $transaction->destinationAccount->accountType->type, $transaction->amount, $transaction->foreign_amount, - $categoryName, $budgetId, $piggyBankId, implode(',', $tags), + $transaction->transactionCurrency->code, + $transaction->foreignCurrency?->code, + $transaction->sourceAccount->name, + $transaction->sourceAccount->accountType->type, + $transaction->destinationAccount->name, + $transaction->destinationAccount->accountType->type, + $transaction->amount, + $transaction->foreign_amount, + $categoryName, + $budgetId, + $piggyBankId, + implode(',', $tags), ]; } } @@ -516,7 +636,8 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } @@ -529,9 +650,31 @@ class ExportDataGenerator */ private function exportRules(): string { - $header = ['user_id', 'rule_id', 'row_contains', 'created_at', 'updated_at', 'group_id', 'group_name', 'title', 'description', 'order', 'active', - 'stop_processing', 'strict', 'trigger_type', 'trigger_value', 'trigger_order', 'trigger_active', 'trigger_stop_processing', 'action_type', - 'action_value', 'action_order', 'action_active', 'action_stop_processing',]; + $header = [ + 'user_id', + 'rule_id', + 'row_contains', + 'created_at', + 'updated_at', + 'group_id', + 'group_name', + 'title', + 'description', + 'order', + 'active', + 'stop_processing', + 'strict', + 'trigger_type', + 'trigger_value', + 'trigger_order', + 'trigger_active', + 'trigger_stop_processing', + 'action_type', + 'action_value', + 'action_order', + 'action_active', + 'action_stop_processing', + ]; $ruleRepos = app(RuleRepositoryInterface::class); $ruleRepos->setUser($this->user); $rules = $ruleRepos->getAll(); @@ -539,31 +682,70 @@ class ExportDataGenerator /** @var Rule $rule */ foreach ($rules as $rule) { $records[] = [ - $this->user->id, $rule->id, 'rule', - $rule->created_at->toAtomString(), $rule->updated_at->toAtomString(), - $rule->ruleGroup->id, $rule->ruleGroup->title, - $rule->title, $rule->description, $rule->order, $rule->active, $rule->stop_processing, $rule->strict, + $this->user->id, + $rule->id, + 'rule', + $rule->created_at->toAtomString(), + $rule->updated_at->toAtomString(), + $rule->ruleGroup->id, + $rule->ruleGroup->title, + $rule->title, + $rule->description, + $rule->order, + $rule->active, + $rule->stop_processing, + $rule->strict, ]; /** @var RuleTrigger $trigger */ foreach ($rule->ruleTriggers as $trigger) { $records[] = [ - $this->user->id, $rule->id, 'trigger', - null, null, - null, null, - null, null, null, null, null, null, - $trigger->trigger_type, $trigger->trigger_value, $trigger->order, $trigger->active, $trigger->stop_processing, + $this->user->id, + $rule->id, + 'trigger', + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + $trigger->trigger_type, + $trigger->trigger_value, + $trigger->order, + $trigger->active, + $trigger->stop_processing, ]; } /** @var RuleAction $action */ foreach ($rule->ruleActions as $action) { $records[] = [ - $this->user->id, $rule->id, 'action', - null, null, - null, null, - null, null, null, null, null, null, - null, null, null, null, null, - $action->action_type, $action->action_value, $action->order, $action->active, $action->stop_processing, + $this->user->id, + $rule->id, + 'action', + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + $action->action_type, + $action->action_value, + $action->order, + $action->active, + $action->stop_processing, ]; } } @@ -583,7 +765,8 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } @@ -593,8 +776,8 @@ class ExportDataGenerator /** * @return string * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ private function exportTags(): string { @@ -635,7 +818,8 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } @@ -648,11 +832,34 @@ class ExportDataGenerator */ private function exportTransactions(): string { - // See reference nr. 41 - $header = ['user_id', 'group_id', 'journal_id', 'created_at', 'updated_at', 'group_title', 'type', 'amount', 'foreign_amount', 'currency_code', - 'foreign_currency_code', 'description', 'date', 'source_name', 'source_iban', 'source_type', 'destination_name', 'destination_iban', - 'destination_type', 'reconciled', 'category', 'budget', 'bill', 'tags', 'notes', - // all optional meta fields: + // TODO better place for keys? + $header = [ + 'user_id', + 'group_id', + 'journal_id', + 'created_at', + 'updated_at', + 'group_title', + 'type', + 'amount', + 'foreign_amount', + 'currency_code', + 'foreign_currency_code', + 'description', + 'date', + 'source_name', + 'source_iban', + 'source_type', + 'destination_name', + 'destination_iban', + 'destination_type', + 'reconciled', + 'category', + 'budget', + 'bill', + 'tags', + 'notes', + // all optional meta fields: ]; $metaFields = config('firefly.journal_meta_fields'); @@ -737,7 +944,6 @@ class ExportDataGenerator $metaData['recurrence_total'], $metaData['recurrence_count'], ]; - } //load the CSV document from a string @@ -755,7 +961,8 @@ class ExportDataGenerator try { $string = $csv->toString(); - } catch (Exception $e) { + } catch (Exception $e) { // intentional generic exception + Log::error($e->getMessage()); throw new FireflyException(sprintf(self::EXPORT_ERR, $e->getMessage()), 0, $e); } @@ -763,13 +970,21 @@ class ExportDataGenerator } /** - * @param array $tags + * @param Collection $accounts + */ + public function setAccounts(Collection $accounts): void + { + $this->accounts = $accounts; + } + + /** + * @param array $tags * * @return string */ private function mergeTags(array $tags): string { - if (empty($tags)) { + if (0 === count($tags)) { return ''; } $smol = []; @@ -781,15 +996,7 @@ class ExportDataGenerator } /** - * @param Collection $accounts - */ - public function setAccounts(Collection $accounts): void - { - $this->accounts = $accounts; - } - - /** - * @param Carbon $end + * @param Carbon $end */ public function setEnd(Carbon $end): void { @@ -797,7 +1004,7 @@ class ExportDataGenerator } /** - * @param bool $exportAccounts + * @param bool $exportAccounts */ public function setExportAccounts(bool $exportAccounts): void { @@ -805,7 +1012,7 @@ class ExportDataGenerator } /** - * @param bool $exportBills + * @param bool $exportBills */ public function setExportBills(bool $exportBills): void { @@ -813,7 +1020,7 @@ class ExportDataGenerator } /** - * @param bool $exportBudgets + * @param bool $exportBudgets */ public function setExportBudgets(bool $exportBudgets): void { @@ -821,7 +1028,7 @@ class ExportDataGenerator } /** - * @param bool $exportCategories + * @param bool $exportCategories */ public function setExportCategories(bool $exportCategories): void { @@ -829,7 +1036,7 @@ class ExportDataGenerator } /** - * @param bool $exportPiggies + * @param bool $exportPiggies */ public function setExportPiggies(bool $exportPiggies): void { @@ -837,7 +1044,7 @@ class ExportDataGenerator } /** - * @param bool $exportRecurring + * @param bool $exportRecurring */ public function setExportRecurring(bool $exportRecurring): void { @@ -845,7 +1052,7 @@ class ExportDataGenerator } /** - * @param bool $exportRules + * @param bool $exportRules */ public function setExportRules(bool $exportRules): void { @@ -853,7 +1060,7 @@ class ExportDataGenerator } /** - * @param bool $exportTags + * @param bool $exportTags */ public function setExportTags(bool $exportTags): void { @@ -861,7 +1068,7 @@ class ExportDataGenerator } /** - * @param bool $exportTransactions + * @param bool $exportTransactions */ public function setExportTransactions(bool $exportTransactions): void { @@ -869,7 +1076,7 @@ class ExportDataGenerator } /** - * @param Carbon $start + * @param Carbon $start */ public function setStart(Carbon $start): void { @@ -877,11 +1084,18 @@ class ExportDataGenerator } /** - * @param User $user + * @inheritDoc */ - public function setUser(User $user): void + public function get(string $key, mixed $default = null): mixed { - $this->user = $user; + return null; } + /** + * @inheritDoc + */ + public function has(mixed $key): mixed + { + return null; + } } diff --git a/app/Support/Facades/AccountForm.php b/app/Support/Facades/AccountForm.php index 06d4f2da11..86c7046c07 100644 --- a/app/Support/Facades/AccountForm.php +++ b/app/Support/Facades/AccountForm.php @@ -1,4 +1,5 @@ warning('Hi there'); } /** diff --git a/app/Support/Facades/RuleForm.php b/app/Support/Facades/RuleForm.php index 9a9caaf29a..fe103723ed 100644 --- a/app/Support/Facades/RuleForm.php +++ b/app/Support/Facades/RuleForm.php @@ -1,4 +1,5 @@ forceDelete(); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException - } + Configuration::where('name', $name)->forceDelete(); } /** - * @param string $name - * @param bool|string|int|null $default + * @param string $name + * + * @return bool + */ + public function has(string $name): bool + { + return Configuration::where('name', $name)->count() === 1; + } + + /** + * @param string $name + * @param bool|string|int|null $default * * @return Configuration|null * @throws FireflyException */ public function get(string $name, $default = null): ?Configuration { - $fullName = 'ff-config-' . $name; + $fullName = 'ff-config-'.$name; if (Cache::has($fullName)) { return Cache::get($fullName); } @@ -69,8 +76,8 @@ class FireflyConfig try { /** @var Configuration|null $config */ $config = Configuration::where('name', $name)->first(['id', 'name', 'data']); - } catch (QueryException|Exception $e) { // @phpstan-ignore-line - throw new FireflyException(sprintf('Could not poll the database: %s', $e->getMessage())); + } catch (QueryException|Exception $e) { + throw new FireflyException(sprintf('Could not poll the database: %s', $e->getMessage()), 0, $e); } if (null !== $config) { @@ -87,8 +94,8 @@ class FireflyConfig } /** - * @param string $name - * @param mixed $value + * @param string $name + * @param mixed $value * * @return Configuration */ @@ -96,8 +103,9 @@ class FireflyConfig { try { $config = Configuration::whereName($name)->whereNull('deleted_at')->first(); - } catch (QueryException|Exception $e) { // @phpstan-ignore-line - $item = new Configuration; + } catch (QueryException $e) { + Log::error($e->getMessage()); + $item = new Configuration(); $item->name = $name; $item->data = $value; @@ -105,33 +113,31 @@ class FireflyConfig } if (null === $config) { - $item = new Configuration; + $item = new Configuration(); $item->name = $name; $item->data = $value; $item->save(); - Cache::forget('ff-config-' . $name); + Cache::forget('ff-config-'.$name); return $item; } $config->data = $value; $config->save(); - Cache::forget('ff-config-' . $name); + Cache::forget('ff-config-'.$name); return $config; } /** - * @param string $name - * @param mixed $default + * @param string $name + * @param mixed $default * * @return Configuration|null */ public function getFresh(string $name, $default = null): ?Configuration { - $config = Configuration::where('name', $name)->first(['id', 'name', 'data']); if ($config) { - return $config; } // no preference found and default is null: @@ -143,18 +149,8 @@ class FireflyConfig } /** - * @param string $name - * - * @return bool - */ - public function has(string $name): bool - { - return Configuration::where('name', $name)->count() === 1; - } - - /** - * @param string $name - * @param mixed $value + * @param string $name + * @param mixed $value * * @return Configuration */ diff --git a/app/Support/Form/AccountForm.php b/app/Support/Form/AccountForm.php index 740a2c6896..31b02dcb93 100644 --- a/app/Support/Form/AccountForm.php +++ b/app/Support/Form/AccountForm.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Form; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; @@ -34,8 +35,8 @@ use Throwable; * * All form methods that are account related. * - * See reference nr. 29 - * See reference nr. 30 + * TODO describe all methods + * TODO optimize repositories and methods. */ class AccountForm { @@ -44,9 +45,9 @@ class AccountForm /** * Grouped dropdown list of all accounts that are valid as the destination of a withdrawal. * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -56,8 +57,8 @@ class AccountForm $repository = $this->getAccountRepository(); $grouped = $this->getAccountsGrouped($types, $repository); $cash = $repository->getCashAccount(); - $key = (string) trans('firefly.cash_account_type'); - $grouped[$key][$cash->id] = sprintf('(%s)', (string) trans('firefly.cash')); + $key = (string)trans('firefly.cash_account_type'); + $grouped[$key][$cash->id] = sprintf('(%s)', (string)trans('firefly.cash')); return $this->select($name, $grouped, $value, $options); } @@ -73,7 +74,7 @@ class AccountForm /** @var Account $account */ foreach ($accountList as $account) { - $role = (string) $repository->getMetaValue($account, 'account_role'); + $role = (string)$repository->getMetaValue($account, 'account_role'); if (in_array($account->accountType->type, $liabilityTypes, true)) { $role = sprintf('l_%s', $account->accountType->type); } elseif ('' === $role) { @@ -85,7 +86,7 @@ class AccountForm $role = 'no_account_type'; } } - $key = (string) trans(sprintf('firefly.opt_group_%s', $role)); + $key = (string)trans(sprintf('firefly.opt_group_%s', $role)); $grouped[$key][$account->id] = $account->name; } @@ -95,9 +96,9 @@ class AccountForm /** * Grouped dropdown list of all accounts that are valid as the destination of a withdrawal. * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -108,8 +109,8 @@ class AccountForm $grouped = $this->getAccountsGrouped($types, $repository); $cash = $repository->getCashAccount(); - $key = (string) trans('firefly.cash_account_type'); - $grouped[$key][$cash->id] = sprintf('(%s)', (string) trans('firefly.cash')); + $key = (string)trans('firefly.cash_account_type'); + $grouped[$key][$cash->id] = sprintf('(%s)', (string)trans('firefly.cash')); return $this->select($name, $grouped, $value, $options); } @@ -117,8 +118,8 @@ class AccountForm /** * Check list of asset accounts. * - * @param string $name - * @param array|null $options + * @param string $name + * @param array|null $options * * @return string */ @@ -137,9 +138,10 @@ class AccountForm unset($options['class']); try { $html = view('form.assetAccountCheckList', compact('classes', 'selected', 'name', 'label', 'options', 'grouped'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render assetAccountCheckList(): %s', $e->getMessage())); $html = 'Could not render assetAccountCheckList.'; + throw new FireflyException($html, 0, $e); } return $html; @@ -148,9 +150,9 @@ class AccountForm /** * Basic list of asset accounts. * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -165,9 +167,9 @@ class AccountForm /** * Same list but all liabilities as well. * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ diff --git a/app/Support/Form/CurrencyForm.php b/app/Support/Form/CurrencyForm.php index 04c96adafd..6f07c77fd5 100644 --- a/app/Support/Form/CurrencyForm.php +++ b/app/Support/Form/CurrencyForm.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Form; use Amount as Amt; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use Illuminate\Support\Collection; @@ -40,9 +41,9 @@ class CurrencyForm use FormSupport; /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -52,10 +53,10 @@ class CurrencyForm } /** - * @param string $name - * @param string $view - * @param mixed $value - * @param array|null $options + * @param string $name + * @param string $view + * @param mixed $value + * @param array|null $options * * @return string */ @@ -76,8 +77,8 @@ class CurrencyForm if (!is_array($preFilled)) { $preFilled = []; } - $key = 'amount_currency_id_' . $name; - $sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id; + $key = 'amount_currency_id_'.$name; + $sentCurrencyId = array_key_exists($key, $preFilled) ? (int)$preFilled[$key] : $defaultCurrency->id; Log::debug(sprintf('Sent currency ID is %d', $sentCurrencyId)); @@ -95,21 +96,22 @@ class CurrencyForm $value = app('steam')->bcround($value, $defaultCurrency->decimal_places); } try { - $html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + $html = view('form.'.$view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render(); + } catch (Throwable $e) { Log::debug(sprintf('Could not render currencyField(): %s', $e->getMessage())); $html = 'Could not render currencyField.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * See reference nr. 23 + * TODO describe and cleanup. * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -119,12 +121,12 @@ class CurrencyForm } /** - * See reference nr. 24 + * TODO describe and cleanup * - * @param string $name - * @param string $view - * @param mixed $value - * @param array|null $options + * @param string $name + * @param string $view + * @param mixed $value + * @param array|null $options * * @return string */ @@ -145,8 +147,8 @@ class CurrencyForm if (!is_array($preFilled)) { $preFilled = []; } - $key = 'amount_currency_id_' . $name; - $sentCurrencyId = array_key_exists($key, $preFilled) ? (int) $preFilled[$key] : $defaultCurrency->id; + $key = 'amount_currency_id_'.$name; + $sentCurrencyId = array_key_exists($key, $preFilled) ? (int)$preFilled[$key] : $defaultCurrency->id; Log::debug(sprintf('Sent currency ID is %d', $sentCurrencyId)); @@ -164,21 +166,22 @@ class CurrencyForm $value = app('steam')->bcround($value, $defaultCurrency->decimal_places); } try { - $html = view('form.' . $view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + $html = view('form.'.$view, compact('defaultCurrency', 'currencies', 'classes', 'name', 'label', 'value', 'options'))->render(); + } catch (Throwable $e) { Log::debug(sprintf('Could not render currencyField(): %s', $e->getMessage())); $html = 'Could not render currencyField.'; + throw new FireflyException($html, 0, $e); } return $html; } /** - * See reference nr. 25 + * TODO cleanup and describe * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -192,18 +195,18 @@ class CurrencyForm $array = []; /** @var TransactionCurrency $currency */ foreach ($list as $currency) { - $array[$currency->id] = $currency->name . ' (' . $currency->symbol . ')'; + $array[$currency->id] = $currency->name.' ('.$currency->symbol.')'; } return $this->select($name, $array, $value, $options); } /** - * See reference nr. 26 + * TODO cleanup and describe * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -215,14 +218,13 @@ class CurrencyForm // get all currencies: $list = $currencyRepos->get(); $array = [ - 0 => (string) trans('firefly.no_currency'), + 0 => (string)trans('firefly.no_currency'), ]; /** @var TransactionCurrency $currency */ foreach ($list as $currency) { - $array[$currency->id] = $currency->name . ' (' . $currency->symbol . ')'; + $array[$currency->id] = $currency->name.' ('.$currency->symbol.')'; } return $this->select($name, $array, $value, $options); } - } diff --git a/app/Support/Form/FormSupport.php b/app/Support/Form/FormSupport.php index 0abf922be0..cfcb34f661 100644 --- a/app/Support/Form/FormSupport.php +++ b/app/Support/Form/FormSupport.php @@ -24,11 +24,10 @@ declare(strict_types=1); namespace FireflyIII\Support\Form; use Carbon\Carbon; -use Exception; +use Carbon\Exceptions\InvalidDateException; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use Illuminate\Support\MessageBag; use Log; -use RuntimeException; use Throwable; /** @@ -37,10 +36,10 @@ use Throwable; trait FormSupport { /** - * @param string $name - * @param array|null $list - * @param mixed $selected - * @param array|null $options + * @param string $name + * @param array|null $list + * @param mixed $selected + * @param array|null $options * * @return string */ @@ -54,7 +53,7 @@ trait FormSupport unset($options['autocomplete'], $options['placeholder']); try { $html = view('form.select', compact('classes', 'name', 'label', 'selected', 'options', 'list'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Could not render select(): %s', $e->getMessage())); $html = 'Could not render select.'; } @@ -63,8 +62,8 @@ trait FormSupport } /** - * @param string $name - * @param array|null $options + * @param string $name + * @param array|null $options * * @return string */ @@ -76,13 +75,13 @@ trait FormSupport } $name = str_replace('[]', '', $name); - return (string) trans('form.' . $name); + return (string)trans('form.'.$name); } /** - * @param string $name - * @param mixed $label - * @param array|null $options + * @param string $name + * @param mixed $label + * @param array|null $options * * @return array */ @@ -91,7 +90,7 @@ trait FormSupport $options = $options ?? []; $name = str_replace('[]', '', $name); $options['class'] = 'form-control'; - $options['id'] = 'ffInput_' . $name; + $options['id'] = 'ffInput_'.$name; $options['autocomplete'] = 'off'; $options['placeholder'] = ucfirst($label); @@ -99,7 +98,7 @@ trait FormSupport } /** - * @param string $name + * @param string $name * * @return string */ @@ -118,8 +117,8 @@ trait FormSupport } /** - * @param string $name - * @param mixed|null $value + * @param string $name + * @param mixed|null $value * * @return mixed */ @@ -130,13 +129,8 @@ trait FormSupport $value = array_key_exists($name, $preFilled) && null === $value ? $preFilled[$name] : $value; } - try { - if (null !== request()->old($name)) { - $value = request()->old($name); - } - } catch (RuntimeException $e) { // @phpstan-ignore-line - // don't care about session errors. - Log::debug(sprintf('Run time: %s', $e->getMessage())); + if (null !== request()->old($name)) { + $value = request()->old($name); } if ($value instanceof Carbon) { @@ -163,8 +157,8 @@ trait FormSupport $date = null; try { $date = today(config('app.timezone')); - } catch (Exception $e) { // @phpstan-ignore-line - // @ignoreException + } catch (InvalidDateException $e) { + Log::error($e->getMessage()); } return $date; diff --git a/app/Support/Form/PiggyBankForm.php b/app/Support/Form/PiggyBankForm.php index 3d836661be..c9391d375a 100644 --- a/app/Support/Form/PiggyBankForm.php +++ b/app/Support/Form/PiggyBankForm.php @@ -29,18 +29,18 @@ use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; /** * Class PiggyBankForm * - * See reference nr. 27 + * TODO cleanup and describe. */ class PiggyBankForm { use FormSupport; /** - * See reference nr. 28 + * TODO cleanup and describe * - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -50,7 +50,7 @@ class PiggyBankForm /** @var PiggyBankRepositoryInterface $repository */ $repository = app(PiggyBankRepositoryInterface::class); $piggyBanks = $repository->getPiggyBanksWithAmount(); - $title = (string) trans('firefly.default_group_title_name'); + $title = (string)trans('firefly.default_group_title_name'); $array = []; $subList = [ 0 => [ @@ -58,7 +58,7 @@ class PiggyBankForm 'title' => $title, ], 'piggies' => [ - (string) trans('firefly.none_in_select_list'), + (string)trans('firefly.none_in_select_list'), ], ], ]; @@ -72,11 +72,11 @@ class PiggyBankForm $groupOrder = $group->order; } $subList[$groupOrder] = $subList[$groupOrder] ?? [ - 'group' => [ - 'title' => $groupTitle, - ], - 'piggies' => [], - ]; + 'group' => [ + 'title' => $groupTitle, + ], + 'piggies' => [], + ]; $subList[$groupOrder]['piggies'][$piggy->id] = $piggy->name; } ksort($subList); diff --git a/app/Support/Form/RuleForm.php b/app/Support/Form/RuleForm.php index 87f0b29ff9..c20d8e49ce 100644 --- a/app/Support/Form/RuleForm.php +++ b/app/Support/Form/RuleForm.php @@ -30,16 +30,16 @@ use Illuminate\Support\HtmlString; /** * Class RuleForm - * See reference nr. 31 + * TODO cleanup and describe */ class RuleForm { use FormSupport; /** - * @param string $name - * @param mixed $value - * @param array|null $options + * @param string $name + * @param mixed $value + * @param array|null $options * * @return string */ @@ -60,9 +60,9 @@ class RuleForm } /** - * @param string $name - * @param null $value - * @param array|null $options + * @param string $name + * @param null $value + * @param array|null $options * * @return HtmlString */ @@ -76,11 +76,11 @@ class RuleForm // get all currencies: $list = $groupRepos->get(); $array = [ - 0 => (string) trans('firefly.none_in_select_list'), + 0 => (string)trans('firefly.none_in_select_list'), ]; /** @var RuleGroup $group */ foreach ($list as $group) { - if (array_key_exists('hidden', $options) && (int) $options['hidden'] !== $group->id) { + if (array_key_exists('hidden', $options) && (int)$options['hidden'] !== $group->id) { $array[$group->id] = $group->title; } } diff --git a/app/Support/Http/Api/AccountFilter.php b/app/Support/Http/Api/AccountFilter.php index 8624181e5d..1204164501 100644 --- a/app/Support/Http/Api/AccountFilter.php +++ b/app/Support/Http/Api/AccountFilter.php @@ -35,17 +35,27 @@ trait AccountFilter /** * All the available types. * - * @param string $type + * @param string $type * * @return array */ protected function mapAccountTypes(string $type): array { $types = [ - 'all' => [AccountType::DEFAULT, AccountType::CASH, - AccountType::ASSET, AccountType::EXPENSE, AccountType::REVENUE, - AccountType::INITIAL_BALANCE, AccountType::BENEFICIARY, AccountType::IMPORT, AccountType::RECONCILIATION, - AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + 'all' => [ + AccountType::DEFAULT, + AccountType::CASH, + AccountType::ASSET, + AccountType::EXPENSE, + AccountType::REVENUE, + AccountType::INITIAL_BALANCE, + AccountType::BENEFICIARY, + AccountType::IMPORT, + AccountType::RECONCILIATION, + AccountType::LOAN, + AccountType::DEBT, + AccountType::MORTGAGE, + ], 'asset' => [AccountType::DEFAULT, AccountType::ASSET,], 'cash' => [AccountType::CASH,], 'expense' => [AccountType::EXPENSE, AccountType::BENEFICIARY,], diff --git a/app/Support/Http/Api/ApiSupport.php b/app/Support/Http/Api/ApiSupport.php index afe8de3b9e..342c8eb51d 100644 --- a/app/Support/Http/Api/ApiSupport.php +++ b/app/Support/Http/Api/ApiSupport.php @@ -36,7 +36,7 @@ trait ApiSupport /** * Small helper function for the revenue and expense account charts. * - * @param array $names + * @param array $names * * @return array */ @@ -53,7 +53,7 @@ trait ApiSupport /** * Small helper function for the revenue and expense account charts. * - * @param Collection $accounts + * @param Collection $accounts * * @return array */ diff --git a/app/Support/Http/Api/ConvertsExchangeRates.php b/app/Support/Http/Api/ConvertsExchangeRates.php new file mode 100644 index 0000000000..e3e567fcba --- /dev/null +++ b/app/Support/Http/Api/ConvertsExchangeRates.php @@ -0,0 +1,269 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Support\Http\Api; + +use Carbon\Carbon; +use DateTimeInterface; +use FireflyIII\Models\CurrencyExchangeRate; +use FireflyIII\Models\TransactionCurrency; +use Log; + +/** + * Trait ConvertsExchangeRates + */ +trait ConvertsExchangeRates +{ + private ?bool $enabled = null; + + /** + * @param array $set + * @return array + */ + public function cerChartSet(array $set): array + { + if (null === $this->enabled) { + $this->getPreference(); + } + + // if not enabled, return the same array but without conversion: + if (false === $this->enabled) { + $set['converted'] = false; + return $set; + } + + $set['converted'] = true; + /** @var TransactionCurrency $native */ + $native = app('amount')->getDefaultCurrency(); + $currency = $this->getCurrency((int)$set['currency_id']); + if ($native->id === $currency->id) { + $set['native_id'] = (string)$currency->id; + $set['native_code'] = $currency->code; + $set['native_symbol'] = $currency->symbol; + $set['native_decimal_places'] = $currency->decimal_places; + return $set; + } + foreach ($set['entries'] as $date => $entry) { + $carbon = Carbon::createFromFormat(DateTimeInterface::ATOM, $date); + $rate = $this->getRate($currency, $native, $carbon); + $rate = '0' === $rate ? '1' : $rate; + Log::debug(sprintf('bcmul("%s", "%s")', (string)$entry, $rate)); + $set['entries'][$date] = (float)bcmul((string)$entry, $rate); + } + return $set; + } + + /** + * For a sum of entries, get the exchange rate to the native currency of + * the user. + * @param array $entries + * @return array + */ + public function cerSum(array $entries): array + { + if (null === $this->enabled) { + $this->getPreference(); + } + + // if false, return the same array without conversion info + if (false === $this->enabled) { + $return = []; + /** @var array $entry */ + foreach ($entries as $entry) { + $entry['converted'] = false; + $return[] = $entry; + } + return $return; + } + + + /** @var TransactionCurrency $native */ + $native = app('amount')->getDefaultCurrency(); + $return = []; + /** @var array $entry */ + foreach ($entries as $entry) { + $currency = $this->getCurrency((int)$entry['id']); + if ($currency->id !== $native->id) { + $amount = $this->convertAmount($entry['sum'], $currency, $native); + $entry['converted'] = true; + $entry['native_sum'] = $amount; + $entry['native_id'] = (string)$native->id; + $entry['native_name'] = $native->name; + $entry['native_symbol'] = $native->symbol; + $entry['native_code'] = $native->code; + $entry['native_decimal_places'] = $native->decimal_places; + } + if ($currency->id === $native->id) { + $entry['converted'] = false; + $entry['native_sum'] = $entry['sum']; + $entry['native_id'] = (string)$native->id; + $entry['native_name'] = $native->name; + $entry['native_symbol'] = $native->symbol; + $entry['native_code'] = $native->code; + $entry['native_decimal_places'] = $native->decimal_places; + } + $return[] = $entry; + } + return $return; + } + + /** + * @return void + */ + private function getPreference(): void + { + $this->enabled = true; + } + + /** + * @param int $currencyId + * @return TransactionCurrency + */ + private function getCurrency(int $currencyId): TransactionCurrency + { + $result = TransactionCurrency::find($currencyId); + if (null === $result) { + return app('amount')->getDefaultCurrency(); + } + return $result; + } + + /** + * @param string $amount + * @param TransactionCurrency $from + * @param TransactionCurrency $to + * @return string + */ + private function convertAmount(string $amount, TransactionCurrency $from, TransactionCurrency $to, ?Carbon $date = null): string + { + Log::debug(sprintf('Converting %s from %s to %s', $amount, $from->code, $to->code)); + $date = $date ?? Carbon::now(); + $rate = $this->getRate($from, $to, $date); + + return bcmul($amount, $rate); + } + + /** + * @param TransactionCurrency $from + * @param TransactionCurrency $to + * @param Carbon $date + * @return string + */ + private function getRate(TransactionCurrency $from, TransactionCurrency $to, Carbon $date): string + { + Log::debug(sprintf('getRate(%s, %s, "%s")', $from->code, $to->code, $date->format('Y-m-d'))); + /** @var CurrencyExchangeRate $result */ + $result = auth()->user() + ->currencyExchangeRates() + ->where('from_currency_id', $from->id) + ->where('to_currency_id', $to->id) + ->where('date', '<=', $date->format('Y-m-d')) + ->orderBy('date', 'DESC') + ->first(); + if (null !== $result) { + $rate = (string)$result->rate; + Log::debug(sprintf('Rate is %s', $rate)); + return $rate; + } + // no result. perhaps the other way around? + /** @var CurrencyExchangeRate $result */ + $result = auth()->user() + ->currencyExchangeRates() + ->where('from_currency_id', $to->id) + ->where('to_currency_id', $from->id) + ->where('date', '<=', $date->format('Y-m-d')) + ->orderBy('date', 'DESC') + ->first(); + if (null !== $result) { + $rate = bcdiv('1', (string)$result->rate); + Log::debug(sprintf('Reversed rate is %s', $rate)); + return $rate; + } + // try euro rates + $result1 = $this->getEuroRate($from, $date); + if ('0' === $result1) { + Log::debug(sprintf('No exchange rate between EUR and %s', $from->code)); + return '0'; + } + $result2 = $this->getEuroRate($to, $date); + if ('0' === $result2) { + Log::debug(sprintf('No exchange rate between EUR and %s', $to->code)); + return '0'; + } + // still need to inverse rate 2: + $result2 = bcdiv('1', $result2); + $rate = bcmul($result1, $result2); + Log::debug(sprintf('Rate %s to EUR is %s', $from->code, $result1)); + Log::debug(sprintf('Rate EUR to %s is %s', $to->code, $result2)); + Log::debug(sprintf('Rate for %s to %s is %s', $from->code, $to->code, $rate)); + return $rate; + } + + /** + * @param TransactionCurrency $currency + * @param Carbon $date + * @return string + */ + private function getEuroRate(TransactionCurrency $currency, Carbon $date): string + { + Log::debug(sprintf('Find rate for %s to Euro', $currency->code)); + $euro = TransactionCurrency::whereCode('EUR')->first(); + if (null === $euro) { + app('log')->warning('Cannot do indirect conversion without EUR.'); + return '0'; + } + + // try one way: + /** @var CurrencyExchangeRate $result */ + $result = auth()->user() + ->currencyExchangeRates() + ->where('from_currency_id', $currency->id) + ->where('to_currency_id', $euro->id) + ->where('date', '<=', $date->format('Y-m-d')) + ->orderBy('date', 'DESC') + ->first(); + if (null !== $result) { + $rate = (string)$result->rate; + Log::debug(sprintf('Rate for %s to EUR is %s.', $currency->code, $rate)); + return $rate; + } + // try the other way around and inverse it. + /** @var CurrencyExchangeRate $result */ + $result = auth()->user() + ->currencyExchangeRates() + ->where('from_currency_id', $euro->id) + ->where('to_currency_id', $currency->id) + ->where('date', '<=', $date->format('Y-m-d')) + ->orderBy('date', 'DESC') + ->first(); + if (null !== $result) { + $rate = bcdiv('1', (string)$result->rate); + Log::debug(sprintf('Inverted rate for %s to EUR is %s.', $currency->code, $rate)); + return $rate; + } + + Log::debug(sprintf('No rate for %s to EUR.', $currency->code)); + return '0'; + } +} diff --git a/app/Support/Http/Api/TransactionFilter.php b/app/Support/Http/Api/TransactionFilter.php index f0e703860d..b5b4376df0 100644 --- a/app/Support/Http/Api/TransactionFilter.php +++ b/app/Support/Http/Api/TransactionFilter.php @@ -35,15 +35,20 @@ trait TransactionFilter /** * All the types you can request. * - * @param string $type + * @param string $type * * @return array */ protected function mapTransactionTypes(string $type): array { $types = [ - 'all' => [TransactionType::WITHDRAWAL, TransactionType::DEPOSIT, TransactionType::TRANSFER, TransactionType::OPENING_BALANCE, - TransactionType::RECONCILIATION,], + 'all' => [ + TransactionType::WITHDRAWAL, + TransactionType::DEPOSIT, + TransactionType::TRANSFER, + TransactionType::OPENING_BALANCE, + TransactionType::RECONCILIATION, + ], 'withdrawal' => [TransactionType::WITHDRAWAL,], 'withdrawals' => [TransactionType::WITHDRAWAL,], 'expense' => [TransactionType::WITHDRAWAL,], diff --git a/app/Support/Http/Controllers/AugumentData.php b/app/Support/Http/Controllers/AugumentData.php index 8cf762f790..1db9fb5f8f 100644 --- a/app/Support/Http/Controllers/AugumentData.php +++ b/app/Support/Http/Controllers/AugumentData.php @@ -37,7 +37,6 @@ use FireflyIII\Repositories\Budget\OperationsRepositoryInterface; use FireflyIII\Repositories\Category\CategoryRepositoryInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; -use JsonException; /** * Trait AugumentData @@ -48,7 +47,7 @@ trait AugumentData /** * Searches for the opposing account. * - * @param Collection $accounts + * @param Collection $accounts * * @return array */ @@ -59,7 +58,7 @@ trait AugumentData $combined = []; /** @var Account $expenseAccount */ foreach ($accounts as $expenseAccount) { - $collection = new Collection; + $collection = new Collection(); $collection->push($expenseAccount); $revenue = $repository->findByName($expenseAccount->name, [AccountType::REVENUE]); @@ -75,7 +74,7 @@ trait AugumentData /** * Small helper function for the revenue and expense account charts. * - * @param array $names + * @param array $names * * @return array */ @@ -92,7 +91,7 @@ trait AugumentData /** * Small helper function for the revenue and expense account charts. * - * @param Collection $accounts + * @param Collection $accounts * * @return array */ @@ -110,7 +109,7 @@ trait AugumentData /** * Get the account names belonging to a bunch of account ID's. * - * @param array $accountIds + * @param array $accountIds * * @return array */ @@ -123,7 +122,7 @@ trait AugumentData $return = []; foreach ($accountIds as $combinedId) { $parts = explode('-', $combinedId); - $accountId = (int) $parts[0]; + $accountId = (int)$parts[0]; if (array_key_exists($accountId, $grouped)) { $return[$accountId] = $grouped[$accountId][0]['name']; } @@ -136,7 +135,7 @@ trait AugumentData /** * Get the budget names from a set of budget ID's. * - * @param array $budgetIds + * @param array $budgetIds * * @return array */ @@ -152,7 +151,7 @@ trait AugumentData $return[$budgetId] = $grouped[$budgetId][0]['name']; } } - $return[0] = (string) trans('firefly.no_budget'); + $return[0] = (string)trans('firefly.no_budget'); return $return; } @@ -160,7 +159,7 @@ trait AugumentData /** * Get the category names from a set of category ID's. Small helper function for some of the charts. * - * @param array $categoryIds + * @param array $categoryIds * * @return array */ @@ -173,12 +172,12 @@ trait AugumentData $return = []; foreach ($categoryIds as $combinedId) { $parts = explode('-', $combinedId); - $categoryId = (int) $parts[0]; + $categoryId = (int)$parts[0]; if (array_key_exists($categoryId, $grouped)) { $return[$categoryId] = $grouped[$categoryId][0]['name']; } } - $return[0] = (string) trans('firefly.no_category'); + $return[0] = (string)trans('firefly.no_category'); return $return; } @@ -186,9 +185,9 @@ trait AugumentData /** * Gets all budget limits for a budget. * - * @param Budget $budget - * @param Carbon $start - * @param Carbon $end + * @param Budget $budget + * @param Carbon $start + * @param Carbon $end * * @return Collection */ @@ -200,7 +199,7 @@ trait AugumentData /** @var BudgetLimitRepositoryInterface $blRepository */ $blRepository = app(BudgetLimitRepositoryInterface::class); // properties for cache - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty($budget->id); @@ -221,7 +220,7 @@ trait AugumentData $currentStart = clone $entry->start_date; $currentEnd = clone $entry->end_date; $expenses = $opsRepository->sumExpenses($currentStart, $currentEnd, null, $budgetCollection, $currency); - $spent = $expenses[(int) $currency->id]['sum'] ?? '0'; + $spent = $expenses[(int)$currency->id]['sum'] ?? '0'; $entry->spent = $spent; $limits->push($entry); @@ -234,13 +233,12 @@ trait AugumentData /** * Group set of transactions by name of opposing account. * - * @param array $array + * @param array $array * * @return array */ protected function groupByName(array $array): array // filter + group data { - // group by opposing account name. $grouped = []; /** @var array $journal */ @@ -263,10 +261,10 @@ trait AugumentData /** * Spent in a period. * - * @param Collection $assets - * @param Collection $opposing - * @param Carbon $start - * @param Carbon $end + * @param Collection $assets + * @param Collection $opposing + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -284,7 +282,7 @@ trait AugumentData ]; // loop to support multi currency foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; // if not set, set to zero: if (!array_key_exists($currencyId, $sum['per_currency'])) { diff --git a/app/Support/Http/Controllers/BasicDataSupport.php b/app/Support/Http/Controllers/BasicDataSupport.php index 360634330b..d0bc600038 100644 --- a/app/Support/Http/Controllers/BasicDataSupport.php +++ b/app/Support/Http/Controllers/BasicDataSupport.php @@ -34,8 +34,8 @@ trait BasicDataSupport /** * Find the ID in a given array. Return '0' if not there (amount). * - * @param array $array - * @param int $entryId + * @param array $array + * @param int $entryId * * @return null|mixed */ @@ -47,8 +47,8 @@ trait BasicDataSupport /** * Find the ID in a given array. Return null if not there (amount). * - * @param array $array - * @param int $entryId + * @param array $array + * @param int $entryId * * @return null|Carbon */ diff --git a/app/Support/Http/Controllers/ChartGeneration.php b/app/Support/Http/Controllers/ChartGeneration.php index 0db3129191..ce5518e8d3 100644 --- a/app/Support/Http/Controllers/ChartGeneration.php +++ b/app/Support/Http/Controllers/ChartGeneration.php @@ -42,9 +42,9 @@ trait ChartGeneration /** * Shows an overview of the account balances for a set of accounts. * - * @param Collection $accounts - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Carbon $start + * @param Carbon $end * * @return array * @throws FireflyException @@ -52,7 +52,6 @@ trait ChartGeneration */ protected function accountBalanceChart(Collection $accounts, Carbon $start, Carbon $end): array // chart helper method. { - // chart properties for cache: $cache = new CacheProperties(); $cache->addProperty($start); @@ -76,8 +75,8 @@ trait ChartGeneration $chartData = []; /** @var Account $account */ foreach ($accounts as $account) { - // See reference nr. 33 - $currency = $repository->find((int) $accountRepos->getMetaValue($account, 'currency_id')); + // TODO we can use getAccountCurrency instead. + $currency = $repository->find((int)$accountRepos->getMetaValue($account, 'currency_id')); if (null === $currency) { $currency = $default; } @@ -92,7 +91,7 @@ trait ChartGeneration $previous = array_values($range)[0]; while ($currentStart <= $end) { $format = $currentStart->format('Y-m-d'); - $label = trim($currentStart->isoFormat((string) trans('config.month_and_day_js', [], $locale))); + $label = trim($currentStart->isoFormat((string)trans('config.month_and_day_js', [], $locale))); $balance = $range[$format] ?? $previous; $previous = $balance; $currentStart->addDay(); diff --git a/app/Support/Http/Controllers/CreateStuff.php b/app/Support/Http/Controllers/CreateStuff.php index 4ec6aec618..368b57ea1e 100644 --- a/app/Support/Http/Controllers/CreateStuff.php +++ b/app/Support/Http/Controllers/CreateStuff.php @@ -39,12 +39,11 @@ use phpseclib3\Crypt\RSA; */ trait CreateStuff { - /** * Creates an asset account. * - * @param NewUserFormRequest $request - * @param TransactionCurrency $currency + * @param NewUserFormRequest $request + * @param TransactionCurrency $currency * * @return bool */ @@ -61,7 +60,7 @@ trait CreateStuff 'active' => true, 'account_role' => 'defaultAsset', 'opening_balance' => $request->input('bank_balance'), - 'opening_balance_date' => new Carbon, + 'opening_balance_date' => new Carbon(), 'currency_id' => $currency->id, ]; @@ -73,8 +72,8 @@ trait CreateStuff /** * Creates a cash wallet. * - * @param TransactionCurrency $currency - * @param string $language + * @param TransactionCurrency $currency + * @param string $language * * @return bool */ @@ -83,7 +82,7 @@ trait CreateStuff /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $assetAccount = [ - 'name' => (string) trans('firefly.cash_wallet', [], $language), + 'name' => (string)trans('firefly.cash_wallet', [], $language), 'iban' => null, 'account_type_name' => 'asset', 'virtual_balance' => 0, @@ -120,7 +119,7 @@ trait CreateStuff if (class_exists(LegacyRSA::class)) { // PHP 7 Log::info('Will run PHP7 code.'); - $keys = (new LegacyRSA)->createKey(4096); + $keys = (new LegacyRSA())->createKey(4096); } if (!class_exists(LegacyRSA::class)) { @@ -139,9 +138,9 @@ trait CreateStuff /** * Create a savings account. * - * @param NewUserFormRequest $request - * @param TransactionCurrency $currency - * @param string $language + * @param NewUserFormRequest $request + * @param TransactionCurrency $currency + * @param string $language * * @return bool */ @@ -150,7 +149,7 @@ trait CreateStuff /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $savingsAccount = [ - 'name' => (string) trans('firefly.new_savings_account', ['bank_name' => $request->get('bank_name')], $language), + 'name' => (string)trans('firefly.new_savings_account', ['bank_name' => $request->get('bank_name')], $language), 'iban' => null, 'account_type_name' => 'asset', 'account_type_id' => null, @@ -158,7 +157,7 @@ trait CreateStuff 'active' => true, 'account_role' => 'savingAsset', 'opening_balance' => $request->input('savings_balance'), - 'opening_balance_date' => new Carbon, + 'opening_balance_date' => new Carbon(), 'currency_id' => $currency->id, ]; $repository->store($savingsAccount); @@ -169,7 +168,7 @@ trait CreateStuff /** * Create a new user instance after a valid registration. * - * @param array $data + * @param array $data * * @return User */ @@ -182,5 +181,4 @@ trait CreateStuff ] ); } - } diff --git a/app/Support/Http/Controllers/CronRunner.php b/app/Support/Http/Controllers/CronRunner.php index 89e93ef55d..db119cab87 100644 --- a/app/Support/Http/Controllers/CronRunner.php +++ b/app/Support/Http/Controllers/CronRunner.php @@ -34,8 +34,8 @@ use FireflyIII\Support\Cronjobs\RecurringCronjob; trait CronRunner { /** - * @param bool $force - * @param Carbon $date + * @param bool $force + * @param Carbon $date * * @return array */ @@ -65,8 +65,8 @@ trait CronRunner } /** - * @param bool $force - * @param Carbon $date + * @param bool $force + * @param Carbon $date * * @return array */ @@ -93,8 +93,5 @@ trait CronRunner 'job_errored' => $recurring->jobErrored, 'message' => $recurring->message, ]; - } - - } diff --git a/app/Support/Http/Controllers/DateCalculation.php b/app/Support/Http/Controllers/DateCalculation.php index 05d2b44421..563146f321 100644 --- a/app/Support/Http/Controllers/DateCalculation.php +++ b/app/Support/Http/Controllers/DateCalculation.php @@ -37,8 +37,8 @@ trait DateCalculation * * If both are in the past OR both are in the future, simply return the number of days in the period with a minimum of 1 * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return int */ @@ -59,8 +59,8 @@ trait DateCalculation * * If both are in the past OR both are in the future, simply return the period between them with a minimum of 1 * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return int */ @@ -77,14 +77,13 @@ trait DateCalculation } /** - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return string */ protected function calculateStep(Carbon $start, Carbon $end): string { - $step = '1D'; $months = $start->diffInMonths($end); if ($months > 3) { @@ -104,8 +103,8 @@ trait DateCalculation * Get a list of the periods that will occur after this date. For example, * March 2018, April 2018, etc. * - * @param Carbon $date - * @param string $range + * @param Carbon $date + * @param string $range * * @return array */ @@ -140,8 +139,8 @@ trait DateCalculation * Get a list of the periods that occurred before the start date. For example, * March 2018, February 2018, etc. * - * @param Carbon $date - * @param string $range + * @param Carbon $date + * @param string $range * * @return array */ @@ -167,5 +166,4 @@ trait DateCalculation return $loop; } - } diff --git a/app/Support/Http/Controllers/GetConfigurationData.php b/app/Support/Http/Controllers/GetConfigurationData.php index 8ee87faca6..7b5561d3a2 100644 --- a/app/Support/Http/Controllers/GetConfigurationData.php +++ b/app/Support/Http/Controllers/GetConfigurationData.php @@ -26,6 +26,8 @@ namespace FireflyIII\Support\Http\Controllers; use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Trait GetConfigurationData @@ -36,7 +38,7 @@ trait GetConfigurationData /** * Some common combinations. * - * @param int $value + * @param int $value * * @return string */ @@ -52,13 +54,13 @@ trait GetConfigurationData E_COMPILE_ERROR | E_RECOVERABLE_ERROR | E_ERROR | E_CORE_ERROR => 'E_COMPILE_ERROR|E_RECOVERABLE_ERROR|E_ERROR|E_CORE_ERROR', ]; - return $array[$value] ?? (string) $value; + return $array[$value] ?? (string)$value; } /** * Get the basic steps from config. * - * @param string $route + * @param string $route * * @return array */ @@ -72,7 +74,7 @@ trait GetConfigurationData $currentStep = $options; // get the text: - $currentStep['intro'] = (string) trans('intro.' . $route . '_' . $key); + $currentStep['intro'] = (string)trans('intro.'.$route.'_'.$key); // save in array: $steps[] = $currentStep; @@ -88,12 +90,12 @@ trait GetConfigurationData * * @return array * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ protected function getDateRangeConfig(): array // get configuration + get preferences. { - $viewRange = (string) app('preferences')->get('viewRange', '1M')->data; + $viewRange = (string)app('preferences')->get('viewRange', '1M')->data; /** @var Carbon $start */ $start = session('start'); /** @var Carbon $end */ @@ -134,41 +136,41 @@ trait GetConfigurationData /** @var Carbon $todayEnd */ $todayEnd = app('navigation')->endOfPeriod($todayStart, $viewRange); if ($todayStart->ne($start) || $todayEnd->ne($end)) { - $ranges[ucfirst((string) trans('firefly.today'))] = [$todayStart, $todayEnd]; + $ranges[ucfirst((string)trans('firefly.today'))] = [$todayStart, $todayEnd]; } // last seven days: $seven = Carbon::now()->subDays(7); - $index = (string) trans('firefly.last_seven_days'); - $ranges[$index] = [$seven, new Carbon]; + $index = (string)trans('firefly.last_seven_days'); + $ranges[$index] = [$seven, new Carbon()]; // last 30 days: $thirty = Carbon::now()->subDays(30); - $index = (string) trans('firefly.last_thirty_days'); - $ranges[$index] = [$thirty, new Carbon]; + $index = (string)trans('firefly.last_thirty_days'); + $ranges[$index] = [$thirty, new Carbon()]; // month to date: $monthBegin = Carbon::now()->startOfMonth(); - $index = (string) trans('firefly.month_to_date'); - $ranges[$index] = [$monthBegin, new Carbon]; + $index = (string)trans('firefly.month_to_date'); + $ranges[$index] = [$monthBegin, new Carbon()]; // year to date: $yearBegin = Carbon::now()->startOfYear(); - $index = (string) trans('firefly.year_to_date'); - $ranges[$index] = [$yearBegin, new Carbon]; + $index = (string)trans('firefly.year_to_date'); + $ranges[$index] = [$yearBegin, new Carbon()]; // everything - $index = (string) trans('firefly.everything'); - $ranges[$index] = [$first, new Carbon]; + $index = (string)trans('firefly.everything'); + $ranges[$index] = [$first, new Carbon()]; return [ 'title' => $title, 'configuration' => [ - 'apply' => (string) trans('firefly.apply'), - 'cancel' => (string) trans('firefly.cancel'), - 'from' => (string) trans('firefly.from'), - 'to' => (string) trans('firefly.to'), - 'customRange' => (string) trans('firefly.customRange'), + 'apply' => (string)trans('firefly.apply'), + 'cancel' => (string)trans('firefly.cancel'), + 'from' => (string)trans('firefly.from'), + 'to' => (string)trans('firefly.to'), + 'customRange' => (string)trans('firefly.customRange'), 'start' => $start->format('Y-m-d'), 'end' => $end->format('Y-m-d'), 'ranges' => $ranges, @@ -179,8 +181,8 @@ trait GetConfigurationData /** * Get specific info for special routes. * - * @param string $route - * @param string $specificPage + * @param string $route + * @param string $specificPage * * @return array * @@ -193,13 +195,13 @@ trait GetConfigurationData // user is on page with specific instructions: if ('' !== $specificPage) { $routeKey = str_replace('.', '_', $route); - $elements = config(sprintf('intro.%s', $routeKey . '_' . $specificPage)); + $elements = config(sprintf('intro.%s', $routeKey.'_'.$specificPage)); if (is_array($elements) && count($elements) > 0) { foreach ($elements as $key => $options) { $currentStep = $options; // get the text: - $currentStep['intro'] = (string) trans('intro.' . $route . '_' . $specificPage . '_' . $key); + $currentStep['intro'] = (string)trans('intro.'.$route.'_'.$specificPage.'_'.$key); // save in array: $steps[] = $currentStep; @@ -217,7 +219,7 @@ trait GetConfigurationData protected function verifyRecurringCronJob(): void { $config = app('fireflyconfig')->get('last_rt_job', 0); - $lastTime = (int) $config->data; + $lastTime = (int)$config->data; $now = time(); Log::debug(sprintf('verifyRecurringCronJob: last time is %d ("%s"), now is %d', $lastTime, $config->data, $now)); if (0 === $lastTime) { diff --git a/app/Support/Http/Controllers/ModelInformation.php b/app/Support/Http/Controllers/ModelInformation.php index 621dd26b84..957549e1cd 100644 --- a/app/Support/Http/Controllers/ModelInformation.php +++ b/app/Support/Http/Controllers/ModelInformation.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Http\Controllers; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\AccountType; use FireflyIII\Models\Bill; use FireflyIII\Models\Tag; @@ -41,7 +42,7 @@ trait ModelInformation /** * Get actions based on a bill. * - * @param Bill $bill + * @param Bill $bill * * @return array */ @@ -57,10 +58,11 @@ trait ModelInformation 'count' => 1, ] )->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Throwable was thrown in getActionsForBill(): %s', $e->getMessage())); Log::error($e->getTraceAsString()); $result = 'Could not render view. See log files.'; + throw new FireflyException($result, 0, $e); } return [$result]; @@ -78,14 +80,13 @@ trait ModelInformation /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); // types of liability: - $debt = $repository->getAccountTypeByType(AccountType::DEBT); - $loan = $repository->getAccountTypeByType(AccountType::LOAN); - $mortgage = $repository->getAccountTypeByType(AccountType::MORTGAGE); - /** @noinspection NullPointerExceptionInspection */ + $debt = $repository->getAccountTypeByType(AccountType::DEBT); + $loan = $repository->getAccountTypeByType(AccountType::LOAN); + $mortgage = $repository->getAccountTypeByType(AccountType::MORTGAGE); $liabilityTypes = [ - $debt->id => (string) trans(sprintf('firefly.account_type_%s', AccountType::DEBT)), - $loan->id => (string) trans(sprintf('firefly.account_type_%s', AccountType::LOAN)), - $mortgage->id => (string) trans(sprintf('firefly.account_type_%s', AccountType::MORTGAGE)), + $debt->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::DEBT)), + $loan->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::LOAN)), + $mortgage->id => (string)trans(sprintf('firefly.account_type_%s', AccountType::MORTGAGE)), ]; asort($liabilityTypes); @@ -100,7 +101,7 @@ trait ModelInformation { $roles = []; foreach (config('firefly.accountRoles') as $role) { - $roles[$role] = (string) trans(sprintf('firefly.account_role_%s', $role)); + $roles[$role] = (string)trans(sprintf('firefly.account_role_%s', $role)); } return $roles; @@ -109,19 +110,18 @@ trait ModelInformation /** * Create fake triggers to match the bill's properties * - * @param Bill $bill + * @param Bill $bill * * @return array */ protected function getTriggersForBill(Bill $bill): array // get info and augument { - // See reference nr. 39 + // TODO duplicate code $operators = config('search.operators'); $triggers = []; foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - - $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); @@ -146,11 +146,11 @@ trait ModelInformation 'triggers' => $triggers, ] )->render(); - } catch (Throwable $e) { // @phpstan-ignore-line - + } catch (Throwable $e) { Log::debug(sprintf('Throwable was thrown in getTriggersForBill(): %s', $e->getMessage())); Log::debug($e->getTraceAsString()); $string = ''; + throw new FireflyException('Could not render trigger', 0, $e); } if ('' !== $string) { $result[] = $string; @@ -161,7 +161,7 @@ trait ModelInformation } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return array */ @@ -172,8 +172,7 @@ trait ModelInformation $triggers = []; foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - - $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); @@ -262,11 +261,11 @@ trait ModelInformation 'triggers' => $triggers, ] )->render(); - } catch (Throwable $e) { // @phpstan-ignore-line - + } catch (Throwable $e) { Log::debug(sprintf('Throwable was thrown in getTriggersForJournal(): %s', $e->getMessage())); Log::debug($e->getTraceAsString()); $string = ''; + throw new FireflyException('Could not render trigger', 0, $e); } if ('' !== $string) { $result[] = $string; diff --git a/app/Support/Http/Controllers/PeriodOverview.php b/app/Support/Http/Controllers/PeriodOverview.php index af093ba365..60d1d2e5c6 100644 --- a/app/Support/Http/Controllers/PeriodOverview.php +++ b/app/Support/Http/Controllers/PeriodOverview.php @@ -33,13 +33,14 @@ use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Journal\JournalRepositoryInterface; use FireflyIII\Support\CacheProperties; use Illuminate\Support\Collection; -use JsonException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; /** * Trait PeriodOverview. * - * See reference nr. 36 + * TODO verify this all works as expected. * * - Always request start date and end date. * - Group expenses, income, etc. under this period. @@ -73,14 +74,14 @@ trait PeriodOverview * and for each period, the amount of money spent and earned. This is a complex operation which is cached for * performance reasons. * - * @param Account $account - * @param Carbon $start - * @param Carbon $end + * @param Account $account + * @param Carbon $start + * @param Carbon $end * * @return array * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ protected function getAccountPeriodOverview(Account $account, Carbon $start, Carbon $end): array { @@ -88,7 +89,7 @@ trait PeriodOverview [$start, $end] = $end < $start ? [$end, $start] : [$start, $end]; // properties for cache - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('account-show-period-entries'); @@ -152,9 +153,9 @@ trait PeriodOverview /** * Filter a list of journals by a set of dates, and then group them by currency. * - * @param array $array - * @param Carbon $start - * @param Carbon $end + * @param array $array + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -174,8 +175,8 @@ trait PeriodOverview /** * Return only transactions where $account is the source. * - * @param Account $account - * @param array $journals + * @param Account $account + * @param array $journals * * @return array */ @@ -184,7 +185,7 @@ trait PeriodOverview $return = []; /** @var array $journal */ foreach ($journals as $journal) { - if ($account->id === (int) $journal['source_account_id']) { + if ($account->id === (int)$journal['source_account_id']) { $return[] = $journal; } } @@ -195,8 +196,8 @@ trait PeriodOverview /** * Return only transactions where $account is the source. * - * @param Account $account - * @param array $journals + * @param Account $account + * @param array $journals * * @return array * @codeCoverageIgnore @@ -206,7 +207,7 @@ trait PeriodOverview $return = []; /** @var array $journal */ foreach ($journals as $journal) { - if ($account->id === (int) $journal['destination_account_id']) { + if ($account->id === (int)$journal['destination_account_id']) { $return[] = $journal; } } @@ -215,7 +216,7 @@ trait PeriodOverview } /** - * @param array $journals + * @param array $journals * * @return array * @codeCoverageIgnore @@ -225,7 +226,7 @@ trait PeriodOverview $return = []; /** @var array $journal */ foreach ($journals as $journal) { - $currencyId = (int) $journal['currency_id']; + $currencyId = (int)$journal['currency_id']; $foreignCurrencyId = $journal['foreign_currency_id']; if (!array_key_exists($currencyId, $return)) { $return[$currencyId] = [ @@ -246,18 +247,16 @@ trait PeriodOverview $return[$foreignCurrencyId] = [ 'amount' => '0', 'count' => 0, - 'currency_id' => (int) $foreignCurrencyId, + 'currency_id' => (int)$foreignCurrencyId, 'currency_name' => $journal['foreign_currency_name'], 'currency_code' => $journal['foreign_currency_code'], 'currency_symbol' => $journal['foreign_currency_symbol'], 'currency_decimal_places' => $journal['foreign_currency_decimal_places'], ]; - } $return[$foreignCurrencyId]['count']++; $return[$foreignCurrencyId]['amount'] = bcadd($return[$foreignCurrencyId]['amount'], $journal['foreign_amount']); } - } return $return; @@ -266,14 +265,14 @@ trait PeriodOverview /** * Overview for single category. Has been refactored recently. * - * @param Category $category - * @param Carbon $start - * @param Carbon $end + * @param Category $category + * @param Carbon $start + * @param Carbon $end * * @return array * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ protected function getCategoryPeriodOverview(Category $category, Carbon $start, Carbon $end): array { @@ -347,13 +346,13 @@ trait PeriodOverview * * This method has been refactored recently. * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return array * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ protected function getNoBudgetPeriodOverview(Carbon $start, Carbon $end): array { @@ -361,7 +360,7 @@ trait PeriodOverview [$start, $end] = $end < $start ? [$end, $start] : [$start, $end]; - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('no-budget-period-entries'); @@ -399,24 +398,24 @@ trait PeriodOverview } /** - * See reference nr. 37 + * TODO fix the date. * * Show period overview for no category view. * - * @param Carbon $theDate + * @param Carbon $theDate * * @return array * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ protected function getNoCategoryPeriodOverview(Carbon $theDate): array { Log::debug(sprintf('Now in getNoCategoryPeriodOverview(%s)', $theDate->format('Y-m-d'))); $range = app('preferences')->get('viewRange', '1M')->data; $first = $this->journalRepos->firstNull(); - $start = null === $first ? new Carbon : $first->date; - $end = $theDate ?? today(config('app.timezone')); + $start = null === $first ? new Carbon() : $first->date; + $end = clone $theDate; 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'))); @@ -473,23 +472,22 @@ trait PeriodOverview /** * This shows a period overview for a tag. It goes back in time and lists all relevant transactions and sums. * - * @param Tag $tag - * @param Carbon $start - * @param Carbon $end + * @param Tag $tag + * @param Carbon $start + * @param Carbon $end * * @return array * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ protected function getTagPeriodOverview(Tag $tag, Carbon $start, Carbon $end): array // period overview for tags. { - $range = app('preferences')->get('viewRange', '1M')->data; [$start, $end] = $end < $start ? [$end, $start] : [$start, $end]; // properties for cache - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('tag-period-entries'); @@ -549,14 +547,14 @@ trait PeriodOverview } /** - * @param string $transactionType - * @param Carbon $start - * @param Carbon $end + * @param string $transactionType + * @param Carbon $start + * @param Carbon $end * * @return array * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ protected function getTransactionPeriodOverview(string $transactionType, Carbon $start, Carbon $end): array { @@ -565,7 +563,7 @@ trait PeriodOverview [$start, $end] = $end < $start ? [$end, $start] : [$start, $end]; // properties for cache - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($start); $cache->addProperty($end); $cache->addProperty('transactions-period-entries'); diff --git a/app/Support/Http/Controllers/RenderPartialViews.php b/app/Support/Http/Controllers/RenderPartialViews.php index 3990c7bbc2..026bffd204 100644 --- a/app/Support/Http/Controllers/RenderPartialViews.php +++ b/app/Support/Http/Controllers/RenderPartialViews.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Http\Controllers; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Helpers\Report\PopupReportInterface; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; @@ -44,11 +45,10 @@ use Throwable; */ trait RenderPartialViews { - /** * View for transactions in a budget for an account. * - * @param array $attributes + * @param array $attributes * * @return string */ @@ -59,18 +59,19 @@ trait RenderPartialViews /** @var BudgetRepositoryInterface $budgetRepository */ $budgetRepository = app(BudgetRepositoryInterface::class); - $budget = $budgetRepository->find((int) $attributes['budgetId']); + $budget = $budgetRepository->find((int)$attributes['budgetId']); $accountRepos = app(AccountRepositoryInterface::class); - $account = $accountRepos->find((int) $attributes['accountId']); + $account = $accountRepos->find((int)$attributes['accountId']); $journals = $popupHelper->balanceForBudget($budget, $account, $attributes); try { $view = view('popup.report.balance-amount', compact('journals', 'budget', 'account'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render: %s', $e->getMessage())); $view = 'Firefly III could not render the view. Please see the log files.'; + throw new FireflyException($view, 0, $e); } return $view; @@ -89,9 +90,10 @@ trait RenderPartialViews try { $result = view('reports.options.budget', compact('budgets'))->render(); - } catch (Throwable $e) {// @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } return $result; @@ -100,7 +102,7 @@ trait RenderPartialViews /** * View for spent in a single budget. * - * @param array $attributes + * @param array $attributes * * @return string */ @@ -112,17 +114,18 @@ trait RenderPartialViews /** @var PopupReportInterface $popupHelper */ $popupHelper = app(PopupReportInterface::class); - $budget = $budgetRepository->find((int) $attributes['budgetId']); + $budget = $budgetRepository->find((int)$attributes['budgetId']); if (null === $budget) { - $budget = new Budget; + $budget = new Budget(); } $journals = $popupHelper->byBudget($budget, $attributes); try { $view = view('popup.report.budget-spent-amount', compact('journals', 'budget'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render: %s', $e->getMessage())); $view = 'Firefly III could not render the view. Please see the log files.'; + throw new FireflyException($view, 0, $e); } return $view; @@ -131,7 +134,7 @@ trait RenderPartialViews /** * View for transactions in a category. * - * @param array $attributes + * @param array $attributes * * @return string */ @@ -142,14 +145,15 @@ trait RenderPartialViews /** @var CategoryRepositoryInterface $categoryRepository */ $categoryRepository = app(CategoryRepositoryInterface::class); - $category = $categoryRepository->find((int) $attributes['categoryId']); + $category = $categoryRepository->find((int)$attributes['categoryId']); $journals = $popupHelper->byCategory($category, $attributes); try { $view = view('popup.report.category-entry', compact('journals', 'category'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render: %s', $e->getMessage())); $view = 'Firefly III could not render the view. Please see the log files.'; + throw new FireflyException($view, 0, $e); } return $view; @@ -168,9 +172,10 @@ trait RenderPartialViews try { $result = view('reports.options.category', compact('categories'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.options.category: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } return $result; @@ -209,9 +214,10 @@ trait RenderPartialViews try { $result = view('reports.options.double', compact('set'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } return $result; @@ -220,7 +226,7 @@ trait RenderPartialViews /** * Returns all the expenses that went to the given expense account. * - * @param array $attributes + * @param array $attributes * * @return string */ @@ -232,7 +238,7 @@ trait RenderPartialViews /** @var PopupReportInterface $popupHelper */ $popupHelper = app(PopupReportInterface::class); - $account = $accountRepository->find((int) $attributes['accountId']); + $account = $accountRepository->find((int)$attributes['accountId']); if (null === $account) { return 'This is an unknown account. Apologies.'; @@ -242,9 +248,10 @@ trait RenderPartialViews try { $view = view('popup.report.expense-entry', compact('journals', 'account'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render: %s', $e->getMessage())); $view = 'Firefly III could not render the view. Please see the log files.'; + throw new FireflyException($view, 0, $e); } return $view; @@ -253,7 +260,7 @@ trait RenderPartialViews /** * Get current (from system) rule actions. * - * @param Rule $rule + * @param Rule $rule * * @return array */ @@ -276,10 +283,10 @@ trait RenderPartialViews 'count' => $count, ] )->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Throwable was thrown in getCurrentActions(): %s', $e->getMessage())); Log::error($e->getTraceAsString()); + throw new FireflyException('Could not render', 0, $e); } ++$index; @@ -291,20 +298,19 @@ trait RenderPartialViews /** * Get current (from DB) rule triggers. * - * @param Rule $rule + * @param Rule $rule * * @return array * */ protected function getCurrentTriggers(Rule $rule): array // get info from object and present. { - // See reference nr. 38 + // TODO duplicated code. $operators = config('search.operators'); $triggers = []; foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - - $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); @@ -317,20 +323,25 @@ trait RenderPartialViews if ('user_action' !== $entry->trigger_type) { $count = ($index + 1); try { + $rootOperator = OperatorQuerySearch::getRootOperator($entry->trigger_type); + if (str_starts_with($rootOperator, '-')) { + $rootOperator = substr($rootOperator, 1); + } $renderedEntries[] = view( 'rules.partials.trigger', [ - 'oldTrigger' => OperatorQuerySearch::getRootOperator($entry->trigger_type), - 'oldValue' => $entry->trigger_value, - 'oldChecked' => $entry->stop_processing, - 'count' => $count, - 'triggers' => $triggers, + 'oldTrigger' => $rootOperator, + 'oldValue' => $entry->trigger_value, + 'oldChecked' => $entry->stop_processing, + 'oldProhibited' => str_starts_with($entry->trigger_type, '-'), + 'count' => $count, + 'triggers' => $triggers, ] )->render(); - - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Throwable was thrown in getCurrentTriggers(): %s', $e->getMessage())); Log::error($e->getTraceAsString()); + throw new FireflyException('Could not render', 0, $e); } ++$index; @@ -343,7 +354,7 @@ trait RenderPartialViews /** * Returns all the incomes that went to the given asset account. * - * @param array $attributes + * @param array $attributes * * @return string */ @@ -354,7 +365,7 @@ trait RenderPartialViews /** @var PopupReportInterface $popupHelper */ $popupHelper = app(PopupReportInterface::class); - $account = $accountRepository->find((int) $attributes['accountId']); + $account = $accountRepository->find((int)$attributes['accountId']); if (null === $account) { return 'This is an unknown category. Apologies.'; @@ -364,9 +375,10 @@ trait RenderPartialViews try { $view = view('popup.report.income-entry', compact('journals', 'account'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Could not render: %s', $e->getMessage())); $view = 'Firefly III could not render the view. Please see the log files.'; + throw new FireflyException($view, 0, $e); } return $view; @@ -379,12 +391,12 @@ trait RenderPartialViews */ protected function noReportOptions(): string // render a view { - try { $result = view('reports.options.no-options')->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.options.no-options: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } return $result; @@ -404,9 +416,10 @@ trait RenderPartialViews try { $result = view('reports.options.tag', compact('tags'))->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.options.tag: %s', $e->getMessage())); $result = 'Could not render view.'; + throw new FireflyException($result, 0, $e); } return $result; diff --git a/app/Support/Http/Controllers/RequestInformation.php b/app/Support/Http/Controllers/RequestInformation.php index da3d4b3d63..e85afb2e81 100644 --- a/app/Support/Http/Controllers/RequestInformation.php +++ b/app/Support/Http/Controllers/RequestInformation.php @@ -37,6 +37,8 @@ use Illuminate\Routing\Route; use Illuminate\Support\Facades\Validator; use InvalidArgumentException; use Log; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; use Route as RouteFacade; /** @@ -88,8 +90,8 @@ trait RequestInformation * * @return bool * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ final protected function hasSeenDemo(): bool // get request info + get preference { @@ -230,5 +232,4 @@ trait RequestInformation ] ); } - } diff --git a/app/Support/Http/Controllers/RuleManagement.php b/app/Support/Http/Controllers/RuleManagement.php index 2144fa036d..a839b01018 100644 --- a/app/Support/Http/Controllers/RuleManagement.php +++ b/app/Support/Http/Controllers/RuleManagement.php @@ -23,6 +23,7 @@ declare(strict_types=1); namespace FireflyIII\Support\Http\Controllers; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Repositories\RuleGroup\RuleGroupRepositoryInterface; use FireflyIII\Support\Search\OperatorQuerySearch; use Illuminate\Http\Request; @@ -35,9 +36,8 @@ use Throwable; */ trait RuleManagement { - /** - * @param Request $request + * @param Request $request * * @return array * @codeCoverageIgnore @@ -55,13 +55,14 @@ trait RuleManagement [ 'oldAction' => $oldAction['type'], 'oldValue' => $oldAction['value'], - 'oldChecked' => 1 === (int) ($oldAction['stop_processing'] ?? '0'), + 'oldChecked' => 1 === (int)($oldAction['stop_processing'] ?? '0'), 'count' => $index + 1, ] )->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage())); Log::error($e->getTraceAsString()); + throw new FireflyException('Could not render', 0, $e); } $index++; } @@ -71,20 +72,19 @@ trait RuleManagement } /** - * @param Request $request + * @param Request $request * * @return array * @codeCoverageIgnore */ protected function getPreviousTriggers(Request $request): array { - // See reference nr. 34 + // TODO duplicated code. $operators = config('search.operators'); $triggers = []; foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - - $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); @@ -98,16 +98,18 @@ trait RuleManagement $renderedEntries[] = view( 'rules.partials.trigger', [ - 'oldTrigger' => OperatorQuerySearch::getRootOperator($oldTrigger['type']), - 'oldValue' => $oldTrigger['value'], - 'oldChecked' => 1 === (int) ($oldTrigger['stop_processing'] ?? '0'), - 'count' => $index + 1, - 'triggers' => $triggers, + 'oldTrigger' => OperatorQuerySearch::getRootOperator($oldTrigger['type']), + 'oldValue' => $oldTrigger['value'], + 'oldChecked' => 1 === (int)($oldTrigger['stop_processing'] ?? '0'), + 'oldProhibited' => 1 === (int)($oldTrigger['prohibited'] ?? '0'), + 'count' => $index + 1, + 'triggers' => $triggers, ] )->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage())); Log::error($e->getTraceAsString()); + throw new FireflyException('Could not render', 0, $e); } $index++; } @@ -117,20 +119,19 @@ trait RuleManagement } /** - * @param array $submittedOperators + * @param array $submittedOperators * * @return array */ protected function parseFromOperators(array $submittedOperators): array { - // See reference nr. 35 + // TODO duplicated code. $operators = config('search.operators'); $renderedEntries = []; $triggers = []; foreach ($operators as $key => $operator) { if ('user_action' !== $key && false === $operator['alias']) { - - $triggers[$key] = (string) trans(sprintf('firefly.rule_trigger_%s_choice', $key)); + $triggers[$key] = (string)trans(sprintf('firefly.rule_trigger_%s_choice', $key)); } } asort($triggers); @@ -148,9 +149,10 @@ trait RuleManagement 'triggers' => $triggers, ] )->render(); - } catch (Throwable $e) { // @phpstan-ignore-line + } catch (Throwable $e) { Log::debug(sprintf('Throwable was thrown in getPreviousTriggers(): %s', $e->getMessage())); Log::error($e->getTraceAsString()); + throw new FireflyException('Could not render', 0, $e); } $index++; } @@ -167,8 +169,8 @@ trait RuleManagement $repository = app(RuleGroupRepositoryInterface::class); if (0 === $repository->count()) { $data = [ - 'title' => (string) trans('firefly.default_rule_group_name'), - 'description' => (string) trans('firefly.default_rule_group_description'), + 'title' => (string)trans('firefly.default_rule_group_name'), + 'description' => (string)trans('firefly.default_rule_group_description'), 'active' => true, ]; diff --git a/app/Support/Http/Controllers/TransactionCalculation.php b/app/Support/Http/Controllers/TransactionCalculation.php index 533434a967..5d8ac77d9d 100644 --- a/app/Support/Http/Controllers/TransactionCalculation.php +++ b/app/Support/Http/Controllers/TransactionCalculation.php @@ -37,10 +37,10 @@ trait TransactionCalculation /** * Get all expenses for a set of accounts. * - * @param Collection $accounts - * @param Collection $opposing - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $opposing + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -61,10 +61,10 @@ trait TransactionCalculation /** * Get all expenses by tags. * - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return array * @@ -83,10 +83,10 @@ trait TransactionCalculation /** * Helper function that collects expenses for the given budgets. * - * @param Collection $accounts - * @param Collection $budgets - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $budgets + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -103,10 +103,10 @@ trait TransactionCalculation /** * Get all expenses in a period for categories. * - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -127,10 +127,10 @@ trait TransactionCalculation /** * Get all income for a period and a bunch of categories. * - * @param Collection $accounts - * @param Collection $categories - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $categories + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -147,10 +147,10 @@ trait TransactionCalculation /** * Get the income for a set of accounts. * - * @param Collection $accounts - * @param Collection $opposing - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $opposing + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -167,10 +167,10 @@ trait TransactionCalculation /** * Get all income by tag. * - * @param Collection $accounts - * @param Collection $tags - * @param Carbon $start - * @param Carbon $end + * @param Collection $accounts + * @param Collection $tags + * @param Carbon $start + * @param Carbon $end * * @return array */ @@ -183,5 +183,4 @@ trait TransactionCalculation return $collector->getExtractedJournals(); } - } diff --git a/app/Support/Http/Controllers/UserNavigation.php b/app/Support/Http/Controllers/UserNavigation.php index 7368e1d4a7..84cf46b458 100644 --- a/app/Support/Http/Controllers/UserNavigation.php +++ b/app/Support/Http/Controllers/UserNavigation.php @@ -39,7 +39,6 @@ use Log; */ trait UserNavigation { - /** * Functionality:. * @@ -47,14 +46,14 @@ trait UserNavigation * will be returned. * - If the remembered url contains "jscript/" the remembered url will not be returned but instead the index (/) will be returned. * - * @param string $identifier + * @param string $identifier * * @return string */ final protected function getPreviousUrl(string $identifier): string { Log::debug(sprintf('Trying to retrieve URL stored under "%s"', $identifier)); - $url = (string) session($identifier); + $url = (string)session($identifier); Log::debug(sprintf('The URL is %s', $url)); return app('steam')->getSafeUrl($url, route('index')); @@ -63,7 +62,7 @@ trait UserNavigation /** * Will return false if you cant edit this account type. * - * @param Account $account + * @param Account $account * * @return bool */ @@ -76,7 +75,7 @@ trait UserNavigation } /** - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return bool */ @@ -94,7 +93,7 @@ trait UserNavigation } /** - * @param Account $account + * @param Account $account * * @return RedirectResponse|Redirector */ @@ -129,7 +128,7 @@ trait UserNavigation } /** - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return RedirectResponse|Redirector */ @@ -157,7 +156,7 @@ trait UserNavigation } /** - * @param string $identifier + * @param string $identifier * * @return string|null */ diff --git a/app/Support/Logging/AuditLogger.php b/app/Support/Logging/AuditLogger.php index 01eecf70e4..d08542122d 100644 --- a/app/Support/Logging/AuditLogger.php +++ b/app/Support/Logging/AuditLogger.php @@ -38,19 +38,18 @@ class AuditLogger /** * Customize the given logger instance. * - * @param Logger $logger + * @param Logger $logger * * @return void */ public function __invoke(Logger $logger) { - $processor = new AuditProcessor; + $processor = new AuditProcessor(); /** @var AbstractProcessingHandler $handler */ foreach ($logger->getHandlers() as $handler) { $formatter = new LineFormatter("[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"); $handler->setFormatter($formatter); $handler->pushProcessor($processor); } - } } diff --git a/app/Support/Logging/AuditProcessor.php b/app/Support/Logging/AuditProcessor.php index b3651b6357..acc4cc1e33 100644 --- a/app/Support/Logging/AuditProcessor.php +++ b/app/Support/Logging/AuditProcessor.php @@ -32,20 +32,20 @@ namespace FireflyIII\Support\Logging; class AuditProcessor { /** - * @param array $record + * @param array $record * * @return array */ public function __invoke(array $record): array { if (auth()->check()) { - $record['message'] = sprintf( 'AUDIT: %s (%s (%s) -> %s:%s)', $record['message'], app('request')->ip(), auth()->user()->email, - request()->method(), request()->url() + request()->method(), + request()->url() ); return $record; @@ -55,7 +55,8 @@ class AuditProcessor 'AUDIT: %s (%s -> %s:%s)', $record['message'], app('request')->ip(), - request()->method(), request()->url() + request()->method(), + request()->url() ); return $record; diff --git a/app/Support/Navigation.php b/app/Support/Navigation.php index a9fda5a1cd..31266f2bca 100644 --- a/app/Support/Navigation.php +++ b/app/Support/Navigation.php @@ -1,4 +1,5 @@ preferredCarbonFormat($start, $end); - $displayFormat = (string) trans('config.month_and_day_js', [], $locale); + $displayFormat = (string)trans('config.month_and_day_js', [], $locale); // increment by month (for year) if ($start->diffInMonths($end) > 1) { $increment = 'addMonth'; - $displayFormat = (string) trans('config.month_js'); + $displayFormat = (string)trans('config.month_js'); } // increment by year (for multi year) if ($start->diffInMonths($end) > 12) { $increment = 'addYear'; - $displayFormat = (string) trans('config.year_js'); + $displayFormat = (string)trans('config.year_js'); } $begin = clone $start; $entries = []; @@ -369,8 +369,8 @@ class Navigation * If the date difference between start and end is less than a month, method returns "Y-m-d". If the difference is less than a year, * method returns "Y-m". If the date difference is larger, method returns "Y". * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -389,8 +389,8 @@ class Navigation } /** - * @param Carbon $theDate - * @param string $repeatFrequency + * @param Carbon $theDate + * @param string $repeatFrequency * * @return string */ @@ -398,23 +398,23 @@ class Navigation { $date = clone $theDate; $formatMap = [ - '1D' => (string) trans('config.specific_day_js'), - 'daily' => (string) trans('config.specific_day_js'), - 'custom' => (string) trans('config.specific_day_js'), - '1W' => (string) trans('config.week_in_year_js'), - 'week' => (string) trans('config.week_in_year_js'), - 'weekly' => (string) trans('config.week_in_year_js'), - '1M' => (string) trans('config.month_js'), - 'month' => (string) trans('config.month_js'), - 'monthly' => (string) trans('config.month_js'), - '1Y' => (string) trans('config.year_js'), - 'year' => (string) trans('config.year_js'), - 'yearly' => (string) trans('config.year_js'), - '6M' => (string) trans('config.half_year_js'), + '1D' => (string)trans('config.specific_day_js'), + 'daily' => (string)trans('config.specific_day_js'), + 'custom' => (string)trans('config.specific_day_js'), + '1W' => (string)trans('config.week_in_year_js'), + 'week' => (string)trans('config.week_in_year_js'), + 'weekly' => (string)trans('config.week_in_year_js'), + '1M' => (string)trans('config.month_js'), + 'month' => (string)trans('config.month_js'), + 'monthly' => (string)trans('config.month_js'), + '1Y' => (string)trans('config.year_js'), + 'year' => (string)trans('config.year_js'), + 'yearly' => (string)trans('config.year_js'), + '6M' => (string)trans('config.half_year_js'), ]; if (array_key_exists($repeatFrequency, $formatMap)) { - return $date->isoFormat((string) $formatMap[$repeatFrequency]); + return $date->isoFormat((string)$formatMap[$repeatFrequency]); } if ('3M' === $repeatFrequency || 'quarter' === $repeatFrequency) { $quarter = ceil($theDate->month / 3); @@ -426,15 +426,14 @@ class Navigation Log::error(sprintf('No date formats for frequency "%s"!', $repeatFrequency)); return $date->format('Y-m-d'); - } /** * If the date difference between start and end is less than a month, method returns trans(config.month_and_day). If the difference is less than a year, * method returns "config.month". If the date difference is larger, method returns "config.year". * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return string * @throws FireflyException @@ -442,13 +441,13 @@ class Navigation public function preferredCarbonLocalizedFormat(Carbon $start, Carbon $end): string { $locale = app('steam')->getLocale(); - $format = (string) trans('config.month_and_day_js', [], $locale); + $format = (string)trans('config.month_and_day_js', [], $locale); if ($start->diffInMonths($end) > 1) { - $format = (string) trans('config.month_js', [], $locale); + $format = (string)trans('config.month_js', [], $locale); } if ($start->diffInMonths($end) > 12) { - $format = (string) trans('config.year_js', [], $locale); + $format = (string)trans('config.year_js', [], $locale); } return $format; @@ -458,8 +457,8 @@ class Navigation * If the date difference between start and end is less than a month, method returns "endOfDay". If the difference is less than a year, * method returns "endOfMonth". If the date difference is larger, method returns "endOfYear". * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -481,8 +480,8 @@ class Navigation * If the date difference between start and end is less than a month, method returns "1D". If the difference is less than a year, * method returns "1M". If the date difference is larger, method returns "1Y". * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -504,8 +503,8 @@ class Navigation * If the date difference between start and end is less than a month, method returns "%Y-%m-%d". If the difference is less than a year, * method returns "%Y-%m". If the date difference is larger, method returns "%Y". * - * @param Carbon $start - * @param Carbon $end + * @param Carbon $start + * @param Carbon $end * * @return string */ @@ -524,9 +523,9 @@ class Navigation } /** - * @param Carbon $theDate - * @param string $repeatFreq - * @param int|null $subtract + * @param Carbon $theDate + * @param string $repeatFreq + * @param int|null $subtract * * @return Carbon * @@ -585,10 +584,10 @@ class Navigation switch ($repeatFreq) { default: break; - case 'last7'; + case 'last7': $date->subDays(7); return $date; - case 'last30'; + case 'last30': $date->subDays(30); return $date; case 'last90': @@ -613,8 +612,8 @@ class Navigation } /** - * @param string $range - * @param Carbon $start + * @param string $range + * @param Carbon $start * * @return Carbon * @@ -655,25 +654,25 @@ class Navigation return $fiscalHelper->endOfFiscalYear($end); } - switch ($range) { - default: - break; - case 'last7'; - case 'last30'; - case 'last90': - case 'last365': - case 'YTD': - case 'QTD': - case 'MTD': - return $end; + $list = [ + 'last7', + 'last30', + 'last90', + 'last365', + 'YTD', + 'QTD', + 'MTD', + ]; + if (in_array($range, $list, true)) { + return $end; } throw new FireflyException(sprintf('updateEndDate cannot handle range "%s"', $range)); } /** - * @param string $range - * @param Carbon $start + * @param string $range + * @param Carbon $start * * @return Carbon * @@ -715,10 +714,10 @@ class Navigation switch ($range) { default: break; - case 'last7'; + case 'last7': $start->subDays(7); return $start; - case 'last30'; + case 'last30': $start->subDays(30); return $start; case 'last90': diff --git a/app/Support/NullArrayObject.php b/app/Support/NullArrayObject.php index 60d20319db..144bc1bb7d 100644 --- a/app/Support/NullArrayObject.php +++ b/app/Support/NullArrayObject.php @@ -37,9 +37,10 @@ class NullArrayObject extends ArrayObject /** * NullArrayObject constructor. * - * @param array $array - * @param null $default + * @param array $array + * @param null $default */ + /* @phpstan-ignore-next-line */ public function __construct(array $array, $default = null) { parent::__construct($array); @@ -47,11 +48,11 @@ class NullArrayObject extends ArrayObject } /** - * @param mixed $key + * @param mixed $key * - * @return mixed|null + * @return mixed */ - public function offsetGet($key) + public function offsetGet($key): mixed { if ($this->offsetExists($key)) { return parent::offsetGet($key); diff --git a/app/Support/ParseDateString.php b/app/Support/ParseDateString.php index b04870b01b..2b6255c7fc 100644 --- a/app/Support/ParseDateString.php +++ b/app/Support/ParseDateString.php @@ -33,7 +33,7 @@ use Log; */ class ParseDateString { - private $keywords + private array $keywords = [ 'today', 'yesterday', @@ -49,7 +49,7 @@ class ParseDateString ]; /** - * @param string $date + * @param string $date * * @return bool */ @@ -73,13 +73,14 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return Carbon * @throws FireflyException */ public function parseDate(string $date): Carbon { + Log::debug(sprintf('parseDate("%s")', $date)); $date = strtolower($date); // parse keywords: if (in_array($date, $this->keywords, true)) { @@ -94,7 +95,6 @@ class ParseDateString // if + or -: if (str_starts_with($date, '+') || str_starts_with($date, '-')) { - return $this->parseRelativeDate($date); } if ('xxxx-xx-xx' === strtolower($date)) { @@ -114,15 +114,15 @@ class ParseDateString return new Carbon('1984-09-17'); } // maybe a year, nothing else? - if (4 === strlen($date) && is_numeric($date) && (int) $date > 1000 && (int) $date <= 3000) { + if (4 === strlen($date) && is_numeric($date) && (int)$date > 1000 && (int)$date <= 3000) { return new Carbon(sprintf('%d-01-01', $date)); } - throw new FireflyException(sprintf('[d]Not a recognised date format: "%s"', $date)); + throw new FireflyException(sprintf('[d] Not a recognised date format: "%s"', $date)); } /** - * @param string $keyword + * @param string $keyword * * @return Carbon */ @@ -146,7 +146,7 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return Carbon */ @@ -156,7 +156,7 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return Carbon */ @@ -172,7 +172,8 @@ class ParseDateString 'm' => 'subMonths', 'q' => 'subQuarters', 'y' => 'subYears', - ], [ + ], + [ 'd' => 'addDays', 'w' => 'addWeeks', 'm' => 'addMonths', @@ -194,7 +195,7 @@ class ParseDateString } $direction = str_starts_with($part, '+') ? 1 : 0; $period = $part[strlen($part) - 1]; - $number = (int) substr($part, 1, -1); + $number = (int)substr($part, 1, -1); if (!array_key_exists($period, $functions[$direction])) { Log::error(sprintf('No method for direction %d and period "%s".', $direction, $period)); continue; @@ -203,14 +204,13 @@ class ParseDateString Log::debug(sprintf('Will now do %s(%d) on %s', $func, $number, $today->format('Y-m-d'))); $today->$func($number); Log::debug(sprintf('Resulting date is %s', $today->format('Y-m-d'))); - } return $today; } /** - * @param string $date + * @param string $date * * @return array */ @@ -247,7 +247,7 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return bool */ @@ -268,7 +268,7 @@ class ParseDateString /** * format of string is xxxx-xx-DD * - * @param string $date + * @param string $date * * @return array */ @@ -282,7 +282,7 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return bool */ @@ -303,7 +303,7 @@ class ParseDateString /** * format of string is xxxx-MM-xx * - * @param string $date + * @param string $date * * @return array */ @@ -318,7 +318,7 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return bool */ @@ -339,7 +339,7 @@ class ParseDateString /** * format of string is YYYY-xx-xx * - * @param string $date + * @param string $date * * @return array */ @@ -354,7 +354,7 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return bool */ @@ -375,7 +375,7 @@ class ParseDateString /** * format of string is xxxx-MM-DD * - * @param string $date + * @param string $date * * @return array */ @@ -391,7 +391,7 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return bool */ @@ -412,7 +412,7 @@ class ParseDateString /** * format of string is YYYY-xx-DD * - * @param string $date + * @param string $date * * @return array */ @@ -428,7 +428,7 @@ class ParseDateString } /** - * @param string $date + * @param string $date * * @return bool */ @@ -449,7 +449,7 @@ class ParseDateString /** * format of string is YYYY-MM-xx * - * @param string $date + * @param string $date * * @return array */ @@ -463,5 +463,4 @@ class ParseDateString 'month' => $parts[1], ]; } - } diff --git a/app/Support/Preferences.php b/app/Support/Preferences.php index 8f9a91862f..10390fe799 100644 --- a/app/Support/Preferences.php +++ b/app/Support/Preferences.php @@ -1,4 +1,5 @@ user(); if (null === $user) { - return new Collection; + return new Collection(); } return Preference::where('user_id', $user->id)->get(); } /** - * @param User $user - * @param string $search + * @param string $name + * @param mixed $default * - * @return Collection + * @return Preference|null + * @throws FireflyException */ - public function beginsWith(User $user, string $search): Collection + public function get(string $name, $default = null): ?Preference { - return Preference::where('user_id', $user->id)->where('name', 'LIKE', $search . '%')->get(); + /** @var User|null $user */ + $user = auth()->user(); + if (null === $user) { + $preference = new Preference(); + $preference->data = $default; + + return $preference; + } + + return $this->getForUser($user, $name, $default); } /** - * @param string $name + * @param User $user + * @param string $name + * @param null|string|int $default + * + * @return Preference|null + * @throws FireflyException + */ + public function getForUser(User $user, string $name, $default = null): ?Preference + { + $preference = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']); + if (null !== $preference && null === $preference->data) { + $preference->delete(); + $preference = null; + } + + if (null !== $preference) { + return $preference; + } + // no preference found and default is null: + if (null === $default) { + // return NULL + return null; + } + + return $this->setForUser($user, $name, $default); + } + + /** + * @param string $name * * @return bool * @throws FireflyException @@ -74,28 +113,14 @@ class Preferences if (Cache::has($fullName)) { Cache::forget($fullName); } - try { - Preference::where('user_id', auth()->user()->id)->where('name', $name)->delete(); - } catch (Exception $e) { - throw new FireflyException(sprintf('Could not delete preference: %s', $e->getMessage()), 0, $e); - } + Preference::where('user_id', auth()->user()->id)->where('name', $name)->delete(); return true; } /** - * @param string $name - * - * @return Collection - */ - public function findByName(string $name): Collection - { - return Preference::where('name', $name)->get(); - } - - /** - * @param User $user - * @param string $name + * @param User $user + * @param string $name */ public function forget(User $user, string $name): void { @@ -105,8 +130,68 @@ class Preferences } /** - * @param User $user - * @param array $list + * @param User $user + * @param string $name + * @param mixed $value + * + * @return Preference + * @throws FireflyException + */ + public function setForUser(User $user, string $name, $value): Preference + { + $fullName = sprintf('preference%s%s', $user->id, $name); + Cache::forget($fullName); + /** @var Preference|null $pref */ + $pref = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']); + + if (null !== $pref && null === $value) { + $pref->delete(); + + return new Preference(); + } + if (null === $value) { + return new Preference(); + } + if (null === $pref) { + $pref = new Preference(); + $pref->user_id = $user->id; + $pref->name = $name; + } + $pref->data = $value; + try { + $pref->save(); + } catch (PDOException $e) { + throw new FireflyException(sprintf('Could not save preference: %s', $e->getMessage()), 0, $e); + } + Cache::forever($fullName, $pref); + + return $pref; + } + + /** + * @param User $user + * @param string $search + * + * @return Collection + */ + public function beginsWith(User $user, string $search): Collection + { + return Preference::where('user_id', $user->id)->where('name', 'LIKE', $search.'%')->get(); + } + + /** + * @param string $name + * + * @return Collection + */ + public function findByName(string $name): Collection + { + return Preference::where('name', $name)->get(); + } + + /** + * @param User $user + * @param array $list * * @return array */ @@ -128,8 +213,8 @@ class Preferences } /** - * @param string $name - * @param mixed $default + * @param string $name + * @param mixed $default * * @return Preference|null * @throws FireflyException @@ -139,7 +224,7 @@ class Preferences /** @var User|null $user */ $user = auth()->user(); if (null === $user) { - $preference = new Preference; + $preference = new Preference(); $preference->data = $default; return $preference; @@ -149,12 +234,12 @@ class Preferences } /** - * @param User $user - * @param string $name - * @param null $default + * @param User $user + * @param string $name + * @param null $default * * @return Preference|null - * See reference nr. 44 + * TODO remove me. * @throws FireflyException */ public function getFreshForUser(User $user, string $name, $default = null): ?Preference @@ -162,82 +247,6 @@ class Preferences return $this->getForUser($user, $name, $default); } - /** - * @param User $user - * @param string $name - * @param null|string|int $default - * - * @return Preference|null - * @throws FireflyException - */ - public function getForUser(User $user, string $name, $default = null): ?Preference - { - $preference = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']); - if (null !== $preference && null === $preference->data) { - try { - $preference->delete(); - } catch (Exception $e) { - throw new FireflyException(sprintf('Could not delete preference #%d: %s', $preference->id, $e->getMessage()), 0, $e); - } - $preference = null; - } - - if (null !== $preference) { - - return $preference; - } - // no preference found and default is null: - if (null === $default) { - // return NULL - return null; - } - - return $this->setForUser($user, $name, $default); - } - - /** - * @param User $user - * @param string $name - * @param mixed $value - * - * @return Preference - * @throws FireflyException - */ - public function setForUser(User $user, string $name, $value): Preference - { - $fullName = sprintf('preference%s%s', $user->id, $name); - Cache::forget($fullName); - /** @var Preference|null $pref */ - $pref = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']); - - if (null !== $pref && null === $value) { - try { - $pref->delete(); - } catch (Exception $e) { - throw new FireflyException(sprintf('Could not delete preference: %s', $e->getMessage()), 0, $e); - } - - return new Preference; - } - if (null === $value) { - return new Preference; - } - if (null === $pref) { - $pref = new Preference; - $pref->user_id = $user->id; - $pref->name = $name; - } - $pref->data = $value; - try { - $pref->save(); - } catch (PDOException $e) { - throw new FireflyException(sprintf('Could not save preference: %s', $e->getMessage()), 0, $e); - } - Cache::forever($fullName, $pref); - - return $pref; - } - /** * @return string * @throws FireflyException @@ -257,27 +266,6 @@ class Preferences return hash('sha256', $lastActivity); } - /** - * @param string $name - * @param mixed $default - * - * @return Preference|null - * @throws FireflyException - */ - public function get(string $name, $default = null): ?Preference - { - /** @var User|null $user */ - $user = auth()->user(); - if (null === $user) { - $preference = new Preference; - $preference->data = $default; - - return $preference; - } - - return $this->getForUser($user, $name, $default); - } - /** * */ @@ -288,8 +276,8 @@ class Preferences } /** - * @param string $name - * @param mixed $value + * @param string $name + * @param mixed $value * * @return Preference * @throws FireflyException @@ -299,7 +287,7 @@ class Preferences $user = auth()->user(); if (null === $user) { // make new preference, return it: - $pref = new Preference; + $pref = new Preference(); $pref->name = $name; $pref->data = $value; diff --git a/app/Support/Report/Budget/BudgetReportGenerator.php b/app/Support/Report/Budget/BudgetReportGenerator.php index 31f376b78e..8c79b5faa8 100644 --- a/app/Support/Report/Budget/BudgetReportGenerator.php +++ b/app/Support/Report/Budget/BudgetReportGenerator.php @@ -1,4 +1,5 @@ opsRepository->listExpenses($this->start, $this->end, $this->accounts, $this->budgets); $this->report = []; /** @var Account $account */ foreach ($this->accounts as $account) { $accountId = $account->id; $this->report[$accountId] = $this->report[$accountId] ?? [ - 'name' => $account->name, - 'id' => $account->id, - 'iban' => $account->iban, - 'currencies' => [], - ]; + 'name' => $account->name, + 'id' => $account->id, + 'iban' => $account->iban, + 'currencies' => [], + ]; } // loop expenses. foreach ($spent as $currency) { $this->processExpenses($currency); } - } /** * Process each row of expenses collected for the "Account per budget" partial * - * @param array $expenses + * @param array $expenses */ private function processExpenses(array $expenses): void { @@ -105,24 +106,24 @@ class BudgetReportGenerator /** * Process each set of transactions for each row of expenses. * - * @param array $expenses - * @param array $budget + * @param array $expenses + * @param array $budget */ private function processBudgetExpenses(array $expenses, array $budget): void { - $budgetId = (int) $budget['id']; - $currencyId = (int) $expenses['currency_id']; + $budgetId = (int)$budget['id']; + $currencyId = (int)$expenses['currency_id']; foreach ($budget['transaction_journals'] as $journal) { $sourceAccountId = $journal['source_account_id']; $this->report[$sourceAccountId]['currencies'][$currencyId] = $this->report[$sourceAccountId]['currencies'][$currencyId] ?? [ - 'currency_id' => $expenses['currency_id'], - 'currency_symbol' => $expenses['currency_symbol'], - 'currency_name' => $expenses['currency_name'], - 'currency_decimal_places' => $expenses['currency_decimal_places'], - 'budgets' => [], - ]; + 'currency_id' => $expenses['currency_id'], + 'currency_symbol' => $expenses['currency_symbol'], + 'currency_name' => $expenses['currency_name'], + 'currency_decimal_places' => $expenses['currency_decimal_places'], + 'budgets' => [], + ]; $this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId] = $this->report[$sourceAccountId]['currencies'][$currencyId]['budgets'][$budgetId] ?? '0'; @@ -163,17 +164,17 @@ class BudgetReportGenerator /** * Process expenses etc. for a single budget for the budgets block on the default report. * - * @param Budget $budget + * @param Budget $budget */ private function processBudget(Budget $budget): void { - $budgetId = (int) $budget->id; + $budgetId = (int)$budget->id; $this->report['budgets'][$budgetId] = $this->report['budgets'][$budgetId] ?? [ - 'budget_id' => $budgetId, - 'budget_name' => $budget->name, - 'no_budget' => false, - 'budget_limits' => [], - ]; + 'budget_id' => $budgetId, + 'budget_name' => $budget->name, + 'no_budget' => false, + 'budget_limits' => [], + ]; // get all budget limits for budget in period: $limits = $this->blRepository->getBudgetLimits($budget, $this->start, $this->end); @@ -186,50 +187,50 @@ class BudgetReportGenerator /** * Process a single budget limit for the budgets block on the default report. * - * @param Budget $budget - * @param BudgetLimit $limit + * @param Budget $budget + * @param BudgetLimit $limit */ private function processLimit(Budget $budget, BudgetLimit $limit): void { - $budgetId = (int) $budget->id; - $limitId = (int) $limit->id; + $budgetId = (int)$budget->id; + $limitId = (int)$limit->id; $limitCurrency = $limit->transactionCurrency ?? $this->currency; - $currencyId = (int) $limitCurrency->id; + $currencyId = (int)$limitCurrency->id; $expenses = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, $this->accounts, new Collection([$budget])); $spent = $expenses[$currencyId]['sum'] ?? '0'; $left = -1 === bccomp(bcadd($limit->amount, $spent), '0') ? '0' : bcadd($limit->amount, $spent); $overspent = 1 === bccomp(bcmul($spent, '-1'), $limit->amount) ? bcadd($spent, $limit->amount) : '0'; $this->report['budgets'][$budgetId]['budget_limits'][$limitId] = $this->report['budgets'][$budgetId]['budget_limits'][$limitId] ?? [ - 'budget_limit_id' => $limitId, - 'start_date' => $limit->start_date, - 'end_date' => $limit->end_date, - 'budgeted' => $limit->amount, - 'budgeted_pct' => '0', - 'spent' => $spent, - 'spent_pct' => '0', - 'left' => $left, - 'overspent' => $overspent, - 'currency_id' => $currencyId, - 'currency_code' => $limitCurrency->code, - 'currency_name' => $limitCurrency->name, - 'currency_symbol' => $limitCurrency->symbol, - 'currency_decimal_places' => $limitCurrency->decimal_places, - ]; + 'budget_limit_id' => $limitId, + 'start_date' => $limit->start_date, + 'end_date' => $limit->end_date, + 'budgeted' => $limit->amount, + 'budgeted_pct' => '0', + 'spent' => $spent, + 'spent_pct' => '0', + 'left' => $left, + 'overspent' => $overspent, + 'currency_id' => $currencyId, + 'currency_code' => $limitCurrency->code, + 'currency_name' => $limitCurrency->name, + 'currency_symbol' => $limitCurrency->symbol, + 'currency_decimal_places' => $limitCurrency->decimal_places, + ]; // make sum information: $this->report['sums'][$currencyId] = $this->report['sums'][$currencyId] ?? [ - 'budgeted' => '0', - 'spent' => '0', - 'left' => '0', - 'overspent' => '0', - 'currency_id' => $currencyId, - 'currency_code' => $limitCurrency->code, - 'currency_name' => $limitCurrency->name, - 'currency_symbol' => $limitCurrency->symbol, - 'currency_decimal_places' => $limitCurrency->decimal_places, - ]; + 'budgeted' => '0', + 'spent' => '0', + 'left' => '0', + 'overspent' => '0', + 'currency_id' => $currencyId, + 'currency_code' => $limitCurrency->code, + 'currency_name' => $limitCurrency->name, + 'currency_symbol' => $limitCurrency->symbol, + 'currency_decimal_places' => $limitCurrency->decimal_places, + ]; $this->report['sums'][$currencyId]['budgeted'] = bcadd($this->report['sums'][$currencyId]['budgeted'], $limit->amount); $this->report['sums'][$currencyId]['spent'] = bcadd($this->report['sums'][$currencyId]['spent'], $spent); $this->report['sums'][$currencyId]['left'] = bcadd($this->report['sums'][$currencyId]['left'], bcadd($limit->amount, $spent)); @@ -251,9 +252,8 @@ class BudgetReportGenerator $noBudget = $this->nbRepository->sumExpenses($this->start, $this->end, $this->accounts); foreach ($noBudget as $noBudgetEntry) { - // currency information: - $nbCurrencyId = (int) ($noBudgetEntry['currency_id'] ?? $this->currency->id); + $nbCurrencyId = (int)($noBudgetEntry['currency_id'] ?? $this->currency->id); $nbCurrencyCode = $noBudgetEntry['currency_code'] ?? $this->currency->code; $nbCurrencyName = $noBudgetEntry['currency_name'] ?? $this->currency->name; $nbCurrencySymbol = $noBudgetEntry['currency_symbol'] ?? $this->currency->symbol; @@ -298,9 +298,9 @@ class BudgetReportGenerator // make percentages based on total amount. foreach ($this->report['budgets'] as $budgetId => $data) { foreach ($data['budget_limits'] as $limitId => $entry) { - $budgetId = (int) $budgetId; - $limitId = (int) $limitId; - $currencyId = (int) $entry['currency_id']; + $budgetId = (int)$budgetId; + $limitId = (int)$limitId; + $currencyId = (int)$entry['currency_id']; $spent = $entry['spent']; $totalSpent = $this->report['sums'][$currencyId]['spent'] ?? '0'; $spentPct = '0'; @@ -309,10 +309,10 @@ class BudgetReportGenerator $budgetedPct = '0'; if (0 !== bccomp($spent, '0') && 0 !== bccomp($totalSpent, '0')) { - $spentPct = round((float) bcmul(bcdiv($spent, $totalSpent), '100')); + $spentPct = round((float)bcmul(bcdiv($spent, $totalSpent), '100')); } if (0 !== bccomp($budgeted, '0') && 0 !== bccomp($totalBudgeted, '0')) { - $budgetedPct = round((float) bcmul(bcdiv($budgeted, $totalBudgeted), '100')); + $budgetedPct = round((float)bcmul(bcdiv($budgeted, $totalBudgeted), '100')); } $this->report['sums'][$currencyId]['budgeted'] = $this->report['sums'][$currencyId]['budgeted'] ?? '0'; $this->report['budgets'][$budgetId]['budget_limits'][$limitId]['spent_pct'] = $spentPct; @@ -330,7 +330,7 @@ class BudgetReportGenerator } /** - * @param Collection $accounts + * @param Collection $accounts */ public function setAccounts(Collection $accounts): void { @@ -338,7 +338,7 @@ class BudgetReportGenerator } /** - * @param Collection $budgets + * @param Collection $budgets */ public function setBudgets(Collection $budgets): void { @@ -346,7 +346,7 @@ class BudgetReportGenerator } /** - * @param Carbon $end + * @param Carbon $end */ public function setEnd(Carbon $end): void { @@ -354,7 +354,7 @@ class BudgetReportGenerator } /** - * @param Carbon $start + * @param Carbon $start */ public function setStart(Carbon $start): void { @@ -362,9 +362,9 @@ class BudgetReportGenerator } /** - * @param User $user - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException + * @param User $user + * @throws FireflyException + * @throws JsonException */ public function setUser(User $user): void { diff --git a/app/Support/Report/Category/CategoryReportGenerator.php b/app/Support/Report/Category/CategoryReportGenerator.php index efd064d6b3..93097dd029 100644 --- a/app/Support/Report/Category/CategoryReportGenerator.php +++ b/app/Support/Report/Category/CategoryReportGenerator.php @@ -88,12 +88,12 @@ class CategoryReportGenerator /** * Process one of the spent arrays from the operations method. * - * @param array $data + * @param array $data */ private function processOpsArray(array $data): void { /** - * @var int $currencyId + * @var int $currencyId * @var array $currencyRow */ foreach ($data as $currencyId => $currencyRow) { @@ -102,24 +102,24 @@ class CategoryReportGenerator } /** - * @param int $currencyId - * @param array $currencyRow + * @param int $currencyId + * @param array $currencyRow */ private function processCurrencyArray(int $currencyId, array $currencyRow): void { $this->report['sums'][$currencyId] = $this->report['sums'][$currencyId] ?? [ - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - 'currency_id' => $currencyRow['currency_id'], - 'currency_symbol' => $currencyRow['currency_symbol'], - 'currency_name' => $currencyRow['currency_name'], - 'currency_code' => $currencyRow['currency_code'], - 'currency_decimal_places' => $currencyRow['currency_decimal_places'], - ]; + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + 'currency_id' => $currencyRow['currency_id'], + 'currency_symbol' => $currencyRow['currency_symbol'], + 'currency_name' => $currencyRow['currency_name'], + 'currency_code' => $currencyRow['currency_code'], + 'currency_decimal_places' => $currencyRow['currency_decimal_places'], + ]; /** - * @var int $categoryId + * @var int $categoryId * @var array $categoryRow */ foreach ($currencyRow['categories'] as $categoryId => $categoryRow) { @@ -128,26 +128,26 @@ class CategoryReportGenerator } /** - * @param int $currencyId - * @param array $currencyRow - * @param int $categoryId - * @param array $categoryRow + * @param int $currencyId + * @param array $currencyRow + * @param int $categoryId + * @param array $categoryRow */ private function processCategoryRow(int $currencyId, array $currencyRow, int $categoryId, array $categoryRow): void { $key = sprintf('%s-%s', $currencyId, $categoryId); $this->report['categories'][$key] = $this->report['categories'][$key] ?? [ - 'id' => $categoryId, - 'title' => $categoryRow['name'], - 'currency_id' => $currencyRow['currency_id'], - 'currency_symbol' => $currencyRow['currency_symbol'], - 'currency_name' => $currencyRow['currency_name'], - 'currency_code' => $currencyRow['currency_code'], - 'currency_decimal_places' => $currencyRow['currency_decimal_places'], - 'spent' => '0', - 'earned' => '0', - 'sum' => '0', - ]; + 'id' => $categoryId, + 'title' => $categoryRow['name'], + 'currency_id' => $currencyRow['currency_id'], + 'currency_symbol' => $currencyRow['currency_symbol'], + 'currency_name' => $currencyRow['currency_name'], + 'currency_code' => $currencyRow['currency_code'], + 'currency_decimal_places' => $currencyRow['currency_decimal_places'], + 'spent' => '0', + 'earned' => '0', + 'sum' => '0', + ]; // loop journals: foreach ($categoryRow['transaction_journals'] as $journal) { // sum of sums @@ -179,7 +179,7 @@ class CategoryReportGenerator } /** - * @param Collection $accounts + * @param Collection $accounts */ public function setAccounts(Collection $accounts): void { @@ -187,7 +187,7 @@ class CategoryReportGenerator } /** - * @param Carbon $end + * @param Carbon $end */ public function setEnd(Carbon $end): void { @@ -195,7 +195,7 @@ class CategoryReportGenerator } /** - * @param Carbon $start + * @param Carbon $start */ public function setStart(Carbon $start): void { @@ -203,12 +203,11 @@ class CategoryReportGenerator } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->noCatRepository->setUser($user); $this->opsRepository->setUser($user); } - } diff --git a/app/Support/Repositories/Recurring/CalculateRangeOccurrences.php b/app/Support/Repositories/Recurring/CalculateRangeOccurrences.php index d5160b32ef..cccdb12026 100644 --- a/app/Support/Repositories/Recurring/CalculateRangeOccurrences.php +++ b/app/Support/Repositories/Recurring/CalculateRangeOccurrences.php @@ -32,13 +32,12 @@ use Illuminate\Support\Facades\Log; */ trait CalculateRangeOccurrences { - /** * Get the number of daily occurrences for a recurring transaction until date $end is reached. Will skip every $skipMod-1 occurrences. * - * @param Carbon $start - * @param Carbon $end - * @param int $skipMod + * @param Carbon $start + * @param Carbon $end + * @param int $skipMod * * @return array */ @@ -60,10 +59,10 @@ trait CalculateRangeOccurrences /** * Get the number of daily occurrences for a recurring transaction until date $end is reached. Will skip every $skipMod-1 occurrences. * - * @param Carbon $start - * @param Carbon $end - * @param int $skipMod - * @param string $moment + * @param Carbon $start + * @param Carbon $end + * @param int $skipMod + * @param string $moment * * @return array * @@ -72,7 +71,7 @@ trait CalculateRangeOccurrences { $return = []; $attempts = 0; - $dayOfMonth = (int) $moment; + $dayOfMonth = (int)$moment; if ($start->day > $dayOfMonth) { // day has passed already, add a month. $start->addMonth(); @@ -93,10 +92,10 @@ trait CalculateRangeOccurrences /** * Get the number of daily occurrences for a recurring transaction until date $end is reached. Will skip every $skipMod-1 occurrences. * - * @param Carbon $start - * @param Carbon $end - * @param int $skipMod - * @param string $moment + * @param Carbon $start + * @param Carbon $end + * @param int $skipMod + * @param string $moment * * @return array */ @@ -125,10 +124,10 @@ trait CalculateRangeOccurrences /** * Get the number of daily occurrences for a recurring transaction until date $end is reached. Will skip every $skipMod-1 occurrences. * - * @param Carbon $start - * @param Carbon $end - * @param int $skipMod - * @param string $moment + * @param Carbon $start + * @param Carbon $end + * @param int $skipMod + * @param string $moment * * @return array * @@ -140,7 +139,7 @@ trait CalculateRangeOccurrences Log::debug('Rep is weekly.'); // monday = 1 // sunday = 7 - $dayOfWeek = (int) $moment; + $dayOfWeek = (int)$moment; Log::debug(sprintf('DoW in repetition is %d, in mutator is %d', $dayOfWeek, $start->dayOfWeekIso)); if ($start->dayOfWeekIso > $dayOfWeek) { // day has already passed this week, add one week: @@ -169,10 +168,10 @@ trait CalculateRangeOccurrences /** * Get the number of daily occurrences for a recurring transaction until date $end is reached. Will skip every $skipMod-1 occurrences. * - * @param Carbon $start - * @param Carbon $end - * @param int $skipMod - * @param string $moment + * @param Carbon $start + * @param Carbon $end + * @param int $skipMod + * @param string $moment * * @return array * @@ -185,7 +184,6 @@ trait CalculateRangeOccurrences $return = []; if ($start > $date) { $date->addYear(); - } // is $date between $start and $end? @@ -201,6 +199,5 @@ trait CalculateRangeOccurrences } return $return; - } } diff --git a/app/Support/Repositories/Recurring/CalculateXOccurrences.php b/app/Support/Repositories/Recurring/CalculateXOccurrences.php index 166fa78fcc..59e7ea2861 100644 --- a/app/Support/Repositories/Recurring/CalculateXOccurrences.php +++ b/app/Support/Repositories/Recurring/CalculateXOccurrences.php @@ -31,14 +31,13 @@ use Carbon\Carbon; */ trait CalculateXOccurrences { - /** * Calculates the number of daily occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param int $count - * @param int $skipMod + * @param Carbon $date + * @param int $count + * @param int $skipMod * * @return array */ @@ -64,10 +63,10 @@ trait CalculateXOccurrences * Calculates the number of monthly occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param int $count - * @param int $skipMod - * @param string $moment + * @param Carbon $date + * @param int $count + * @param int $skipMod + * @param string $moment * * @return array */ @@ -77,7 +76,7 @@ trait CalculateXOccurrences $mutator = clone $date; $total = 0; $attempts = 0; - $dayOfMonth = (int) $moment; + $dayOfMonth = (int)$moment; if ($mutator->day > $dayOfMonth) { // day has passed already, add a month. $mutator->addMonth(); @@ -101,10 +100,10 @@ trait CalculateXOccurrences * Calculates the number of NDOM occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param int $count - * @param int $skipMod - * @param string $moment + * @param Carbon $date + * @param int $count + * @param int $skipMod + * @param string $moment * * @return array */ @@ -139,10 +138,10 @@ trait CalculateXOccurrences * Calculates the number of weekly occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param int $count - * @param int $skipMod - * @param string $moment + * @param Carbon $date + * @param int $count + * @param int $skipMod + * @param string $moment * * @return array */ @@ -155,7 +154,7 @@ trait CalculateXOccurrences // monday = 1 // sunday = 7 $mutator->addDay(); // always assume today has passed. - $dayOfWeek = (int) $moment; + $dayOfWeek = (int)$moment; if ($mutator->dayOfWeekIso > $dayOfWeek) { // day has already passed this week, add one week: $mutator->addWeek(); @@ -181,10 +180,10 @@ trait CalculateXOccurrences * Calculates the number of yearly occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param int $count - * @param int $skipMod - * @param string $moment + * @param Carbon $date + * @param int $count + * @param int $skipMod + * @param string $moment * * @return array */ @@ -210,6 +209,5 @@ trait CalculateXOccurrences } return $return; - } } diff --git a/app/Support/Repositories/Recurring/CalculateXOccurrencesSince.php b/app/Support/Repositories/Recurring/CalculateXOccurrencesSince.php index b46a5dfebc..c9b505c25a 100644 --- a/app/Support/Repositories/Recurring/CalculateXOccurrencesSince.php +++ b/app/Support/Repositories/Recurring/CalculateXOccurrencesSince.php @@ -32,15 +32,14 @@ use Log; */ trait CalculateXOccurrencesSince { - /** * Calculates the number of daily occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param Carbon $afterDate - * @param int $count - * @param int $skipMod + * @param Carbon $date + * @param Carbon $afterDate + * @param int $count + * @param int $skipMod * * @return array */ @@ -67,11 +66,11 @@ trait CalculateXOccurrencesSince * Calculates the number of monthly occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param Carbon $afterDate - * @param int $count - * @param int $skipMod - * @param string $moment + * @param Carbon $date + * @param Carbon $afterDate + * @param int $count + * @param int $skipMod + * @param string $moment * * @return array */ @@ -82,7 +81,7 @@ trait CalculateXOccurrencesSince $mutator = clone $date; $total = 0; $attempts = 0; - $dayOfMonth = (int) $moment; + $dayOfMonth = (int)$moment; $dayOfMonth = 0 === $dayOfMonth ? 1 : $dayOfMonth; if ($mutator->day > $dayOfMonth) { Log::debug(sprintf('%d is after %d, add a month. Mutator is now', $mutator->day, $dayOfMonth)); @@ -110,11 +109,11 @@ trait CalculateXOccurrencesSince * Calculates the number of NDOM occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param Carbon $afterDate - * @param int $count - * @param int $skipMod - * @param string $moment + * @param Carbon $date + * @param Carbon $afterDate + * @param int $count + * @param int $skipMod + * @param string $moment * * @return array */ @@ -150,11 +149,11 @@ trait CalculateXOccurrencesSince * Calculates the number of weekly occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param Carbon $afterDate - * @param int $count - * @param int $skipMod - * @param string $moment + * @param Carbon $date + * @param Carbon $afterDate + * @param int $count + * @param int $skipMod + * @param string $moment * * @return array */ @@ -169,7 +168,7 @@ trait CalculateXOccurrencesSince // sunday = 7 // Removed assumption today has passed, see issue https://github.com/firefly-iii/firefly-iii/issues/4798 //$mutator->addDay(); // always assume today has passed. - $dayOfWeek = (int) $moment; + $dayOfWeek = (int)$moment; if ($mutator->dayOfWeekIso > $dayOfWeek) { // day has already passed this week, add one week: $mutator->addWeek(); @@ -195,11 +194,11 @@ trait CalculateXOccurrencesSince * Calculates the number of yearly occurrences for a recurring transaction, starting at the date, until $count is reached. It will skip * over $skipMod -1 recurrences. * - * @param Carbon $date - * @param Carbon $afterDate - * @param int $count - * @param int $skipMod - * @param string $moment + * @param Carbon $date + * @param Carbon $afterDate + * @param int $count + * @param int $skipMod + * @param string $moment * * @return array */ @@ -234,6 +233,5 @@ trait CalculateXOccurrencesSince } return $return; - } } diff --git a/app/Support/Repositories/Recurring/FiltersWeekends.php b/app/Support/Repositories/Recurring/FiltersWeekends.php index 04afa7dd81..a86be7a4fc 100644 --- a/app/Support/Repositories/Recurring/FiltersWeekends.php +++ b/app/Support/Repositories/Recurring/FiltersWeekends.php @@ -34,12 +34,11 @@ use Illuminate\Support\Facades\Log; */ trait FiltersWeekends { - /** * Filters out all weekend entries, if necessary. * - * @param RecurrenceRepetition $repetition - * @param array $dates + * @param RecurrenceRepetition $repetition + * @param array $dates * * @return array * @@ -47,7 +46,7 @@ trait FiltersWeekends protected function filterWeekends(RecurrenceRepetition $repetition, array $dates): array { Log::debug(sprintf('Now in %s', __METHOD__)); - if ((int) $repetition->weekend === RecurrenceRepetition::WEEKEND_DO_NOTHING) { + if ((int)$repetition->weekend === RecurrenceRepetition::WEEKEND_DO_NOTHING) { Log::debug('Repetition will not be filtered on weekend days.'); return $dates; diff --git a/app/Support/Request/AppendsLocationData.php b/app/Support/Request/AppendsLocationData.php index 7958cacdac..0bd76b8143 100644 --- a/app/Support/Request/AppendsLocationData.php +++ b/app/Support/Request/AppendsLocationData.php @@ -42,9 +42,9 @@ trait AppendsLocationData /** * Read the submitted Request data and add new or updated Location data to the array. * - * @param array $data + * @param array $data * - * @param string|null $prefix + * @param string|null $prefix * * @return array */ @@ -100,8 +100,8 @@ trait AppendsLocationData } /** - * @param string|null $prefix - * @param string $key + * @param string|null $prefix + * @param string $key * * @return string */ @@ -115,7 +115,7 @@ trait AppendsLocationData } /** - * @param string|null $prefix + * @param string|null $prefix * * @return bool */ @@ -167,7 +167,7 @@ trait AppendsLocationData /** * Abstract method. * - * @param mixed ...$patterns + * @param mixed ...$patterns * * @return mixed */ @@ -176,15 +176,15 @@ trait AppendsLocationData /** * Abstract method stolen from "InteractsWithInput". * - * @param null $key - * @param bool $default + * @param null $key + * @param bool $default * * @return mixed */ abstract public function boolean($key = null, $default = false); /** - * @param string|null $prefix + * @param string|null $prefix * * @return bool */ @@ -229,7 +229,7 @@ trait AppendsLocationData } /** - * @param string|null $prefix + * @param string|null $prefix * * @return bool */ @@ -240,13 +240,12 @@ trait AppendsLocationData $zoomLevelKey = $this->getLocationKey($prefix, 'zoom_level'); return ( - null === $this->get($longitudeKey) - && null === $this->get($latitudeKey) - && null === $this->get($zoomLevelKey)) - && ('PUT' === $this->method() + null === $this->get($longitudeKey) + && null === $this->get($latitudeKey) + && null === $this->get($zoomLevelKey)) + && ( + 'PUT' === $this->method() || ('POST' === $this->method() && $this->routeIs('*.update')) ); - } - } diff --git a/app/Support/Request/ConvertAPIDataTypes.php b/app/Support/Request/ConvertAPIDataTypes.php index 3c6acabc22..837e906847 100644 --- a/app/Support/Request/ConvertAPIDataTypes.php +++ b/app/Support/Request/ConvertAPIDataTypes.php @@ -28,5 +28,4 @@ namespace FireflyIII\Support\Request; */ trait ConvertAPIDataTypes { - } diff --git a/app/Support/Request/ConvertsDataTypes.php b/app/Support/Request/ConvertsDataTypes.php index b4e3cf2fce..17d217d10f 100644 --- a/app/Support/Request/ConvertsDataTypes.php +++ b/app/Support/Request/ConvertsDataTypes.php @@ -32,33 +32,51 @@ use Log; */ trait ConvertsDataTypes { + /** + * Abstract method that always exists in the Request classes that use this + * trait, OR a stub needs to be added by any other class that uses this train. + * + * @param string $key + * @param mixed|null $default + * @return mixed + */ + abstract public function get(string $key, mixed $default = null): mixed; + + /** + * Abstract method that always exists in the Request classes that use this + * trait, OR a stub needs to be added by any other class that uses this train. + * + * @param mixed $key + * @return mixed + */ + abstract public function has($key); /** * Return integer value. * - * @param string $field + * @param string $field * * @return int */ public function convertInteger(string $field): int { - return (int) $this->get($field); + return (int)$this->get($field); } /** * Return string value. * - * @param string $field + * @param string $field * * @return string */ public function convertString(string $field): string { - return $this->clearString((string) ($this->get($field) ?? ''), false); + return $this->clearString((string)($this->get($field) ?? ''), false); } /** - * @param string|null $string - * @param bool $keepNewlines + * @param string|null $string + * @param bool $keepNewlines * * @return string|null */ @@ -122,23 +140,26 @@ trait ConvertsDataTypes $secondSearch = $keepNewlines ? ["\r"] : ["\r", "\n", "\t", "\036", "\025"]; $string = str_replace($secondSearch, '', $string); + // clear zalgo text (TODO also in API v2) + $string = preg_replace('/\pM/u', '', $string); + return trim($string); } /** * Return string value with newlines. * - * @param string $field + * @param string $field * * @return string */ public function stringWithNewlines(string $field): string { - return $this->clearString((string) ($this->get($field) ?? '')); + return $this->clearString((string)($this->get($field) ?? '')); } /** - * @param mixed $array + * @param mixed $array * * @return array|null */ @@ -158,7 +179,7 @@ trait ConvertsDataTypes } /** - * @param string|null $value + * @param string|null $value * * @return bool */ @@ -184,7 +205,24 @@ trait ConvertsDataTypes } /** - * @param string|null $string + * Return floating value. + * + * @param string $field + * + * @return float|null + */ + protected function convertFloat(string $field): ?float + { + $res = $this->get($field); + if (null === $res) { + return null; + } + + return (float)$res; + } + + /** + * @param string|null $string * * @return Carbon|null */ @@ -198,7 +236,7 @@ trait ConvertsDataTypes } $carbon = null; try { - $carbon = new Carbon($string); + $carbon = new Carbon($string, config('app.timezone')); } catch (InvalidFormatException $e) { // @ignoreException } @@ -212,28 +250,11 @@ trait ConvertsDataTypes return $carbon; } - /** - * Return floating value. - * - * @param string $field - * - * @return float|null - */ - protected function convertFloat(string $field): ?float - { - $res = $this->get($field); - if (null === $res) { - return null; - } - - return (float) $res; - } - /** * Returns all data in the request, or omits the field if not set, * according to the config from the request. This is the way. * - * @param array $fields + * @param array $fields * * @return array */ @@ -253,7 +274,7 @@ trait ConvertsDataTypes /** * Return date or NULL. * - * @param string $field + * @param string $field * * @return Carbon|null */ @@ -275,7 +296,7 @@ trait ConvertsDataTypes /** * Parse to integer * - * @param string|null $string + * @param string|null $string * * @return int|null */ @@ -288,13 +309,13 @@ trait ConvertsDataTypes return null; } - return (int) $string; + return (int)$string; } /** * Return integer value, or NULL when it's not set. * - * @param string $field + * @param string $field * * @return int|null */ @@ -304,12 +325,11 @@ trait ConvertsDataTypes return null; } - $value = (string) $this->get($field); + $value = (string)$this->get($field); if ('' === $value) { return null; } - return (int) $value; + return (int)$value; } - } diff --git a/app/Support/Request/GetRecurrenceData.php b/app/Support/Request/GetRecurrenceData.php index 38602e28f2..661823ac60 100644 --- a/app/Support/Request/GetRecurrenceData.php +++ b/app/Support/Request/GetRecurrenceData.php @@ -29,7 +29,7 @@ namespace FireflyIII\Support\Request; trait GetRecurrenceData { /** - * @param array $transaction + * @param array $transaction * * @return array */ @@ -42,7 +42,7 @@ trait GetRecurrenceData $return['amount'] = $transaction['amount']; } if (array_key_exists('currency_id', $transaction)) { - $return['currency_id'] = (int) $transaction['currency_id']; + $return['currency_id'] = (int)$transaction['currency_id']; } if (array_key_exists('currency_code', $transaction)) { $return['currency_code'] = $transaction['currency_code']; @@ -53,17 +53,17 @@ trait GetRecurrenceData $return['foreign_amount'] = $transaction['foreign_amount']; } if (array_key_exists('foreign_currency_id', $transaction)) { - $return['foreign_currency_id'] = (int) $transaction['foreign_currency_id']; + $return['foreign_currency_id'] = (int)$transaction['foreign_currency_id']; } if (array_key_exists('foreign_currency_code', $transaction)) { $return['foreign_currency_code'] = $transaction['foreign_currency_code']; } // source + dest if (array_key_exists('source_id', $transaction)) { - $return['source_id'] = (int) $transaction['source_id']; + $return['source_id'] = (int)$transaction['source_id']; } if (array_key_exists('destination_id', $transaction)) { - $return['destination_id'] = (int) $transaction['destination_id']; + $return['destination_id'] = (int)$transaction['destination_id']; } // description if (array_key_exists('description', $transaction)) { @@ -71,20 +71,19 @@ trait GetRecurrenceData } if (array_key_exists('piggy_bank_id', $transaction)) { - $return['piggy_bank_id'] = (int) $transaction['piggy_bank_id']; + $return['piggy_bank_id'] = (int)$transaction['piggy_bank_id']; } if (array_key_exists('tags', $transaction)) { $return['tags'] = $transaction['tags']; } if (array_key_exists('budget_id', $transaction)) { - $return['budget_id'] = (int) $transaction['budget_id']; + $return['budget_id'] = (int)$transaction['budget_id']; } if (array_key_exists('category_id', $transaction)) { - $return['category_id'] = (int) $transaction['category_id']; + $return['category_id'] = (int)$transaction['category_id']; } return $return; } - } diff --git a/app/Support/Request/GetRuleConfiguration.php b/app/Support/Request/GetRuleConfiguration.php index 9c7e8ef1fb..776d966ea6 100644 --- a/app/Support/Request/GetRuleConfiguration.php +++ b/app/Support/Request/GetRuleConfiguration.php @@ -28,7 +28,6 @@ namespace FireflyIII\Support\Request; */ trait GetRuleConfiguration { - /** * @return array */ diff --git a/app/Support/Search/AccountSearch.php b/app/Support/Search/AccountSearch.php index 9ace498a2b..1a8cd8e002 100644 --- a/app/Support/Search/AccountSearch.php +++ b/app/Support/Search/AccountSearch.php @@ -27,7 +27,6 @@ namespace FireflyIII\Support\Search; use FireflyIII\User; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; -use JsonException; /** * Class AccountSearch @@ -59,7 +58,6 @@ class AccountSearch implements GenericSearchInterface */ public function search(): Collection { - $searchQuery = $this->user->accounts() ->leftJoin('account_types', 'accounts.account_type_id', '=', 'account_types.id') ->leftJoin('account_meta', 'accounts.id', '=', 'account_meta.account_id') @@ -86,7 +84,7 @@ class AccountSearch implements GenericSearchInterface ); break; case self::SEARCH_ID: - $searchQuery->where('accounts.id', '=', (int) $originalQuery); + $searchQuery->where('accounts.id', '=', (int)$originalQuery); break; case self::SEARCH_NAME: $searchQuery->where('accounts.name', 'LIKE', $like); @@ -110,7 +108,7 @@ class AccountSearch implements GenericSearchInterface } /** - * @param string $field + * @param string $field */ public function setField(string $field): void { @@ -118,7 +116,7 @@ class AccountSearch implements GenericSearchInterface } /** - * @param string $query + * @param string $query */ public function setQuery(string $query): void { @@ -126,7 +124,7 @@ class AccountSearch implements GenericSearchInterface } /** - * @param array $types + * @param array $types */ public function setTypes(array $types): void { @@ -134,11 +132,10 @@ class AccountSearch implements GenericSearchInterface } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { $this->user = $user; } - } diff --git a/app/Support/Search/GenericSearchInterface.php b/app/Support/Search/GenericSearchInterface.php index 60b4539da7..e7bb9005c3 100644 --- a/app/Support/Search/GenericSearchInterface.php +++ b/app/Support/Search/GenericSearchInterface.php @@ -35,5 +35,4 @@ interface GenericSearchInterface * @return Collection */ public function search(): Collection; - } diff --git a/app/Support/Search/OperatorQuerySearch.php b/app/Support/Search/OperatorQuerySearch.php index 3978c9caec..e2ca15d071 100644 --- a/app/Support/Search/OperatorQuerySearch.php +++ b/app/Support/Search/OperatorQuerySearch.php @@ -38,6 +38,7 @@ use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\Tag\TagRepositoryInterface; use FireflyIII\Support\ParseDateString; use FireflyIII\User; +use Gdbots\QueryParser\Enum\BoolOperator; use Gdbots\QueryParser\Node\Date; use Gdbots\QueryParser\Node\Emoji; use Gdbots\QueryParser\Node\Emoticon; @@ -73,6 +74,7 @@ class OperatorQuerySearch implements SearchInterface private int $limit; private Collection $operators; private int $page; + private array $prohibitedWords; private float $startTime; private TagRepositoryInterface $tagRepository; private array $validOperators; @@ -86,9 +88,10 @@ class OperatorQuerySearch implements SearchInterface public function __construct() { Log::debug('Constructed OperatorQuerySearch'); - $this->operators = new Collection; + $this->operators = new Collection(); $this->page = 1; $this->words = []; + $this->prohibitedWords = []; $this->invalidOperators = []; $this->limit = 25; $this->date = today(config('app.timezone')); @@ -168,10 +171,11 @@ class OperatorQuerySearch implements SearchInterface } $this->collector->setSearchWords($this->words); + $this->collector->excludeSearchWords($this->prohibitedWords); } /** - * @param Node $searchNode + * @param Node $searchNode * * @throws FireflyException */ @@ -185,8 +189,8 @@ class OperatorQuerySearch implements SearchInterface throw new FireflyException(sprintf('Firefly III search cant handle "%s"-nodes', $class)); case Subquery::class: // loop all notes in subquery: - foreach ($searchNode->getNodes() as $subNode) { // @phpstan-ignore-line - $this->handleSearchNode($subNode); // let's hope it's not too recursive! + foreach ($searchNode->getNodes() as $subNode) { // @phpstan-ignore-line PHPStan thinks getNodes() does not exist but it does. + $this->handleSearchNode($subNode); // let's hope it's not too recursive } break; case Word::class: @@ -198,7 +202,7 @@ class OperatorQuerySearch implements SearchInterface case Emoticon::class: case Emoji::class: case Mention::class: - $allWords = (string) $searchNode->getValue(); + $allWords = (string)$searchNode->getValue(); Log::debug(sprintf('Add words "%s" to search string, because Node class is "%s"', $allWords, $class)); $this->words[] = $allWords; break; @@ -206,14 +210,25 @@ class OperatorQuerySearch implements SearchInterface Log::debug(sprintf('Now handle Node class %s', $class)); /** @var Field $searchNode */ // used to search for x:y - $operator = strtolower($searchNode->getValue()); - $value = $searchNode->getNode()->getValue(); + $operator = strtolower($searchNode->getValue()); + $value = $searchNode->getNode()->getValue(); + $prohibited = $searchNode->getBoolOperator()->equals(BoolOperator::PROHIBITED()->getValue()); + $context = config(sprintf('search.operators.%s.needs_context', $operator)); + + // is an operator that needs no context, and value is false, then prohibited = true. + if ('false' === $value && in_array($operator, $this->validOperators, true) && false === $context) { + $prohibited = true; + } + // must be valid operator: - if (in_array($operator, $this->validOperators, true) && $this->updateCollector($operator, (string) $value)) { + if ( + in_array($operator, $this->validOperators, true) && + $this->updateCollector($operator, (string)$value, $prohibited)) { $this->operators->push( [ - 'type' => self::getRootOperator($operator), - 'value' => (string) $value, + 'type' => self::getRootOperator($operator), + 'value' => (string)$value, + 'prohibited' => $prohibited, ] ); Log::debug(sprintf('Added operator type "%s"', $operator)); @@ -222,22 +237,26 @@ class OperatorQuerySearch implements SearchInterface Log::debug(sprintf('Added INVALID operator type "%s"', $operator)); $this->invalidOperators[] = [ 'type' => $operator, - 'value' => (string) $value, + 'value' => (string)$value, ]; } } - } /** - * @param string $operator - * @param string $value + * @param string $operator + * @param string $value * * @return bool * @throws FireflyException */ - private function updateCollector(string $operator, string $value): bool + private function updateCollector(string $operator, string $value, bool $prohibited): bool { + if ($prohibited) { + Log::debug(sprintf('Operator "%s" is now "%s"', $operator, sprintf('-%s', $operator))); + $operator = sprintf('-%s', $operator); + } + Log::debug(sprintf('Now in updateCollector("%s", "%s")', $operator, $value)); // check if alias, replace if necessary: @@ -247,64 +266,112 @@ class OperatorQuerySearch implements SearchInterface default: Log::error(sprintf('No such operator: %s', $operator)); throw new FireflyException(sprintf('Unsupported search operator: "%s"', $operator)); - // some search operators are ignored, basically: + // some search operators are ignored, basically: case 'user_action': Log::info(sprintf('Ignore search operator "%s"', $operator)); return false; // - // all account related searches: + // all account related searches: // case 'account_is': $this->searchAccount($value, 3, 4); break; + case '-account_is': + $this->searchAccount($value, 3, 4, true); + break; case 'account_contains': $this->searchAccount($value, 3, 3); break; + case '-account_contains': + $this->searchAccount($value, 3, 3, true); + break; case 'account_ends': $this->searchAccount($value, 3, 2); break; + case '-account_ends': + $this->searchAccount($value, 3, 2, true); + break; case 'account_starts': $this->searchAccount($value, 3, 1); break; + case '-account_starts': + $this->searchAccount($value, 3, 1, true); + break; case 'account_nr_is': $this->searchAccountNr($value, 3, 4); break; + case '-account_nr_is': + $this->searchAccountNr($value, 3, 4, true); + break; case 'account_nr_contains': $this->searchAccountNr($value, 3, 3); break; + case '-account_nr_contains': + $this->searchAccountNr($value, 3, 3, true); + break; case 'account_nr_ends': $this->searchAccountNr($value, 3, 2); break; + case '-account_nr_ends': + $this->searchAccountNr($value, 3, 2, true); + break; case 'account_nr_starts': $this->searchAccountNr($value, 3, 1); break; + case '-account_nr_starts': + $this->searchAccountNr($value, 3, 1, true); + break; case 'source_account_starts': $this->searchAccount($value, 1, 1); break; + case '-source_account_starts': + $this->searchAccount($value, 1, 1, true); + break; case 'source_account_ends': $this->searchAccount($value, 1, 2); break; + case '-source_account_ends': + $this->searchAccount($value, 1, 2, true); + break; case 'source_account_is': $this->searchAccount($value, 1, 4); break; + case '-source_account_is': + $this->searchAccount($value, 1, 4, true); + break; case 'source_account_nr_starts': $this->searchAccountNr($value, 1, 1); break; + case '-source_account_nr_starts': + $this->searchAccountNr($value, 1, 1, true); + break; case 'source_account_nr_ends': $this->searchAccountNr($value, 1, 2); break; + case '-source_account_nr_ends': + $this->searchAccountNr($value, 1, 2, true); + break; case 'source_account_nr_is': $this->searchAccountNr($value, 1, 4); break; + case '-source_account_nr_is': + $this->searchAccountNr($value, 1, 4, true); + break; case 'source_account_nr_contains': $this->searchAccountNr($value, 1, 3); break; + case '-source_account_nr_contains': + $this->searchAccountNr($value, 1, 3, true); + break; case 'source_account_contains': $this->searchAccount($value, 1, 3); break; + case '-source_account_contains': + $this->searchAccount($value, 1, 3, true); + break; case 'source_account_id': - $account = $this->accountRepository->find((int) $value); + $account = $this->accountRepository->find((int)$value); if (null !== $account) { $this->collector->setSourceAccounts(new Collection([$account])); } @@ -313,40 +380,82 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-source_account_id': + $account = $this->accountRepository->find((int)$value); + if (null !== $account) { + $this->collector->excludeSourceAccounts(new Collection([$account])); + } + if (null === $account) { + // since the source does not exist, cannot return results: + $this->collector->findNothing(); + } + break; case 'journal_id': $parts = explode(',', $value); $this->collector->setJournalIds($parts); break; + case '-journal_id': + $parts = explode(',', $value); + $this->collector->excludeJournalIds($parts); + break; case 'id': $parts = explode(',', $value); $this->collector->setIds($parts); break; + case '-id': + $parts = explode(',', $value); + $this->collector->excludeIds($parts); + break; case 'destination_account_starts': $this->searchAccount($value, 2, 1); break; + case '-destination_account_starts': + $this->searchAccount($value, 2, 1, true); + break; case 'destination_account_ends': $this->searchAccount($value, 2, 2); break; + case '-destination_account_ends': + $this->searchAccount($value, 2, 2, true); + break; case 'destination_account_nr_starts': $this->searchAccountNr($value, 2, 1); break; + case '-destination_account_nr_starts': + $this->searchAccountNr($value, 2, 1, true); + break; case 'destination_account_nr_ends': $this->searchAccountNr($value, 2, 2); break; + case '-destination_account_nr_ends': + $this->searchAccountNr($value, 2, 2, true); + break; case 'destination_account_nr_is': $this->searchAccountNr($value, 2, 4); break; + case '-destination_account_nr_is': + $this->searchAccountNr($value, 2, 4, true); + break; case 'destination_account_is': $this->searchAccount($value, 2, 4); break; + case '-destination_account_is': + $this->searchAccount($value, 2, 4, true); + break; case 'destination_account_nr_contains': $this->searchAccountNr($value, 2, 3); break; + case '-destination_account_nr_contains': + $this->searchAccountNr($value, 2, 3, true); + break; case 'destination_account_contains': $this->searchAccount($value, 2, 3); break; + case '-destination_account_contains': + $this->searchAccount($value, 2, 3, true); + break; case 'destination_account_id': - $account = $this->accountRepository->find((int) $value); + $account = $this->accountRepository->find((int)$value); if (null !== $account) { $this->collector->setDestinationAccounts(new Collection([$account])); } @@ -354,11 +463,20 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-destination_account_id': + $account = $this->accountRepository->find((int)$value); + if (null !== $account) { + $this->collector->excludeDestinationAccounts(new Collection([$account])); + } + if (null === $account) { + $this->collector->findNothing(); + } + break; case 'account_id': $parts = explode(',', $value); - $collection = new Collection; + $collection = new Collection(); foreach ($parts as $accountId) { - $account = $this->accountRepository->find((int) $accountId); + $account = $this->accountRepository->find((int)$accountId); if (null !== $account) { $collection->push($account); } @@ -370,39 +488,80 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-account_id': + $parts = explode(',', $value); + $collection = new Collection(); + foreach ($parts as $accountId) { + $account = $this->accountRepository->find((int)$accountId); + if (null !== $account) { + $collection->push($account); + } + } + if ($collection->count() > 0) { + $this->collector->setNotAccounts($collection); + } + if (0 === $collection->count()) { + $this->collector->findNothing(); + } + break; // - // cash account + // cash account // case 'source_is_cash': $account = $this->getCashAccount(); $this->collector->setSourceAccounts(new Collection([$account])); break; + case '-source_is_cash': + $account = $this->getCashAccount(); + $this->collector->excludeSourceAccounts(new Collection([$account])); + break; case 'destination_is_cash': $account = $this->getCashAccount(); $this->collector->setDestinationAccounts(new Collection([$account])); break; + case '-destination_is_cash': + $account = $this->getCashAccount(); + $this->collector->excludeDestinationAccounts(new Collection([$account])); + break; case 'account_is_cash': $account = $this->getCashAccount(); $this->collector->setAccounts(new Collection([$account])); break; + case '-account_is_cash': + $account = $this->getCashAccount(); + $this->collector->excludeAccounts(new Collection([$account])); + break; // - // description + // description // case 'description_starts': $this->collector->descriptionStarts([$value]); break; + case '-description_starts': + $this->collector->descriptionDoesNotStart([$value]); + break; case 'description_ends': $this->collector->descriptionEnds([$value]); break; + case '-description_ends': + $this->collector->descriptionDoesNotEnd([$value]); + break; case 'description_contains': $this->words[] = $value; return false; + case '-description_contains': + $this->prohibitedWords[] = $value; + + break; case 'description_is': $this->collector->descriptionIs($value); break; + case '-description_is': + $this->collector->descriptionIsNot($value); + break; // - // currency + // currency // case 'currency_is': $currency = $this->findCurrency($value); @@ -413,6 +572,15 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-currency_is': + $currency = $this->findCurrency($value); + if (null !== $currency) { + $this->collector->excludeCurrency($currency); + } + if (null === $currency) { + $this->collector->findNothing(); + } + break; case 'foreign_currency_is': $currency = $this->findCurrency($value); if (null !== $currency) { @@ -422,22 +590,35 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-foreign_currency_is': + $currency = $this->findCurrency($value); + if (null !== $currency) { + $this->collector->excludeForeignCurrency($currency); + } + if (null === $currency) { + $this->collector->findNothing(); + } + break; // - // attachments + // attachments // case 'has_attachments': + case '-has_no_attachments': Log::debug('Set collector to filter on attachments.'); $this->collector->hasAttachments(); break; case 'has_no_attachments': + case '-has_attachments': Log::debug('Set collector to filter on NO attachments.'); $this->collector->hasNoAttachments(); break; // - // categories + // categories + case '-has_any_category': case 'has_no_category': $this->collector->withoutCategory(); break; + case '-has_no_category': case 'has_any_category': $this->collector->withCategory(); break; @@ -449,6 +630,13 @@ class OperatorQuerySearch implements SearchInterface } $this->collector->findNothing(); break; + case '-category_is': + $category = $this->categoryRepository->findByName($value); + if (null !== $category) { + $this->collector->excludeCategory($category); + break; + } + break; case 'category_ends': $result = $this->categoryRepository->categoryEndsWith($value, 1337); if ($result->count() > 0) { @@ -458,6 +646,15 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-category_ends': + $result = $this->categoryRepository->categoryEndsWith($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeCategories($result); + } + if (0 === $result->count()) { + $this->collector->findNothing(); + } + break; case 'category_starts': $result = $this->categoryRepository->categoryStartsWith($value, 1337); if ($result->count() > 0) { @@ -467,6 +664,15 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-category_starts': + $result = $this->categoryRepository->categoryStartsWith($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeCategories($result); + } + if (0 === $result->count()) { + $this->collector->findNothing(); + } + break; case 'category_contains': $result = $this->categoryRepository->searchCategory($value, 1337); if ($result->count() > 0) { @@ -476,13 +682,24 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-category_contains': + $result = $this->categoryRepository->searchCategory($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeCategories($result); + } + if (0 === $result->count()) { + $this->collector->findNothing(); + } + break; // - // budgets + // budgets // + case '-has_any_budget': case 'has_no_budget': $this->collector->withoutBudget(); break; case 'has_any_budget': + case '-has_no_budget': $this->collector->withBudget(); break; case 'budget_contains': @@ -494,6 +711,15 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-budget_contains': + $result = $this->budgetRepository->searchBudget($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeBudgets($result); + } + if (0 === $result->count()) { + $this->collector->findNothing(); + } + break; case 'budget_is': $budget = $this->budgetRepository->findByName($value); if (null !== $budget) { @@ -502,6 +728,14 @@ class OperatorQuerySearch implements SearchInterface } $this->collector->findNothing(); break; + case '-budget_is': + $budget = $this->budgetRepository->findByName($value); + if (null !== $budget) { + $this->collector->excludeBudget($budget); + break; + } + $this->collector->findNothing(); + break; case 'budget_ends': $result = $this->budgetRepository->budgetEndsWith($value, 1337); if ($result->count() > 0) { @@ -511,6 +745,15 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-budget_ends': + $result = $this->budgetRepository->budgetEndsWith($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeBudgets($result); + } + if (0 === $result->count()) { + $this->collector->findNothing(); + } + break; case 'budget_starts': $result = $this->budgetRepository->budgetStartsWith($value, 1337); if ($result->count() > 0) { @@ -520,12 +763,23 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-budget_starts': + $result = $this->budgetRepository->budgetStartsWith($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeBudgets($result); + } + if (0 === $result->count()) { + $this->collector->findNothing(); + } + break; // - // bill + // bill // + case '-has_any_bill': case 'has_no_bill': $this->collector->withoutBill(); break; + case '-has_no_bill': case 'has_any_bill': $this->collector->withBill(); break; @@ -537,6 +791,14 @@ class OperatorQuerySearch implements SearchInterface } $this->collector->findNothing(); break; + case '-bill_contains': + $result = $this->billRepository->searchBill($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeBills($result); + break; + } + $this->collector->findNothing(); + break; case 'bill_is': $bill = $this->billRepository->findByName($value); if (null !== $bill) { @@ -545,6 +807,14 @@ class OperatorQuerySearch implements SearchInterface } $this->collector->findNothing(); break; + case '-bill_is': + $bill = $this->billRepository->findByName($value); + if (null !== $bill) { + $this->collector->excludeBills(new Collection([$bill])); + break; + } + $this->collector->findNothing(); + break; case 'bill_ends': $result = $this->billRepository->billEndsWith($value, 1337); if ($result->count() > 0) { @@ -554,6 +824,15 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-bill_ends': + $result = $this->billRepository->billEndsWith($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeBills($result); + } + if (0 === $result->count()) { + $this->collector->findNothing(); + } + break; case 'bill_starts': $result = $this->billRepository->billStartsWith($value, 1337); if ($result->count() > 0) { @@ -563,15 +842,27 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-bill_starts': + $result = $this->billRepository->billStartsWith($value, 1337); + if ($result->count() > 0) { + $this->collector->excludeBills($result); + } + if (0 === $result->count()) { + $this->collector->findNothing(); + } + break; // - // tags + // tags // + case '-has_any_tag': case 'has_no_tag': $this->collector->withoutTags(); break; + case '-has_no_tag': case 'has_any_tag': $this->collector->hasAnyTag(); break; + case '-tag_is_not': case 'tag_is': $result = $this->tagRepository->searchTag($value); if ($result->count() > 0) { @@ -583,6 +874,7 @@ class OperatorQuerySearch implements SearchInterface $this->collector->findNothing(); } break; + case '-tag_is': case 'tag_is_not': $result = $this->tagRepository->searchTag($value); if ($result->count() > 0) { @@ -590,336 +882,517 @@ class OperatorQuerySearch implements SearchInterface } break; // - // notes + // notes // case 'notes_contains': $this->collector->notesContain($value); break; + case '-notes_contains': + $this->collector->notesDoNotContain($value); + break; case 'notes_starts': $this->collector->notesStartWith($value); break; + case '-notes_starts': + $this->collector->notesDontStartWith($value); + break; case 'notes_ends': $this->collector->notesEndWith($value); break; + case '-notes_ends': + $this->collector->notesDontEndWith($value); + break; case 'notes_is': $this->collector->notesExactly($value); break; + case '-notes_is': + $this->collector->notesExactlyNot($value); + break; + case '-any_notes': case 'no_notes': $this->collector->withoutNotes(); break; case 'any_notes': + case '-no_notes': $this->collector->withAnyNotes(); break; + case 'reconciled': + $this->collector->isReconciled(); + break; + case '-reconciled': + $this->collector->isNotReconciled(); + break; // - // amount + // amount // case 'amount_is': // strip comma's, make dots. Log::debug(sprintf('Original value "%s"', $value)); - $value = str_replace(',', '.', (string) $value); + $value = str_replace(',', '.', (string)$value); $amount = app('steam')->positive($value); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->amountIs($amount); break; + case '-amount_is': + // strip comma's, make dots. + Log::debug(sprintf('Original value "%s"', $value)); + $value = str_replace(',', '.', (string)$value); + $amount = app('steam')->positive($value); + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); + $this->collector->amountIsNot($amount); + break; case 'foreign_amount_is': // strip comma's, make dots. - $value = str_replace(',', '.', (string) $value); + $value = str_replace(',', '.', (string)$value); $amount = app('steam')->positive($value); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->foreignAmountIs($amount); break; + case '-foreign_amount_is': + + // strip comma's, make dots. + $value = str_replace(',', '.', (string)$value); + + $amount = app('steam')->positive($value); + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); + $this->collector->foreignAmountIsNot($amount); + break; + case '-amount_more': case 'amount_less': // strip comma's, make dots. - $value = str_replace(',', '.', (string) $value); + $value = str_replace(',', '.', (string)$value); $amount = app('steam')->positive($value); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->amountLess($amount); break; + case '-foreign_amount_more': case 'foreign_amount_less': // strip comma's, make dots. - $value = str_replace(',', '.', (string) $value); + $value = str_replace(',', '.', (string)$value); $amount = app('steam')->positive($value); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->foreignAmountLess($amount); break; + case '-amount_less': case 'amount_more': Log::debug(sprintf('Now handling operator "%s"', $operator)); // strip comma's, make dots. - $value = str_replace(',', '.', (string) $value); + $value = str_replace(',', '.', (string)$value); $amount = app('steam')->positive($value); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->amountMore($amount); break; + case '-foreign_amount_less': case 'foreign_amount_more': Log::debug(sprintf('Now handling operator "%s"', $operator)); // strip comma's, make dots. - $value = str_replace(',', '.', (string) $value); + $value = str_replace(',', '.', (string)$value); $amount = app('steam')->positive($value); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $amount)); $this->collector->foreignAmountMore($amount); break; // - // transaction type + // transaction type // case 'transaction_type': $this->collector->setTypes([ucfirst($value)]); Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); break; + case '-transaction_type': + $this->collector->excludeTypes([ucfirst($value)]); + Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); + break; // - // dates + // dates // + case '-date_on': case 'date_on': $range = $this->parseDateRange($value); - $this->setExactDateParams($range); + $this->setExactDateParams($range, $prohibited); return false; case 'date_before': + case '-date_after': $range = $this->parseDateRange($value); $this->setDateBeforeParams($range); return false; case 'date_after': + case '-date_before': $range = $this->parseDateRange($value); $this->setDateAfterParams($range); return false; + case 'interest_date_on': + case '-interest_date_on': $range = $this->parseDateRange($value); - $this->setExactMetaDateParams('interest_date', $range); + $this->setExactMetaDateParams('interest_date', $range, $prohibited); return false; case 'interest_date_before': + case '-interest_date_after': $range = $this->parseDateRange($value); $this->setMetaDateBeforeParams('interest_date', $range); return false; case 'interest_date_after': + case '-interest_date_before': $range = $this->parseDateRange($value); $this->setMetaDateAfterParams('interest_date', $range); return false; case 'book_date_on': + case '-book_date_on': $range = $this->parseDateRange($value); - $this->setExactMetaDateParams('book_date', $range); + $this->setExactMetaDateParams('book_date', $range, $prohibited); return false; case 'book_date_before': + case '-book_date_after': $range = $this->parseDateRange($value); $this->setMetaDateBeforeParams('book_date', $range); return false; case 'book_date_after': + case '-book_date_before': $range = $this->parseDateRange($value); $this->setMetaDateAfterParams('book_date', $range); return false; case 'process_date_on': + case '-process_date_on': $range = $this->parseDateRange($value); - $this->setExactMetaDateParams('process_date', $range); + $this->setExactMetaDateParams('process_date', $range, $prohibited); return false; case 'process_date_before': + case '-process_date_after': $range = $this->parseDateRange($value); $this->setMetaDateBeforeParams('process_date', $range); return false; case 'process_date_after': + case '-process_date_before': $range = $this->parseDateRange($value); $this->setMetaDateAfterParams('process_date', $range); return false; + case 'due_date_on': + case '-due_date_on': $range = $this->parseDateRange($value); - $this->setExactMetaDateParams('due_date', $range); + $this->setExactMetaDateParams('due_date', $range, $prohibited); return false; case 'due_date_before': + case '-due_date_after': $range = $this->parseDateRange($value); $this->setMetaDateBeforeParams('due_date', $range); return false; case 'due_date_after': + case '-due_date_before': $range = $this->parseDateRange($value); $this->setMetaDateAfterParams('due_date', $range); return false; + case 'payment_date_on': + case '-payment_date_on': $range = $this->parseDateRange($value); - $this->setExactMetaDateParams('payment_date', $range); + $this->setExactMetaDateParams('payment_date', $range, $prohibited); return false; case 'payment_date_before': + case '-payment_date_after': $range = $this->parseDateRange($value); $this->setMetaDateBeforeParams('payment_date', $range); return false; case 'payment_date_after': + case '-payment_date_before': $range = $this->parseDateRange($value); $this->setMetaDateAfterParams('payment_date', $range); return false; + case 'invoice_date_on': + case '-invoice_date_on': $range = $this->parseDateRange($value); - $this->setExactMetaDateParams('invoice_date', $range); + $this->setExactMetaDateParams('invoice_date', $range, $prohibited); return false; case 'invoice_date_before': + case '-invoice_date_after': $range = $this->parseDateRange($value); $this->setMetaDateBeforeParams('invoice_date', $range); return false; case 'invoice_date_after': + case '-invoice_date_before': $range = $this->parseDateRange($value); $this->setMetaDateAfterParams('invoice_date', $range); return false; + case 'created_at_on': + case '-created_at_on': Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); $range = $this->parseDateRange($value); - $this->setExactObjectDateParams('created_at', $range); + $this->setExactObjectDateParams('created_at', $range, $prohibited); return false; case 'created_at_before': + case '-created_at_after': Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); $range = $this->parseDateRange($value); $this->setObjectDateBeforeParams('created_at', $range); return false; case 'created_at_after': + case '-created_at_before': Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); $range = $this->parseDateRange($value); $this->setObjectDateAfterParams('created_at', $range); return false; + case 'updated_at_on': + case '-updated_at_on': Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); $range = $this->parseDateRange($value); - $this->setExactObjectDateParams('updated_at', $range); + $this->setExactObjectDateParams('updated_at', $range, $prohibited); return false; case 'updated_at_before': + case '-updated_at_after': Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); $range = $this->parseDateRange($value); $this->setObjectDateBeforeParams('updated_at', $range); return false; case 'updated_at_after': + case '-updated_at_before': Log::debug(sprintf('Set "%s" using collector with value "%s"', $operator, $value)); $range = $this->parseDateRange($value); $this->setObjectDateAfterParams('updated_at', $range); return false; // - // external URL + // external URL // + case '-any_external_url': case 'no_external_url': $this->collector->withoutExternalUrl(); break; + case '-no_external_url': case 'any_external_url': $this->collector->withExternalUrl(); break; + case '-any_external_id': + case 'no_external_id': + $this->collector->withoutExternalId(); + break; + case '-no_external_id': + case 'any_external_id': + $this->collector->withExternalId(); + break; + case 'external_url_is': $this->collector->setExternalUrl($value); break; + case '-external_url_is': + $this->collector->excludeExternalUrl($value); + break; case 'external_url_contains': $this->collector->externalUrlContains($value); break; + case '-external_url_contains': + $this->collector->externalUrlDoesNotContain($value); + break; case 'external_url_starts': $this->collector->externalUrlStarts($value); break; + case '-external_url_starts': + $this->collector->externalUrlDoesNotStart($value); + break; case 'external_url_ends': $this->collector->externalUrlEnds($value); break; + case '-external_url_ends': + $this->collector->externalUrlDoesNotEnd($value); + break; + // - // other fields + // other fields // case 'external_id_is': $this->collector->setExternalId($value); break; + case '-external_id_is': + $this->collector->excludeExternalId($value); + break; case 'recurrence_id': $this->collector->setRecurrenceId($value); break; + case '-recurrence_id': + $this->collector->excludeRecurrenceId($value); + break; case 'external_id_contains': $this->collector->externalIdContains($value); break; + case '-external_id_contains': + $this->collector->externalIdDoesNotContain($value); + break; case 'external_id_starts': $this->collector->externalIdStarts($value); break; + case '-external_id_starts': + $this->collector->externalIdDoesNotStart($value); + break; case 'external_id_ends': $this->collector->externalIdEnds($value); break; + case '-external_id_ends': + $this->collector->externalIdDoesNotEnd($value); + break; + case 'internal_reference_is': $this->collector->setInternalReference($value); break; + case '-internal_reference_is': + $this->collector->excludeInternalReference($value); + break; case 'internal_reference_contains': $this->collector->internalReferenceContains($value); break; + case '-internal_reference_contains': + $this->collector->internalReferenceDoesNotContain($value); + break; case 'internal_reference_starts': $this->collector->internalReferenceStarts($value); break; + case '-internal_reference_starts': + $this->collector->internalReferenceDoesNotStart($value); + break; case 'internal_reference_ends': $this->collector->internalReferenceEnds($value); break; + case '-internal_reference_ends': + $this->collector->internalReferenceDoesNotEnd($value); + break; + case 'attachment_name_is': $this->collector->attachmentNameIs($value); break; + case '-attachment_name_is': + $this->collector->attachmentNameIsNot($value); + break; case 'attachment_name_contains': $this->collector->attachmentNameContains($value); break; + case '-attachment_name_contains': + $this->collector->attachmentNameDoesNotContain($value); + break; case 'attachment_name_starts': $this->collector->attachmentNameStarts($value); break; + case '-attachment_name_starts': + $this->collector->attachmentNameDoesNotStart($value); + break; case 'attachment_name_ends': $this->collector->attachmentNameEnds($value); break; + case '-attachment_name_ends': + $this->collector->attachmentNameDoesNotEnd($value); + break; + case 'attachment_notes_are': $this->collector->attachmentNotesAre($value); break; + case '-attachment_notes_are': + $this->collector->attachmentNotesAreNot($value); + break; case 'attachment_notes_contains': $this->collector->attachmentNotesContains($value); break; + case '-attachment_notes_contains': + $this->collector->attachmentNotesDoNotContain($value); + break; case 'attachment_notes_starts': $this->collector->attachmentNotesStarts($value); break; + case '-attachment_notes_starts': + $this->collector->attachmentNotesDoNotStart($value); + break; case 'attachment_notes_ends': $this->collector->attachmentNotesEnds($value); break; + case '-attachment_notes_ends': + $this->collector->attachmentNotesDoNotEnd($value); + break; + case 'exists': + $this->collector->exists(); + break; + case '-exists': + $this->collector->findNothing(); + break; case 'sepa_ct_is': $this->collector->setSepaCT($value); break; - } - return true; } /** - * @param string $operator + * @param string $operator * * @return string * @throws FireflyException */ public static function getRootOperator(string $operator): string { + $original = $operator; + // if the string starts with "-" (not), we can remove it and recycle + // the configuration from the original operator. + if (str_starts_with($operator, '-')) { + $operator = substr($operator, 1); + } + $config = config(sprintf('search.operators.%s', $operator)); if (null === $config) { throw new FireflyException(sprintf('No configuration for search operator "%s"', $operator)); } if (true === $config['alias']) { - Log::debug(sprintf('"%s" is an alias for "%s", so return that instead.', $operator, $config['alias_for'])); + $return = $config['alias_for']; + if (str_starts_with($original, '-')) { + $return = sprintf('-%s', $config['alias_for']); + } + Log::debug(sprintf('"%s" is an alias for "%s", so return that instead.', $original, $return)); - return $config['alias_for']; + return $return; } Log::debug(sprintf('"%s" is not an alias.', $operator)); - return $operator; + return $original; } /** * searchDirection: 1 = source (default), 2 = destination, 3 = both * stringPosition: 1 = start (default), 2 = end, 3 = contains, 4 = is * - * @param string $value - * @param int $searchDirection - * @param int $stringPosition + * @param string $value + * @param int $searchDirection + * @param int $stringPosition + * @param bool $prohibited */ - private function searchAccount(string $value, int $searchDirection, int $stringPosition): void + private function searchAccount(string $value, int $searchDirection, int $stringPosition, bool $prohibited = false): void { Log::debug(sprintf('searchAccount("%s", %d, %d)', $value, $stringPosition, $searchDirection)); // search direction (default): for source accounts $searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::REVENUE]; $collectorMethod = 'setSourceAccounts'; + if ($prohibited) { + $collectorMethod = 'excludeSourceAccounts'; + } // search direction: for destination accounts if (2 === $searchDirection) { // destination can be $searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::EXPENSE]; $collectorMethod = 'setDestinationAccounts'; + if ($prohibited) { + $collectorMethod = 'excludeDestinationAccounts'; + } } // either account could be: if (3 === $searchDirection) { $searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::EXPENSE, AccountType::REVENUE]; $collectorMethod = 'setAccounts'; + if ($prohibited) { + $collectorMethod = 'excludeAccounts'; + } } // string position (default): starts with: $stringMethod = 'str_starts_with'; @@ -964,29 +1437,39 @@ class OperatorQuerySearch implements SearchInterface * searchDirection: 1 = source (default), 2 = destination, 3 = both * stringPosition: 1 = start (default), 2 = end, 3 = contains, 4 = is * - * @param string $value - * @param int $searchDirection - * @param int $stringPosition + * @param string $value + * @param int $searchDirection + * @param int $stringPosition + * @param bool $prohibited */ - private function searchAccountNr(string $value, int $searchDirection, int $stringPosition): void + private function searchAccountNr(string $value, int $searchDirection, int $stringPosition, bool $prohibited = false): void { Log::debug(sprintf('searchAccountNr(%s, %d, %d)', $value, $searchDirection, $stringPosition)); // search direction (default): for source accounts $searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::REVENUE]; $collectorMethod = 'setSourceAccounts'; + if (true === $prohibited) { + $collectorMethod = 'excludeSourceAccounts'; + } // search direction: for destination accounts if (2 === $searchDirection) { // destination can be $searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::EXPENSE]; $collectorMethod = 'setDestinationAccounts'; + if (true === $prohibited) { + $collectorMethod = 'excludeDestinationAccounts'; + } } // either account could be: if (3 === $searchDirection) { $searchTypes = [AccountType::ASSET, AccountType::MORTGAGE, AccountType::LOAN, AccountType::DEBT, AccountType::EXPENSE, AccountType::REVENUE]; $collectorMethod = 'setAccounts'; + if (true === $prohibited) { + $collectorMethod = 'excludeAccounts'; + } } // string position (default): starts with: @@ -1016,8 +1499,8 @@ class OperatorQuerySearch implements SearchInterface Log::debug(sprintf('Found %d accounts, will filter.', $accounts->count())); $filtered = $accounts->filter( function (Account $account) use ($value, $stringMethod) { - // either IBAN or account number! - $ibanMatch = $stringMethod(strtolower((string) $account->iban), strtolower((string) $value)); + // either IBAN or account number + $ibanMatch = $stringMethod(strtolower((string)$account->iban), strtolower((string)$value)); $accountNrMatch = false; /** @var AccountMeta $meta */ foreach ($account->accountMeta as $meta) { @@ -1049,7 +1532,7 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param string $value + * @param string $value * * @return TransactionCurrency|null */ @@ -1069,14 +1552,14 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param string $value + * @param string $value * * @return array * @throws FireflyException */ private function parseDateRange(string $value): array { - $parser = new ParseDateString; + $parser = new ParseDateString(); if ($parser->isDateRange($value)) { return $parser->parseRange($value); } @@ -1088,17 +1571,18 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param array $range + * @param array $range * * @throws FireflyException */ - private function setExactDateParams(array $range): void + private function setExactDateParams(array $range, bool $prohibited = false): void { /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setExactParameters()', $key)); @@ -1107,37 +1591,57 @@ class OperatorQuerySearch implements SearchInterface $this->collector->setRange($value, $value); $this->operators->push(['type' => 'date_on', 'value' => $value->format('Y-m-d'),]); break; + case 'exact_not': + $this->collector->excludeRange($value, $value); + $this->operators->push(['type' => 'not_date_on', 'value' => $value->format('Y-m-d'),]); + break; case 'year': Log::debug(sprintf('Set date_is_exact YEAR value "%s"', $value)); $this->collector->yearIs($value); $this->operators->push(['type' => 'date_on_year', 'value' => $value,]); break; + case 'year_not': + Log::debug(sprintf('Set date_is_exact_not YEAR value "%s"', $value)); + $this->collector->yearIsNot($value); + $this->operators->push(['type' => 'not_date_on_year', 'value' => $value,]); + break; case 'month': Log::debug(sprintf('Set date_is_exact MONTH value "%s"', $value)); $this->collector->monthIs($value); $this->operators->push(['type' => 'date_on_month', 'value' => $value,]); break; + case 'month_not': + Log::debug(sprintf('Set date_is_exact not MONTH value "%s"', $value)); + $this->collector->monthIsNot($value); + $this->operators->push(['type' => 'not_date_on_month', 'value' => $value,]); + break; case 'day': Log::debug(sprintf('Set date_is_exact DAY value "%s"', $value)); $this->collector->dayIs($value); $this->operators->push(['type' => 'date_on_day', 'value' => $value,]); break; + case 'day_not': + Log::debug(sprintf('Set not date_is_exact DAY value "%s"', $value)); + $this->collector->dayIsNot($value); + $this->operators->push(['type' => 'not_date_on_day', 'value' => $value,]); + break; } } } /** - * @param array $range + * @param array $range * * @throws FireflyException */ - private function setDateBeforeParams(array $range): void + private function setDateBeforeParams(array $range, bool $prohibited = false): void { /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setDateBeforeParams()', $key)); @@ -1165,17 +1669,18 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param array $range + * @param array $range * * @throws FireflyException */ - private function setDateAfterParams(array $range) + private function setDateAfterParams(array $range, bool $prohibited = false) { /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setDateAfterParams()', $key)); @@ -1203,19 +1708,20 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param string $field - * @param array $range + * @param string $field + * @param array $range * @return void * @throws FireflyException */ - private function setExactMetaDateParams(string $field, array $range): void + private function setExactMetaDateParams(string $field, array $range, bool $prohibited = false): void { Log::debug('Now in setExactMetaDateParams()'); /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setExactMetaDateParams()', $key)); @@ -1224,38 +1730,59 @@ class OperatorQuerySearch implements SearchInterface $this->collector->setMetaDateRange($value, $value, $field); $this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); break; + case 'exact_not': + Log::debug(sprintf('Set NOT %s_is_exact value "%s"', $field, $value->format('Y-m-d'))); + $this->collector->excludeMetaDateRange($value, $value, $field); + $this->operators->push(['type' => sprintf('not_%s_on', $field), 'value' => $value->format('Y-m-d'),]); + break; case 'year': Log::debug(sprintf('Set %s_is_exact YEAR value "%s"', $field, $value)); $this->collector->metaYearIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_year', $field), 'value' => $value,]); break; + case 'year_not': + Log::debug(sprintf('Set NOT %s_is_exact YEAR value "%s"', $field, $value)); + $this->collector->metaYearIsNot($value, $field); + $this->operators->push(['type' => sprintf('not_%s_on_year', $field), 'value' => $value,]); + break; case 'month': Log::debug(sprintf('Set %s_is_exact MONTH value "%s"', $field, $value)); $this->collector->metaMonthIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_month', $field), 'value' => $value,]); break; + case 'month_not': + Log::debug(sprintf('Set NOT %s_is_exact MONTH value "%s"', $field, $value)); + $this->collector->metaMonthIsNot($value, $field); + $this->operators->push(['type' => sprintf('not_%s_on_month', $field), 'value' => $value,]); + break; case 'day': Log::debug(sprintf('Set %s_is_exact DAY value "%s"', $field, $value)); $this->collector->metaDayIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]); break; + case 'day_not': + Log::debug(sprintf('Set NOT %s_is_exact DAY value "%s"', $field, $value)); + $this->collector->metaDayIsNot($value, $field); + $this->operators->push(['type' => sprintf('not_%s_on_day', $field), 'value' => $value,]); + break; } } } /** - * @param string $field - * @param array $range + * @param string $field + * @param array $range * @return void * @throws FireflyException */ - private function setMetaDateBeforeParams(string $field, array $range): void + private function setMetaDateBeforeParams(string $field, array $range, bool $prohibited = false): void { /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setMetaDateBeforeParams()', $key)); @@ -1283,18 +1810,19 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param string $field - * @param array $range + * @param string $field + * @param array $range * @return void * @throws FireflyException */ - private function setMetaDateAfterParams(string $field, array $range): void + private function setMetaDateAfterParams(string $field, array $range, bool $prohibited = false): void { /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setMetaDateAfterParams()', $key)); @@ -1322,18 +1850,19 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param string $field - * @param array $range + * @param string $field + * @param array $range * @return void * @throws FireflyException */ - private function setExactObjectDateParams(string $field, array $range): void + private function setExactObjectDateParams(string $field, array $range, bool $prohibited = false): void { /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setExactObjectDateParams()', $key)); @@ -1342,38 +1871,59 @@ class OperatorQuerySearch implements SearchInterface $this->collector->setObjectRange($value, clone $value, $field); $this->operators->push(['type' => sprintf('%s_on', $field), 'value' => $value->format('Y-m-d'),]); break; + case 'exact_not': + Log::debug(sprintf('Set NOT %s_is_exact value "%s"', $field, $value->format('Y-m-d'))); + $this->collector->excludeObjectRange($value, clone $value, $field); + $this->operators->push(['type' => sprintf('not_%s_on', $field), 'value' => $value->format('Y-m-d'),]); + break; case 'year': Log::debug(sprintf('Set %s_is_exact YEAR value "%s"', $field, $value)); $this->collector->objectYearIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_year', $field), 'value' => $value,]); break; + case 'year_not': + Log::debug(sprintf('Set NOT %s_is_exact YEAR value "%s"', $field, $value)); + $this->collector->objectYearIsNot($value, $field); + $this->operators->push(['type' => sprintf('not_%s_on_year', $field), 'value' => $value,]); + break; case 'month': Log::debug(sprintf('Set %s_is_exact MONTH value "%s"', $field, $value)); $this->collector->objectMonthIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_month', $field), 'value' => $value,]); break; + case 'month_not': + Log::debug(sprintf('Set NOT %s_is_exact MONTH value "%s"', $field, $value)); + $this->collector->objectMonthIsNot($value, $field); + $this->operators->push(['type' => sprintf('not_%s_on_month', $field), 'value' => $value,]); + break; case 'day': Log::debug(sprintf('Set %s_is_exact DAY value "%s"', $field, $value)); $this->collector->objectDayIs($value, $field); $this->operators->push(['type' => sprintf('%s_on_day', $field), 'value' => $value,]); break; + case 'day_not': + Log::debug(sprintf('Set NOT %s_is_exact DAY value "%s"', $field, $value)); + $this->collector->objectDayIsNot($value, $field); + $this->operators->push(['type' => sprintf('not_%s_on_day', $field), 'value' => $value,]); + break; } } } /** - * @param string $field - * @param array $range + * @param string $field + * @param array $range * * @throws FireflyException */ - private function setObjectDateBeforeParams(string $field, array $range) + private function setObjectDateBeforeParams(string $field, array $range, bool $prohibited = false): void { /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setObjectDateBeforeParams()', $key)); @@ -1401,18 +1951,19 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param string $field - * @param array $range + * @param string $field + * @param array $range * * @throws FireflyException */ - private function setObjectDateAfterParams(string $field, array $range) + private function setObjectDateAfterParams(string $field, array $range, bool $prohibited = false): void { /** - * @var string $key + * @var string $key * @var Carbon|string $value */ foreach ($range as $key => $value) { + $key = $prohibited ? sprintf('%s_not', $key) : $key; switch ($key) { default: throw new FireflyException(sprintf('Cannot handle key "%s" in setObjectDateAfterParams()', $key)); @@ -1453,7 +2004,7 @@ class OperatorQuerySearch implements SearchInterface */ public function searchTransactions(): LengthAwarePaginator { - if (empty($this->getWords()) && empty($this->getOperators())) { + if (0 === count($this->getWords()) && 0 === count($this->getOperators())) { return new LengthAwarePaginator([], 0, 5, 1); } @@ -1469,7 +2020,7 @@ class OperatorQuerySearch implements SearchInterface } /** - * @param Carbon $date + * @param Carbon $date */ public function setDate(Carbon $date): void { @@ -1501,12 +2052,11 @@ class OperatorQuerySearch implements SearchInterface $this->collector->setUser($user); $this->collector->withAccountInformation()->withCategoryInformation()->withBudgetInformation(); - $this->setLimit((int) app('preferences')->getForUser($user, 'listPageSize', 50)->data); - + $this->setLimit((int)app('preferences')->getForUser($user, 'listPageSize', 50)->data); } /** - * @param int $limit + * @param int $limit */ public function setLimit(int $limit): void { diff --git a/app/Support/Search/SearchInterface.php b/app/Support/Search/SearchInterface.php index a50f35c833..97bca2720b 100644 --- a/app/Support/Search/SearchInterface.php +++ b/app/Support/Search/SearchInterface.php @@ -1,4 +1,5 @@ addProperty($account->id); $cache->addProperty('balance-in-range'); $cache->addProperty($currency ? $currency->id : 0); @@ -183,12 +152,12 @@ class Steam ->orderBy('transaction_journals.date', 'ASC') ->whereNull('transaction_journals.deleted_at') ->get( - [ // @phpstan-ignore-line - 'transaction_journals.date', - 'transactions.transaction_currency_id', - DB::raw('SUM(transactions.amount) AS modified'), - 'transactions.foreign_currency_id', - DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'), + [ + 'transaction_journals.date', + 'transactions.transaction_currency_id', + DB::raw('SUM(transactions.amount) AS modified'), + 'transactions.foreign_currency_id', + DB::raw('SUM(transactions.foreign_amount) AS modified_foreign'), ] ); @@ -228,12 +197,11 @@ class Steam * * @return string * @throws FireflyException - * @throws JsonException */ public function balance(Account $account, Carbon $date, ?TransactionCurrency $currency = null): string { // abuse chart properties: - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($account->id); $cache->addProperty('balance'); $cache->addProperty($date); @@ -277,13 +245,12 @@ class Steam * @param Carbon $date * * @return array - * @throws JsonException */ public function balancesByAccounts(Collection $accounts, Carbon $date): array { $ids = $accounts->pluck('id')->toArray(); // cache this property. - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($ids); $cache->addProperty('balances'); $cache->addProperty($date); @@ -316,7 +283,7 @@ class Steam { $ids = $accounts->pluck('id')->toArray(); // cache this property. - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($ids); $cache->addProperty('balances-per-currency'); $cache->addProperty($date); @@ -345,7 +312,7 @@ class Steam public function balancePerCurrency(Account $account, Carbon $date): array { // abuse chart properties: - $cache = new CacheProperties; + $cache = new CacheProperties(); $cache->addProperty($account->id); $cache->addProperty('balance-per-currency'); $cache->addProperty($date); @@ -356,7 +323,7 @@ class Steam ->leftJoin('transaction_journals', 'transaction_journals.id', '=', 'transactions.transaction_journal_id') ->where('transaction_journals.date', '<=', $date->format('Y-m-d 23:59:59')) ->groupBy('transactions.transaction_currency_id'); - $balances = $query->get(['transactions.transaction_currency_id', DB::raw('SUM(transactions.amount) as sum_for_currency')]); // @phpstan-ignore-line + $balances = $query->get(['transactions.transaction_currency_id', DB::raw('SUM(transactions.amount) as sum_for_currency')]); $return = []; /** @var stdClass $entry */ foreach ($balances as $entry) { @@ -367,6 +334,38 @@ class Steam return $return; } + /** + * https://stackoverflow.com/questions/1642614/how-to-ceil-floor-and-round-bcmath-numbers + * + * @param null|string $number + * @param int $precision + * @return string + */ + public function bcround(?string $number, int $precision = 0): string + { + if (null === $number) { + return '0'; + } + if ('' === trim($number)) { + return '0'; + } + // if the number contains "E", it's in scientific notation, so we need to convert it to a normal number first. + if (false !== stripos($number, 'e')) { + $number = sprintf('%.24f', $number); + } + + Log::debug(sprintf('Trying bcround("%s",%d)', $number, $precision)); + if (str_contains($number, '.')) { + if ($number[0] !== '-') { + return bcadd($number, '0.'.str_repeat('0', $precision).'5', $precision); + } + + return bcsub($number, '0.'.str_repeat('0', $precision).'5', $precision); + } + + return $number; + } + /** * @param string $string * @@ -423,6 +422,9 @@ class Steam "\x20", // plain old normal space ]; + // clear zalgo text + $string = preg_replace('/\pM/u', '', $string); + return str_replace($search, '', $string); } @@ -438,7 +440,7 @@ class Steam $set = auth()->user()->transactions() ->whereIn('transactions.account_id', $accounts) ->groupBy(['transactions.account_id', 'transaction_journals.user_id']) - ->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')]); // @phpstan-ignore-line + ->get(['transactions.account_id', DB::raw('MAX(transaction_journals.date) AS max_date')]); foreach ($set as $entry) { $date = new Carbon($entry->max_date, config('app.timezone')); @@ -454,8 +456,8 @@ class Steam * * @return string * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function getLocale(): string // get preference { @@ -477,8 +479,8 @@ class Steam * * @return string * @throws FireflyException - * @throws \Psr\Container\ContainerExceptionInterface - * @throws \Psr\Container\NotFoundExceptionInterface + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface */ public function getLanguage(): string // get preference { @@ -666,4 +668,19 @@ class Steam return $amount; } + + /** + * @param string $ipAddress + * @return string + * @throws FireflyException + */ + public function getHostName(string $ipAddress): string + { + try { + $hostName = gethostbyaddr($ipAddress); + } catch (Exception $e) { // intentional generic exception + throw new FireflyException($e->getMessage(), 0, $e); + } + return $hostName; + } } diff --git a/app/Support/System/GeneratesInstallationId.php b/app/Support/System/GeneratesInstallationId.php index f03dc048c5..8ac9d8dd3e 100644 --- a/app/Support/System/GeneratesInstallationId.php +++ b/app/Support/System/GeneratesInstallationId.php @@ -53,10 +53,9 @@ trait GeneratesInstallationId if (null === $config) { $uuid4 = Uuid::uuid4(); - $uniqueId = (string) $uuid4; + $uniqueId = (string)$uuid4; Log::info(sprintf('Created Firefly III installation ID %s', $uniqueId)); app('fireflyconfig')->set('installation_id', $uniqueId); } } - } diff --git a/app/Support/System/OAuthKeys.php b/app/Support/System/OAuthKeys.php index 1eff32208e..0266cb5feb 100644 --- a/app/Support/System/OAuthKeys.php +++ b/app/Support/System/OAuthKeys.php @@ -72,8 +72,8 @@ class OAuthKeys // better check if keys are in the database: if (app('fireflyconfig')->has(self::PRIVATE_KEY) && app('fireflyconfig')->has(self::PUBLIC_KEY)) { try { - $privateKey = (string) app('fireflyconfig')->get(self::PRIVATE_KEY)?->data; - $publicKey = (string) app('fireflyconfig')->get(self::PUBLIC_KEY)?->data; + $privateKey = (string)app('fireflyconfig')->get(self::PRIVATE_KEY)?->data; + $publicKey = (string)app('fireflyconfig')->get(self::PUBLIC_KEY)?->data; } catch (ContainerExceptionInterface|NotFoundExceptionInterface|FireflyException $e) { Log::error(sprintf('Could not validate keysInDatabase(): %s', $e->getMessage())); Log::error($e->getTraceAsString()); @@ -125,8 +125,8 @@ class OAuthKeys */ public static function restoreKeysFromDB(): bool { - $privateKey = (string) app('fireflyconfig')->get(self::PRIVATE_KEY)?->data; - $publicKey = (string) app('fireflyconfig')->get(self::PUBLIC_KEY)?->data; + $privateKey = (string)app('fireflyconfig')->get(self::PRIVATE_KEY)?->data; + $publicKey = (string)app('fireflyconfig')->get(self::PUBLIC_KEY)?->data; try { $privateContent = Crypt::decrypt($privateKey); $publicContent = Crypt::decrypt($publicKey); @@ -146,5 +146,4 @@ class OAuthKeys file_put_contents($public, $publicContent); return true; } - } diff --git a/app/Support/Twig/AmountFormat.php b/app/Support/Twig/AmountFormat.php index 5cc326111d..5ae6db2121 100644 --- a/app/Support/Twig/AmountFormat.php +++ b/app/Support/Twig/AmountFormat.php @@ -1,4 +1,5 @@ symbol = $symbol; $currency->decimal_places = $decimalPlaces; diff --git a/app/Support/Twig/General.php b/app/Support/Twig/General.php index e1e53b521f..670ed6b005 100644 --- a/app/Support/Twig/General.php +++ b/app/Support/Twig/General.php @@ -1,4 +1,5 @@ formatFilesize(), $this->mimeIcon(), $this->markdown(), - $this->floatval(), $this->phpHostName(), ]; } @@ -86,15 +86,15 @@ class General extends AbstractExtension static function (int $size): string { // less than one GB, more than one MB if ($size < (1024 * 1024 * 2014) && $size >= (1024 * 1024)) { - return round($size / (1024 * 1024), 2) . ' MB'; + return round($size / (1024 * 1024), 2).' MB'; } // less than one MB if ($size < (1024 * 1024)) { - return round($size / 1024, 2) . ' KB'; + return round($size / 1024, 2).' KB'; } - return $size . ' bytes'; + return $size.' bytes'; } ); } @@ -114,7 +114,7 @@ class General extends AbstractExtension return 'fa-file-o'; case 'application/pdf': return 'fa-file-pdf-o'; - /* image */ + /* image */ case 'image/png': case 'image/jpeg': case 'image/svg+xml': @@ -122,7 +122,7 @@ class General extends AbstractExtension case 'image/heic-sequence': case 'application/vnd.oasis.opendocument.image': return 'fa-file-image-o'; - /* MS word */ + /* MS word */ case 'application/msword': case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': case 'application/vnd.openxmlformats-officedocument.wordprocessingml.template': @@ -137,7 +137,7 @@ class General extends AbstractExtension case 'application/vnd.oasis.opendocument.text-web': case 'application/vnd.oasis.opendocument.text-master': return 'fa-file-word-o'; - /* MS excel */ + /* MS excel */ case 'application/vnd.ms-excel': case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': case 'application/vnd.openxmlformats-officedocument.spreadsheetml.template': @@ -147,7 +147,7 @@ class General extends AbstractExtension case 'application/vnd.oasis.opendocument.spreadsheet': case 'application/vnd.oasis.opendocument.spreadsheet-template': return 'fa-file-excel-o'; - /* MS powerpoint */ + /* MS powerpoint */ case 'application/vnd.ms-powerpoint': case 'application/vnd.openxmlformats-officedocument.presentationml.presentation': case 'application/vnd.openxmlformats-officedocument.presentationml.template': @@ -158,7 +158,7 @@ class General extends AbstractExtension case 'application/vnd.oasis.opendocument.presentation': case 'application/vnd.oasis.opendocument.presentation-template': return 'fa-file-powerpoint-o'; - /* calc */ + /* calc */ case 'application/vnd.sun.xml.draw': case 'application/vnd.sun.xml.draw.template': case 'application/vnd.stardivision.draw': @@ -171,7 +171,6 @@ class General extends AbstractExtension case 'application/vnd.oasis.opendocument.formula': case 'application/vnd.oasis.opendocument.database': return 'fa-calculator'; - } }, ['is_safe' => ['html']] @@ -184,9 +183,8 @@ class General extends AbstractExtension protected function markdown(): TwigFilter { return new TwigFilter( - 'markdown', + 'markdown', static function (string $text): string { - $converter = new GithubFlavoredMarkdownConverter( [ 'allow_unsafe_links' => false, @@ -195,21 +193,9 @@ class General extends AbstractExtension ] ); - return (string) $converter->convert($text); - }, ['is_safe' => ['html']] - ); - } - - /** - * @return TwigFilter - */ - protected function floatval(): TwigFilter - { - return new TwigFilter( - 'floatval', - static function ($value): float { - return (float) $value; - } + return (string)$converter->convert($text); + }, + ['is_safe' => ['html']] ); } @@ -223,8 +209,8 @@ class General extends AbstractExtension return new TwigFilter( 'phphost', static function (string $string): string { - $proto = (string) parse_url($string, PHP_URL_SCHEME); - $host = (string) parse_url($string, PHP_URL_HOST); + $proto = (string)parse_url($string, PHP_URL_SCHEME); + $host = (string)parse_url($string, PHP_URL_HOST); return e(sprintf('%s://%s', $proto, $host)); } @@ -377,7 +363,7 @@ class General extends AbstractExtension /** * @return TwigFunction - * See reference nr. 43 + * TODO remove me when layout v1 is deprecated. */ protected function getMetaField(): TwigFunction { @@ -421,7 +407,8 @@ class General extends AbstractExtension return new TwigFunction( 'getRootSearchOperator', static function (string $operator): string { - return OperatorQuerySearch::getRootOperator($operator); + $result = OperatorQuerySearch::getRootOperator($operator); + return str_replace('-', 'not_', $result); } ); } diff --git a/app/Support/Twig/Rule.php b/app/Support/Twig/Rule.php index 564547b325..924cd5157d 100644 --- a/app/Support/Twig/Rule.php +++ b/app/Support/Twig/Rule.php @@ -1,4 +1,5 @@ (string) trans('firefly.rule_trigger_store_journal'), - 'update-journal' => (string) trans('firefly.rule_trigger_update_journal'), + 'store-journal' => (string)trans('firefly.rule_trigger_store_journal'), + 'update-journal' => (string)trans('firefly.rule_trigger_update_journal'), ]; } ); @@ -71,7 +72,7 @@ class Rule extends AbstractExtension $possibleTriggers = []; foreach ($ruleTriggers as $key) { if ('user_action' !== $key) { - $possibleTriggers[$key] = (string) trans('firefly.rule_trigger_' . $key . '_choice'); + $possibleTriggers[$key] = (string)trans('firefly.rule_trigger_'.$key.'_choice'); } } unset($ruleTriggers); @@ -94,7 +95,7 @@ class Rule extends AbstractExtension $ruleActions = array_keys(Config::get('firefly.rule-actions')); $possibleActions = []; foreach ($ruleActions as $key) { - $possibleActions[$key] = (string) trans('firefly.rule_action_' . $key . '_choice'); + $possibleActions[$key] = (string)trans('firefly.rule_action_'.$key.'_choice'); } unset($ruleActions); asort($possibleActions); diff --git a/app/Support/Twig/TransactionGroupTwig.php b/app/Support/Twig/TransactionGroupTwig.php index 83f6051eca..409f3b21d9 100644 --- a/app/Support/Twig/TransactionGroupTwig.php +++ b/app/Support/Twig/TransactionGroupTwig.php @@ -37,7 +37,6 @@ use Twig\TwigFunction; */ class TransactionGroupTwig extends AbstractExtension { - /** @noinspection PhpMissingParentCallCommonInspection */ /** * @return array * @@ -80,7 +79,7 @@ class TransactionGroupTwig extends AbstractExtension /** * Generate normal amount for transaction from a transaction group. * - * @param array $array + * @param array $array * * @return string */ @@ -96,7 +95,7 @@ class TransactionGroupTwig extends AbstractExtension $colored = false; } - $result = app('amount')->formatFlat($array['currency_symbol'], (int) $array['currency_decimal_places'], $amount, $colored); + $result = app('amount')->formatFlat($array['currency_symbol'], (int)$array['currency_decimal_places'], $amount, $colored); if ($type === TransactionType::TRANSFER) { $result = sprintf('%s', $result); } @@ -105,15 +104,14 @@ class TransactionGroupTwig extends AbstractExtension } /** - * @param string $amount - * @param string $transactionType - * @param string $sourceType + * @param string $amount + * @param string $transactionType + * @param string $sourceType * * @return string */ private function signAmount(string $amount, string $transactionType, string $sourceType): string { - // withdrawals stay negative if ($transactionType !== TransactionType::WITHDRAWAL) { $amount = bcmul($amount, '-1'); @@ -135,7 +133,7 @@ class TransactionGroupTwig extends AbstractExtension /** * Generate foreign amount for transaction from a transaction group. * - * @param array $array + * @param array $array * * @return string */ @@ -151,7 +149,7 @@ class TransactionGroupTwig extends AbstractExtension if ($type === TransactionType::TRANSFER) { $colored = false; } - $result = app('amount')->formatFlat($array['foreign_currency_symbol'], (int) $array['foreign_currency_decimal_places'], $amount, $colored); + $result = app('amount')->formatFlat($array['foreign_currency_symbol'], (int)$array['foreign_currency_decimal_places'], $amount, $colored); if ($type === TransactionType::TRANSFER) { $result = sprintf('%s', $result); } @@ -185,7 +183,7 @@ class TransactionGroupTwig extends AbstractExtension /** * Generate normal amount for transaction from a transaction group. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return string */ @@ -203,7 +201,7 @@ class TransactionGroupTwig extends AbstractExtension if ($type === TransactionType::TRANSFER) { $colored = false; } - $result = app('amount')->formatFlat($currency->symbol, (int) $currency->decimal_places, $amount, $colored); + $result = app('amount')->formatFlat($currency->symbol, (int)$currency->decimal_places, $amount, $colored); if ($type === TransactionType::TRANSFER) { $result = sprintf('%s', $result); } @@ -212,7 +210,7 @@ class TransactionGroupTwig extends AbstractExtension } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return bool */ @@ -227,7 +225,7 @@ class TransactionGroupTwig extends AbstractExtension /** * Generate foreign amount for journal from a transaction group. * - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return string */ @@ -246,7 +244,7 @@ class TransactionGroupTwig extends AbstractExtension if ($type === TransactionType::TRANSFER) { $colored = false; } - $result = app('amount')->formatFlat($currency->symbol, (int) $currency->decimal_places, $amount, $colored); + $result = app('amount')->formatFlat($currency->symbol, (int)$currency->decimal_places, $amount, $colored); if ($type === TransactionType::TRANSFER) { $result = sprintf('%s', $result); } diff --git a/app/Support/Twig/Translation.php b/app/Support/Twig/Translation.php index 752fd27c79..11b420f0be 100644 --- a/app/Support/Twig/Translation.php +++ b/app/Support/Twig/Translation.php @@ -1,4 +1,5 @@ ['html']] ), diff --git a/app/TransactionRules/Actions/ActionInterface.php b/app/TransactionRules/Actions/ActionInterface.php index 0686714f3e..4dd7e1161f 100644 --- a/app/TransactionRules/Actions/ActionInterface.php +++ b/app/TransactionRules/Actions/ActionInterface.php @@ -1,4 +1,5 @@ insert(['tag_id' => $tag->id, 'transaction_journal_id' => $journal['transaction_journal_id']]); Log::debug(sprintf('RuleAction AddTag. Added tag #%d ("%s") to journal %d.', $tag->id, $tag->tag, $journal['transaction_journal_id'])); + $object = TransactionJournal::find($journal['transaction_journal_id']); + + // event for audit log entry + event(new TriggeredAuditLog($this->action->rule, $object, 'add_tag', null, $tag->tag)); return true; } diff --git a/app/TransactionRules/Actions/AppendDescription.php b/app/TransactionRules/Actions/AppendDescription.php index c7f275ebf1..0b24f8e4af 100644 --- a/app/TransactionRules/Actions/AppendDescription.php +++ b/app/TransactionRules/Actions/AppendDescription.php @@ -1,4 +1,5 @@ action->action_value); DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]); + // event for audit log entry + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_description', $journal['description'], $description)); + return true; } } diff --git a/app/TransactionRules/Actions/AppendDescriptionToNotes.php b/app/TransactionRules/Actions/AppendDescriptionToNotes.php new file mode 100644 index 0000000000..7c887557f5 --- /dev/null +++ b/app/TransactionRules/Actions/AppendDescriptionToNotes.php @@ -0,0 +1,79 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Actions; + +use FireflyIII\Events\TriggeredAuditLog; +use FireflyIII\Models\Note; +use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; +use Illuminate\Support\Facades\Log; + +class AppendDescriptionToNotes implements ActionInterface +{ + private RuleAction $action; + + /** + * TriggerInterface constructor. + * + * @param RuleAction $action + */ + public function __construct(RuleAction $action) + { + $this->action = $action; + } + + /** + * @inheritDoc + */ + public function actOnArray(array $journal): bool + { + /** @var TransactionJournal $journal */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + if (null === $object) { + Log::error(sprintf('No journal #%d belongs to user #%d.', $journal['transaction_journal_id'], $journal['user_id'])); + return false; + } + $note = $object->notes()->first(); + if (null === $note) { + $note = new Note(); + $note->noteable()->associate($object); + $note->text = ''; + } + $before = $note->text; + if ('' !== $note->text) { + $note->text = trim(sprintf("%s \n%s", $note->text, $object->description)); + } + if ('' === $note->text) { + $note->text = (string)$object->description; + } + $after = $note->text; + + // event for audit log entry + event(new TriggeredAuditLog($this->action->rule, $object, 'update_notes', $before, $after)); + + $note->save(); + return true; + } +} diff --git a/app/TransactionRules/Actions/AppendNotes.php b/app/TransactionRules/Actions/AppendNotes.php index 62350cbd44..f55d6dc358 100644 --- a/app/TransactionRules/Actions/AppendNotes.php +++ b/app/TransactionRules/Actions/AppendNotes.php @@ -1,4 +1,5 @@ where('noteable_type', TransactionJournal::class) - ->first(['notes.*']); + $dbNote = Note::where('noteable_id', (int)$journal['transaction_journal_id']) + ->where('noteable_type', TransactionJournal::class) + ->first(['notes.*']); if (null === $dbNote) { - $dbNote = new Note; - $dbNote->noteable_id = (int) $journal['transaction_journal_id']; + $dbNote = new Note(); + $dbNote->noteable_id = (int)$journal['transaction_journal_id']; $dbNote->noteable_type = TransactionJournal::class; $dbNote->text = ''; } Log::debug(sprintf('RuleAction AppendNotes appended "%s" to "%s".', $this->action->action_value, $dbNote->text)); + $before = $dbNote->text; $text = sprintf('%s%s', $dbNote->text, $this->action->action_value); $dbNote->text = $text; $dbNote->save(); + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + + event(new TriggeredAuditLog($this->action->rule, $object, 'update_notes', $before, $text)); + return true; } } diff --git a/app/TransactionRules/Actions/AppendNotesToDescription.php b/app/TransactionRules/Actions/AppendNotesToDescription.php new file mode 100644 index 0000000000..387c1e87b2 --- /dev/null +++ b/app/TransactionRules/Actions/AppendNotesToDescription.php @@ -0,0 +1,101 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Actions; + +use FireflyIII\Events\TriggeredAuditLog; +use FireflyIII\Models\Note; +use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Support\Facades\Log; + +/** + * Class AppendNotesToDescription + */ +class AppendNotesToDescription implements ActionInterface +{ + use ConvertsDataTypes; + + private RuleAction $action; + + /** + * TriggerInterface constructor. + * + * @param RuleAction $action + */ + public function __construct(RuleAction $action) + { + $this->action = $action; + } + + /** + * @inheritDoc + */ + public function actOnArray(array $journal): bool + { + Log::debug('Now in AppendNotesToDescription'); + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + if (null === $object) { + Log::error(sprintf('No journal #%d belongs to user #%d.', $journal['transaction_journal_id'], $journal['user_id'])); + return false; + } + $note = $object->notes()->first(); + if (null === $note) { + Log::debug('Journal has no notes.'); + $note = new Note(); + $note->noteable()->associate($object); + $note->text = ''; + } + // only append if there is something to append + if ('' !== $note->text) { + $before = $object->description; + $object->description = trim(sprintf("%s %s", $object->description, (string)$this->clearString($note->text, false))); + $object->save(); + Log::debug(sprintf('Journal description is updated to "%s".', $object->description)); + + event(new TriggeredAuditLog($this->action->rule, $object, 'update_description', $before, $object->description)); + + return true; + } + return false; + } + + /** + * @inheritDoc + */ + public function get(string $key, mixed $default = null): mixed + { + return null; + } + + /** + * @inheritDoc + */ + public function has(mixed $key): mixed + { + return null; + } +} diff --git a/app/TransactionRules/Actions/ClearBudget.php b/app/TransactionRules/Actions/ClearBudget.php index c13996bbcd..2bef3a4fe4 100644 --- a/app/TransactionRules/Actions/ClearBudget.php +++ b/app/TransactionRules/Actions/ClearBudget.php @@ -1,4 +1,5 @@ action = $action; + } + /** * @inheritDoc */ public function actOnArray(array $journal): bool { + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + $budget = $object->budgets()->first(); + if (null === $budget) { + Log::debug(sprintf('RuleAction ClearBudget, no budget in journal #%d.', $journal['transaction_journal_id'])); + return false; + } + DB::table('budget_transaction_journal')->where('transaction_journal_id', '=', $journal['transaction_journal_id'])->delete(); - Log::debug(sprintf('RuleAction ClearBudget removed all budgets from journal %d.', $journal['transaction_journal_id'])); + event(new TriggeredAuditLog($this->action->rule, $object, 'clear_budget', $budget->name, null)); + + Log::debug(sprintf('RuleAction ClearBudget removed all budgets from journal #%d.', $journal['transaction_journal_id'])); return true; } diff --git a/app/TransactionRules/Actions/ClearCategory.php b/app/TransactionRules/Actions/ClearCategory.php index d32dc222db..43874d063c 100644 --- a/app/TransactionRules/Actions/ClearCategory.php +++ b/app/TransactionRules/Actions/ClearCategory.php @@ -1,4 +1,5 @@ action = $action; + } + /** * @inheritDoc */ public function actOnArray(array $journal): bool { + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + $category = $object->categories()->first(); + if (null === $category) { + Log::debug(sprintf('RuleAction ClearCategory, no category in journal #%d.', $journal['transaction_journal_id'])); + return false; + } + DB::table('category_transaction_journal')->where('transaction_journal_id', '=', $journal['transaction_journal_id'])->delete(); - Log::debug(sprintf('RuleAction ClearCategory removed all categories from journal %d.', $journal['transaction_journal_id'])); + event(new TriggeredAuditLog($this->action->rule, $object, 'clear_category', $category->name, null)); + + Log::debug(sprintf('RuleAction ClearCategory removed all categories from journal #%d.', $journal['transaction_journal_id'])); return true; } diff --git a/app/TransactionRules/Actions/ClearNotes.php b/app/TransactionRules/Actions/ClearNotes.php index d30466cd61..e14fe32b95 100644 --- a/app/TransactionRules/Actions/ClearNotes.php +++ b/app/TransactionRules/Actions/ClearNotes.php @@ -1,4 +1,5 @@ action = $action; + } + /** * @inheritDoc */ public function actOnArray(array $journal): bool { + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + $notes = $object->notes()->first(); + if (null === $notes) { + Log::debug(sprintf('RuleAction ClearNotes, journal #%d has no notes.', $journal['transaction_journal_id'])); + return false; + } + $before = $notes->text; + DB::table('notes') ->where('noteable_id', $journal['transaction_journal_id']) ->where('noteable_type', TransactionJournal::class) ->delete(); - Log::debug('RuleAction ClearNotes removed all notes.'); + Log::debug(sprintf('RuleAction ClearNotes removed all notes from journal #%d.', $journal['transaction_journal_id'])); + + event(new TriggeredAuditLog($this->action->rule, $object, 'clear_notes', $before, null)); return true; } diff --git a/app/TransactionRules/Actions/ConvertToDeposit.php b/app/TransactionRules/Actions/ConvertToDeposit.php index 8ff79f0e79..ce9a74a7f8 100644 --- a/app/TransactionRules/Actions/ConvertToDeposit.php +++ b/app/TransactionRules/Actions/ConvertToDeposit.php @@ -24,10 +24,12 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\AccountFactory; use FireflyIII\Models\AccountType; use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\User; use Log; @@ -43,7 +45,7 @@ class ConvertToDeposit implements ActionInterface /** * TriggerInterface constructor. * - * @param RuleAction $action + * @param RuleAction $action */ public function __construct(RuleAction $action) { @@ -56,6 +58,12 @@ class ConvertToDeposit implements ActionInterface */ public function actOnArray(array $journal): bool { + $groupCount = TransactionJournal::where('transaction_group_id', $journal['transaction_group_id'])->count(); + if ($groupCount > 1) { + Log::error(sprintf('Group #%d has more than one transaction in it, cannot convert to deposit.', $journal['transaction_group_id'])); + return false; + } + Log::debug(sprintf('Convert journal #%d to deposit.', $journal['transaction_journal_id'])); $type = $journal['transaction_type_type']; if (TransactionType::DEPOSIT === $type) { @@ -66,10 +74,14 @@ class ConvertToDeposit implements ActionInterface if (TransactionType::WITHDRAWAL === $type) { Log::debug('Going to transform a withdrawal to a deposit.'); + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::WITHDRAWAL, TransactionType::DEPOSIT)); return $this->convertWithdrawalArray($journal); } if (TransactionType::TRANSFER === $type) { + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::TRANSFER, TransactionType::DEPOSIT)); Log::debug('Going to transform a transfer to a deposit.'); return $this->convertTransferArray($journal); @@ -82,7 +94,7 @@ class ConvertToDeposit implements ActionInterface * Input is a withdrawal from A to B * Is converted to a deposit from C to A. * - * @param array $journal + * @param array $journal * * @return bool * @throws FireflyException @@ -130,7 +142,7 @@ class ConvertToDeposit implements ActionInterface * Input is a transfer from A to B. * Output is a deposit from C to B. * - * @param array $journal + * @param array $journal * * @return bool * @throws FireflyException diff --git a/app/TransactionRules/Actions/ConvertToTransfer.php b/app/TransactionRules/Actions/ConvertToTransfer.php index c0e30816bc..067a622735 100644 --- a/app/TransactionRules/Actions/ConvertToTransfer.php +++ b/app/TransactionRules/Actions/ConvertToTransfer.php @@ -24,9 +24,11 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\User; @@ -43,7 +45,7 @@ class ConvertToTransfer implements ActionInterface /** * TriggerInterface constructor. * - * @param RuleAction $action + * @param RuleAction $action */ public function __construct(RuleAction $action) { @@ -55,6 +57,13 @@ class ConvertToTransfer implements ActionInterface */ public function actOnArray(array $journal): bool { + $groupCount = TransactionJournal::where('transaction_group_id', $journal['transaction_group_id'])->count(); + if ($groupCount > 1) { + Log::error(sprintf('Group #%d has more than one transaction in it, cannot convert to transfer.', $journal['transaction_group_id'])); + return false; + } + + $type = $journal['transaction_type_type']; $user = User::find($journal['user_id']); if (TransactionType::TRANSFER === $type) { @@ -73,8 +82,10 @@ class ConvertToTransfer implements ActionInterface if (null === $asset) { Log::error( sprintf( - 'Journal #%d cannot be converted because no asset with name "%s" exists (rule #%d).', $journal['transaction_journal_id'], - $this->action->action_value, $this->action->rule_id + 'Journal #%d cannot be converted because no asset with name "%s" exists (rule #%d).', + $journal['transaction_journal_id'], + $this->action->action_value, + $this->action->rule_id ) ); @@ -82,12 +93,17 @@ class ConvertToTransfer implements ActionInterface } if (TransactionType::WITHDRAWAL === $type) { Log::debug('Going to transform a withdrawal to a transfer.'); + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::WITHDRAWAL, TransactionType::TRANSFER)); return $this->convertWithdrawalArray($journal, $asset); } if (TransactionType::DEPOSIT === $type) { Log::debug('Going to transform a deposit to a transfer.'); + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::TRANSFER)); + return $this->convertDepositArray($journal, $asset); } @@ -98,8 +114,8 @@ class ConvertToTransfer implements ActionInterface * A withdrawal is from Asset to Expense. * We replace the Expense with another asset. * - * @param array $journal - * @param Account $asset + * @param array $journal + * @param Account $asset * * @return bool */ @@ -138,8 +154,8 @@ class ConvertToTransfer implements ActionInterface * A deposit is from Revenue to Asset. * We replace the Revenue with another asset. * - * @param array $journal - * @param Account $asset + * @param array $journal + * @param Account $asset * * @return bool */ @@ -173,5 +189,4 @@ class ConvertToTransfer implements ActionInterface return true; } - } diff --git a/app/TransactionRules/Actions/ConvertToWithdrawal.php b/app/TransactionRules/Actions/ConvertToWithdrawal.php index ea9faf6ec4..447682cfbe 100644 --- a/app/TransactionRules/Actions/ConvertToWithdrawal.php +++ b/app/TransactionRules/Actions/ConvertToWithdrawal.php @@ -24,10 +24,12 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\AccountFactory; use FireflyIII\Models\AccountType; use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\TransactionType; use FireflyIII\User; use Log; @@ -43,7 +45,7 @@ class ConvertToWithdrawal implements ActionInterface /** * TriggerInterface constructor. * - * @param RuleAction $action + * @param RuleAction $action */ public function __construct(RuleAction $action) { @@ -55,6 +57,12 @@ class ConvertToWithdrawal implements ActionInterface */ public function actOnArray(array $journal): bool { + $groupCount = TransactionJournal::where('transaction_group_id', $journal['transaction_group_id'])->count(); + if ($groupCount > 1) { + Log::error(sprintf('Group #%d has more than one transaction in it, cannot convert to withdrawal.', $journal['transaction_group_id'])); + return false; + } + $type = $journal['transaction_type_type']; if (TransactionType::WITHDRAWAL === $type) { Log::error(sprintf('Journal #%d is already a withdrawal (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id)); @@ -64,11 +72,15 @@ class ConvertToWithdrawal implements ActionInterface if (TransactionType::DEPOSIT === $type) { Log::debug('Going to transform a deposit to a withdrawal.'); + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::WITHDRAWAL)); return $this->convertDepositArray($journal); } if (TransactionType::TRANSFER === $type) { Log::debug('Going to transform a transfer to a withdrawal.'); + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::TRANSFER, TransactionType::WITHDRAWAL)); return $this->convertTransferArray($journal); } @@ -109,14 +121,13 @@ class ConvertToWithdrawal implements ActionInterface Log::debug('Converted deposit to withdrawal.'); return true; - } /** * Input is a transfer from A to B. * Output is a withdrawal from A to C. * - * @param array $journal + * @param array $journal * * @return bool * @throws FireflyException diff --git a/app/TransactionRules/Actions/DeleteTransaction.php b/app/TransactionRules/Actions/DeleteTransaction.php index bbd01aee3f..35be86196a 100644 --- a/app/TransactionRules/Actions/DeleteTransaction.php +++ b/app/TransactionRules/Actions/DeleteTransaction.php @@ -1,4 +1,5 @@ action = $action; + } + /** * @inheritDoc */ @@ -45,13 +60,16 @@ class DeleteTransaction implements ActionInterface Log::debug( sprintf( 'RuleAction DeleteTransaction DELETED the entire transaction group of journal #%d ("%s").', - $journal['transaction_journal_id'], $journal['description'] + $journal['transaction_journal_id'], + $journal['description'] ) ); $group = TransactionGroup::find($journal['transaction_group_id']); $service = app(TransactionGroupDestroyService::class); $service->destroy($group); + event(new TriggeredAuditLog($this->action->rule, $group, 'delete_group', null, null)); + return true; } Log::debug( @@ -59,11 +77,12 @@ class DeleteTransaction implements ActionInterface ); // trigger delete factory: - $journal = TransactionJournal::find($journal['transaction_group_id']); - if (null !== $journal) { + $object = TransactionJournal::find($journal['transaction_group_id']); + if (null !== $object) { /** @var JournalDestroyService $service */ $service = app(JournalDestroyService::class); - $service->destroy($journal); + $service->destroy($object); + event(new TriggeredAuditLog($this->action->rule, $object, 'delete_journal', null, null)); } return true; diff --git a/app/TransactionRules/Actions/LinkToBill.php b/app/TransactionRules/Actions/LinkToBill.php index 5de381a3ab..d4c7ed522c 100644 --- a/app/TransactionRules/Actions/LinkToBill.php +++ b/app/TransactionRules/Actions/LinkToBill.php @@ -1,4 +1,5 @@ setUser($user); - $billName = (string) $this->action->action_value; + $billName = (string)$this->action->action_value; $bill = $repository->findByName($billName); if (null !== $bill && $journal['transaction_type_type'] === TransactionType::WITHDRAWAL) { + $count = DB::table('transaction_journals')->where('id', '=', $journal['transaction_journal_id']) + ->where('bill_id', $bill->id)->count(); + if (0 !== $count) { + Log::error( + sprintf( + 'RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": already set.', + $journal['transaction_journal_id'], + $billName + ) + ); + return false; + } + + DB::table('transaction_journals') ->where('id', '=', $journal['transaction_journal_id']) ->update(['bill_id' => $bill->id]); @@ -69,13 +85,17 @@ class LinkToBill implements ActionInterface sprintf('RuleAction LinkToBill set the bill of journal #%d to bill #%d ("%s").', $journal['transaction_journal_id'], $bill->id, $bill->name) ); + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'set_bill', null, $bill->name)); + return true; } Log::error( sprintf( 'RuleAction LinkToBill could not set the bill of journal #%d to bill "%s": no such bill found or not a withdrawal.', - $journal['transaction_journal_id'], $billName + $journal['transaction_journal_id'], + $billName ) ); diff --git a/app/TransactionRules/Actions/MoveDescriptionToNotes.php b/app/TransactionRules/Actions/MoveDescriptionToNotes.php new file mode 100644 index 0000000000..fcab74d39b --- /dev/null +++ b/app/TransactionRules/Actions/MoveDescriptionToNotes.php @@ -0,0 +1,88 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Actions; + +use FireflyIII\Events\TriggeredAuditLog; +use FireflyIII\Models\Note; +use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; +use Illuminate\Support\Facades\Log; + +/** + * Class MoveDescriptionToNotes + */ +class MoveDescriptionToNotes implements ActionInterface +{ + private RuleAction $action; + + /** + * TriggerInterface constructor. + * + * @codeCoverageIgnore + * + * @param RuleAction $action + */ + public function __construct(RuleAction $action) + { + $this->action = $action; + } + + /** + * @inheritDoc + */ + public function actOnArray(array $journal): bool + { + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + if (null === $object) { + Log::error(sprintf('No journal #%d belongs to user #%d.', $journal['transaction_journal_id'], $journal['user_id'])); + return false; + } + $note = $object->notes()->first(); + if (null === $note) { + $note = new Note(); + $note->noteable()->associate($object); + $note->text = ''; + } + $before = $note->text; + $beforeDescription = $object->description; + if ('' !== $note->text) { + $note->text = trim(sprintf("%s \n%s", $note->text, $object->description)); + $object->description = '(no description)'; + } + if ('' === $note->text) { + $note->text = (string)$object->description; + $object->description = '(no description)'; + } + $after = $note->text; + + event(new TriggeredAuditLog($this->action->rule, $object, 'update_description', $beforeDescription, $object->description)); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_notes', $before, $after)); + + $note->save(); + $object->save(); + return true; + } +} diff --git a/app/TransactionRules/Actions/MoveNotesToDescription.php b/app/TransactionRules/Actions/MoveNotesToDescription.php new file mode 100644 index 0000000000..0410b9998b --- /dev/null +++ b/app/TransactionRules/Actions/MoveNotesToDescription.php @@ -0,0 +1,99 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\TransactionRules\Actions; + +use FireflyIII\Events\TriggeredAuditLog; +use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; +use FireflyIII\Support\Request\ConvertsDataTypes; +use Illuminate\Support\Facades\Log; + +class MoveNotesToDescription implements ActionInterface +{ + use ConvertsDataTypes; + + private RuleAction $action; + + /** + * TriggerInterface constructor. + * + * @codeCoverageIgnore + * + * @param RuleAction $action + */ + public function __construct(RuleAction $action) + { + $this->action = $action; + } + + /** + * @inheritDoc + */ + public function actOnArray(array $journal): bool + { + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + if (null === $object) { + Log::error(sprintf('No journal #%d belongs to user #%d.', $journal['transaction_journal_id'], $journal['user_id'])); + return false; + } + $note = $object->notes()->first(); + if (null === $note) { + // nothing to move, return null + return false; + } + if ('' === $note->text) { + // nothing to move, return null + $note->delete(); + return false; + } + $before = $object->description; + $beforeNote = $note->text; + $object->description = (string)$this->clearString($note->text, false); + $object->save(); + $note->delete(); + + event(new TriggeredAuditLog($this->action->rule, $object, 'update_description', $before, $object->description)); + event(new TriggeredAuditLog($this->action->rule, $object, 'clear_notes', $beforeNote, null)); + + return true; + } + + /** + * @inheritDoc + */ + public function get(string $key, mixed $default = null): mixed + { + return null; + } + + /** + * @inheritDoc + */ + public function has(mixed $key): mixed + { + return null; + } +} diff --git a/app/TransactionRules/Actions/PrependDescription.php b/app/TransactionRules/Actions/PrependDescription.php index 4640d72031..f2a12ef24b 100644 --- a/app/TransactionRules/Actions/PrependDescription.php +++ b/app/TransactionRules/Actions/PrependDescription.php @@ -1,4 +1,5 @@ action->action_value, $journal['description']); - DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $description]); + $before = $journal['description']; + $after = sprintf('%s%s', $this->action->action_value, $journal['description']); + DB::table('transaction_journals')->where('id', $journal['transaction_journal_id'])->limit(1)->update(['description' => $after]); + + // journal + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + + // audit log + event(new TriggeredAuditLog($this->action->rule, $object, 'update_description', $before, $after)); return true; } diff --git a/app/TransactionRules/Actions/PrependNotes.php b/app/TransactionRules/Actions/PrependNotes.php index 4a9f97a426..cff973022c 100644 --- a/app/TransactionRules/Actions/PrependNotes.php +++ b/app/TransactionRules/Actions/PrependNotes.php @@ -1,4 +1,5 @@ where('noteable_type', TransactionJournal::class) - ->first(['notes.*']); + $dbNote = Note::where('noteable_id', (int)$journal['transaction_journal_id']) + ->where('noteable_type', TransactionJournal::class) + ->first(['notes.*']); if (null === $dbNote) { - $dbNote = new Note; - $dbNote->noteable_id = (int) $journal['transaction_journal_id']; + $dbNote = new Note(); + $dbNote->noteable_id = (int)$journal['transaction_journal_id']; $dbNote->noteable_type = TransactionJournal::class; $dbNote->text = ''; } + $before = $dbNote->text; Log::debug(sprintf('RuleAction PrependNotes prepended "%s" to "%s".', $this->action->action_value, $dbNote->text)); $text = sprintf('%s%s', $this->action->action_value, $dbNote->text); $dbNote->text = $text; $dbNote->save(); + // journal + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + + // audit log + event(new TriggeredAuditLog($this->action->rule, $object, 'update_notes', $before, $text)); + return true; } } diff --git a/app/TransactionRules/Actions/RemoveAllTags.php b/app/TransactionRules/Actions/RemoveAllTags.php index f49ce6e34a..54c9d06e2f 100644 --- a/app/TransactionRules/Actions/RemoveAllTags.php +++ b/app/TransactionRules/Actions/RemoveAllTags.php @@ -1,4 +1,5 @@ action = $action; + } + /** * @inheritDoc */ public function actOnArray(array $journal): bool { - Log::debug(sprintf('RuleAction ClearCategory removed all tags from journal %d.', $journal['transaction_journal_id'])); DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->delete(); + $count = DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->count(); + if (0 === $count) { + Log::debug(sprintf('RuleAction RemoveAllTags, journal #%d has no tags.', $journal['transaction_journal_id'])); + return false; + } + Log::debug(sprintf('RuleAction RemoveAllTags removed all tags from journal %d.', $journal['transaction_journal_id'])); + + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + + // audit log + event(new TriggeredAuditLog($this->action->rule, $object, 'clear_all_tags', null, null)); return true; } - } diff --git a/app/TransactionRules/Actions/RemoveTag.php b/app/TransactionRules/Actions/RemoveTag.php index f8bd4671e8..f2b14aa109 100644 --- a/app/TransactionRules/Actions/RemoveTag.php +++ b/app/TransactionRules/Actions/RemoveTag.php @@ -1,4 +1,5 @@ tags()->where('tag', $name)->first(); - if (null !== $tag) { - Log::debug(sprintf('RuleAction RemoveTag removed tag #%d ("%s") from journal #%d.', $tag->id, $tag->tag, $journal['transaction_journal_id'])); - DB::table('tag_transaction_journal') - ->where('transaction_journal_id', $journal['transaction_journal_id']) - ->where('tag_id', $tag->id) - ->delete(); - - return true; + if (null === $tag) { + Log::debug( + sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag exists.', $name, $journal['transaction_journal_id']) + ); + return false; } - Log::debug( - sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag exists.', $name, $journal['transaction_journal_id']) - ); + $count = DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->where('tag_id', $tag->id)->count(); + if (0 === $count) { + Log::debug( + sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag is linked.', $name, $journal['transaction_journal_id']) + ); + return false; + } + + Log::debug(sprintf('RuleAction RemoveTag removed tag #%d ("%s") from journal #%d.', $tag->id, $tag->tag, $journal['transaction_journal_id'])); + DB::table('tag_transaction_journal') + ->where('transaction_journal_id', $journal['transaction_journal_id']) + ->where('tag_id', $tag->id) + ->delete(); + + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'clear_tag', $tag->tag, null)); return true; } diff --git a/app/TransactionRules/Actions/SetBudget.php b/app/TransactionRules/Actions/SetBudget.php index 2e149065dd..35714bd276 100644 --- a/app/TransactionRules/Actions/SetBudget.php +++ b/app/TransactionRules/Actions/SetBudget.php @@ -1,4 +1,5 @@ where('transaction_journal_id', '=', $journal['transaction_journal_id'])->delete(); DB::table('budget_transaction_journal')->insert(['transaction_journal_id' => $journal['transaction_journal_id'], 'budget_id' => $budget->id]); + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'set_budget', null, $budget->name)); + return true; } } diff --git a/app/TransactionRules/Actions/SetCategory.php b/app/TransactionRules/Actions/SetCategory.php index 118d5186b7..ed4cdc34c6 100644 --- a/app/TransactionRules/Actions/SetCategory.php +++ b/app/TransactionRules/Actions/SetCategory.php @@ -1,4 +1,5 @@ id, + 'RuleAction SetCategory set the category of journal #%d to category #%d ("%s").', + $journal['transaction_journal_id'], + $category->id, $category->name ) ); @@ -83,6 +89,10 @@ class SetCategory implements ActionInterface DB::table('category_transaction_journal')->where('transaction_journal_id', '=', $journal['transaction_journal_id'])->delete(); DB::table('category_transaction_journal')->insert(['transaction_journal_id' => $journal['transaction_journal_id'], 'category_id' => $category->id]); + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + event(new TriggeredAuditLog($this->action->rule, $object, 'set_category', null, $category->name)); + return true; } } diff --git a/app/TransactionRules/Actions/SetDescription.php b/app/TransactionRules/Actions/SetDescription.php index fc28d0725b..17eaedce95 100644 --- a/app/TransactionRules/Actions/SetDescription.php +++ b/app/TransactionRules/Actions/SetDescription.php @@ -1,4 +1,5 @@ find($journal['transaction_journal_id']); + $before = $object->description; + DB::table('transaction_journals') ->where('id', '=', $journal['transaction_journal_id']) ->update(['description' => $this->action->action_value]); @@ -60,6 +67,8 @@ class SetDescription implements ActionInterface $this->action->action_value ) ); + $object->refresh(); + event(new TriggeredAuditLog($this->action->rule, $object, 'update_description', $before, $this->action->action_value)); return true; } diff --git a/app/TransactionRules/Actions/SetDestinationAccount.php b/app/TransactionRules/Actions/SetDestinationAccount.php index 4f70ed6e36..0bf9b4f187 100644 --- a/app/TransactionRules/Actions/SetDestinationAccount.php +++ b/app/TransactionRules/Actions/SetDestinationAccount.php @@ -1,4 +1,5 @@ transactionJournals()->find((int) $journal['transaction_journal_id']); + $object = $user->transactionJournals()->find((int)$journal['transaction_journal_id']); $this->repository = app(AccountRepositoryInterface::class); if (null === $object) { @@ -74,7 +76,9 @@ class SetDestinationAccount implements ActionInterface if ((TransactionType::DEPOSIT === $type || TransactionType::TRANSFER === $type) && null === $newAccount) { Log::error( sprintf( - 'Cant change destination account of journal #%d because no asset account with name "%s" exists.', $object->id, $this->action->action_value + 'Cant change destination account of journal #%d because no asset account with name "%s" exists.', + $object->id, + $this->action->action_value ) ); @@ -89,16 +93,17 @@ class SetDestinationAccount implements ActionInterface return false; } - // account must not be deleted (in the mean time): + // account must not be deleted (in the meantime): if (null === $source->account) { Log::error('Could not find source transaction account.'); return false; } - if (null !== $newAccount && (int) $newAccount->id === (int) $source->account_id) { + if (null !== $newAccount && (int)$newAccount->id === (int)$source->account_id) { Log::error( sprintf( - 'New destination account ID #%d and current source account ID #%d are the same. Do nothing.', $newAccount->id, + 'New destination account ID #%d and current source account ID #%d are the same. Do nothing.', + $newAccount->id, $source->account_id ) ); @@ -114,6 +119,8 @@ class SetDestinationAccount implements ActionInterface Log::debug(sprintf('New destination account is #%d ("%s").', $newAccount->id, $newAccount->name)); + event(new TriggeredAuditLog($this->action->rule, $object, 'set_destination', null, $newAccount->name)); + // update destination transaction with new destination account: DB::table('transactions') ->where('transaction_journal_id', '=', $object->id) @@ -123,12 +130,10 @@ class SetDestinationAccount implements ActionInterface Log::debug(sprintf('Updated journal #%d (group #%d) and gave it new destination account ID.', $object->id, $object->transaction_group_id)); return true; - - } /** - * @param string $type + * @param string $type * * @return Account|null */ @@ -164,6 +169,4 @@ class SetDestinationAccount implements ActionInterface return $account; } - - } diff --git a/app/TransactionRules/Actions/SetNotes.php b/app/TransactionRules/Actions/SetNotes.php index 4bf792e0bb..0979fd8e48 100644 --- a/app/TransactionRules/Actions/SetNotes.php +++ b/app/TransactionRules/Actions/SetNotes.php @@ -1,4 +1,5 @@ where('noteable_type', TransactionJournal::class)->first(); if (null === $dbNote) { - $dbNote = new Note; + $dbNote = new Note(); $dbNote->noteable_id = $journal['transaction_journal_id']; $dbNote->noteable_type = TransactionJournal::class; $dbNote->text = ''; @@ -63,11 +65,18 @@ class SetNotes implements ActionInterface Log::debug( sprintf( - 'RuleAction SetNotes changed the notes of journal #%d from "%s" to "%s".', $journal['transaction_journal_id'], $oldNotes, + 'RuleAction SetNotes changed the notes of journal #%d from "%s" to "%s".', + $journal['transaction_journal_id'], + $oldNotes, $this->action->action_value ) ); + /** @var TransactionJournal $object */ + $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); + + event(new TriggeredAuditLog($this->action->rule, $object, 'update_notes', $oldNotes, $this->action->action_value)); + return true; } } diff --git a/app/TransactionRules/Actions/SetSourceAccount.php b/app/TransactionRules/Actions/SetSourceAccount.php index 21d4b60561..f79650e8ea 100644 --- a/app/TransactionRules/Actions/SetSourceAccount.php +++ b/app/TransactionRules/Actions/SetSourceAccount.php @@ -1,4 +1,5 @@ transactionJournals()->find((int) $journal['transaction_journal_id']); + $object = $user->transactionJournals()->find((int)$journal['transaction_journal_id']); $this->repository = app(AccountRepositoryInterface::class); if (null === $object) { Log::error('Could not find journal.'); @@ -86,16 +88,17 @@ class SetSourceAccount implements ActionInterface return false; } - // account must not be deleted (in the mean time): + // account must not be deleted (in the meantime): if (null === $destination->account) { Log::error('Could not find destination transaction account.'); return false; } - if (null !== $newAccount && (int) $newAccount->id === (int) $destination->account_id) { + if (null !== $newAccount && (int)$newAccount->id === (int)$destination->account_id) { Log::error( sprintf( - 'New source account ID #%d and current destination account ID #%d are the same. Do nothing.', $newAccount->id, + 'New source account ID #%d and current destination account ID #%d are the same. Do nothing.', + $newAccount->id, $destination->account_id ) ); @@ -117,13 +120,15 @@ class SetSourceAccount implements ActionInterface ->where('amount', '<', 0) ->update(['account_id' => $newAccount->id]); + event(new TriggeredAuditLog($this->action->rule, $object, 'set_source', null, $newAccount->name)); + Log::debug(sprintf('Updated journal #%d (group #%d) and gave it new source account ID.', $object->id, $object->transaction_group_id)); return true; } /** - * @param string $type + * @param string $type * * @return Account|null */ diff --git a/app/TransactionRules/Actions/UpdatePiggybank.php b/app/TransactionRules/Actions/UpdatePiggybank.php index 85584d7c09..a2dc6ef1d4 100644 --- a/app/TransactionRules/Actions/UpdatePiggybank.php +++ b/app/TransactionRules/Actions/UpdatePiggybank.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; +use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\PiggyBank; use FireflyIII\Models\RuleAction; use FireflyIII\Models\Transaction; @@ -82,20 +83,50 @@ class UpdatePiggybank implements ActionInterface Log::debug(sprintf('Found piggy bank #%d ("%s")', $piggyBank->id, $piggyBank->name)); /** @var Transaction $source */ - /** @var Transaction $destination */ $source = $journalObj->transactions()->where('amount', '<', 0)->first(); + /** @var Transaction $destination */ $destination = $journalObj->transactions()->where('amount', '>', 0)->first(); if ((int)$source->account_id === (int)$piggyBank->account_id) { Log::debug('Piggy bank account is linked to source, so remove amount from piggy bank.'); $this->removeAmount($piggyBank, $journalObj, $destination->amount); + event( + new TriggeredAuditLog( + $this->action->rule, + $journalObj, + 'remove_from_piggy', + null, + [ + 'currency_symbol' => $journalObj->transactionCurrency->symbol, + 'decimal_places' => $journalObj->transactionCurrency->decimal_places, + 'amount' => $destination->amount, + 'piggy' => $piggyBank->name, + ] + ) + ); + return true; } if ((int)$destination->account_id === (int)$piggyBank->account_id) { Log::debug('Piggy bank account is linked to source, so add amount to piggy bank.'); $this->addAmount($piggyBank, $journalObj, $destination->amount); + event( + new TriggeredAuditLog( + $this->action->rule, + $journalObj, + 'add_to_piggy', + null, + [ + 'currency_symbol' => $journalObj->transactionCurrency->symbol, + 'decimal_places' => $journalObj->transactionCurrency->decimal_places, + 'amount' => $destination->amount, + 'piggy' => $piggyBank->name, + ] + ) + ); + return true; } Log::info( diff --git a/app/TransactionRules/Engine/RuleEngineInterface.php b/app/TransactionRules/Engine/RuleEngineInterface.php index c5cf66c2cd..111fdb6231 100644 --- a/app/TransactionRules/Engine/RuleEngineInterface.php +++ b/app/TransactionRules/Engine/RuleEngineInterface.php @@ -34,7 +34,7 @@ interface RuleEngineInterface /** * Add operators added to each search by the rule engine. * - * @param array $operator + * @param array $operator */ public function addOperator(array $operator): void; @@ -58,20 +58,19 @@ interface RuleEngineInterface /** * Add entire rule groups for the engine to execute. * - * @param Collection $ruleGroups + * @param Collection $ruleGroups */ public function setRuleGroups(Collection $ruleGroups): void; /** * Add rules for the engine to execute. * - * @param Collection $rules + * @param Collection $rules */ public function setRules(Collection $rules): void; /** - * @param User $user + * @param User $user */ public function setUser(User $user): void; - } diff --git a/app/TransactionRules/Engine/SearchRuleEngine.php b/app/TransactionRules/Engine/SearchRuleEngine.php index 8afcae7b81..756716ce82 100644 --- a/app/TransactionRules/Engine/SearchRuleEngine.php +++ b/app/TransactionRules/Engine/SearchRuleEngine.php @@ -50,8 +50,8 @@ class SearchRuleEngine implements RuleEngineInterface public function __construct() { - $this->rules = new Collection; - $this->groups = new Collection; + $this->rules = new Collection(); + $this->groups = new Collection(); $this->operators = []; $this->resultCount = []; } @@ -71,9 +71,9 @@ class SearchRuleEngine implements RuleEngineInterface public function find(): Collection { Log::debug('SearchRuleEngine::find()'); - $collection = new Collection; + $collection = new Collection(); foreach ($this->rules as $rule) { - $found = new Collection; + $found = new Collection(); if (true === $rule->strict) { $found = $this->findStrictRule($rule); } @@ -89,7 +89,7 @@ class SearchRuleEngine implements RuleEngineInterface /** * Finds the transactions a strict rule will execute on. * - * @param Rule $rule + * @param Rule $rule * * @return Collection */ @@ -99,7 +99,7 @@ class SearchRuleEngine implements RuleEngineInterface $searchArray = []; /** @var Collection $triggers */ - $triggers = $rule->ruleTriggers; + $triggers = $rule->ruleTriggers()->orderBy('order', 'ASC')->get(); /** @var RuleTrigger $ruleTrigger */ foreach ($triggers as $ruleTrigger) { @@ -152,7 +152,7 @@ class SearchRuleEngine implements RuleEngineInterface * one search operator for "journal_id" it means the date ranges * in the search may need to be updated. * - * @param array $array + * @param array $array * * @return bool */ @@ -178,7 +178,7 @@ class SearchRuleEngine implements RuleEngineInterface } /** - * @param array $array + * @param array $array * * @return Carbon */ @@ -188,7 +188,7 @@ class SearchRuleEngine implements RuleEngineInterface $journalId = 0; foreach ($array as $triggerName => $values) { if ('journal_id' === $triggerName && is_array($values) && 1 === count($values)) { - $journalId = (int) trim(($values[0] ?? '"0"'), '"'); // follows format "123". + $journalId = (int)trim(($values[0] ?? '"0"'), '"'); // follows format "123". Log::debug(sprintf('Found journal ID #%d', $journalId)); } } @@ -209,14 +209,23 @@ class SearchRuleEngine implements RuleEngineInterface } /** - * @param Rule $rule + * @inheritDoc + */ + public function setUser(User $user): void + { + $this->user = $user; + $this->operators = []; + } + + /** + * @param Rule $rule * * @return Collection */ private function findNonStrictRule(Rule $rule): Collection { // start a search query for individual each trigger: - $total = new Collection; + $total = new Collection(); $count = 0; /** @var Collection $triggers */ @@ -320,7 +329,7 @@ class SearchRuleEngine implements RuleEngineInterface /** * Returns true if the rule has been triggered. * - * @param Rule $rule + * @param Rule $rule * * @return bool * @throws FireflyException @@ -346,7 +355,7 @@ class SearchRuleEngine implements RuleEngineInterface /** * Return true if the rule is fired (the collection is larger than zero). * - * @param Rule $rule + * @param Rule $rule * * @return bool * @throws FireflyException @@ -371,8 +380,8 @@ class SearchRuleEngine implements RuleEngineInterface } /** - * @param Rule $rule - * @param Collection $collection + * @param Rule $rule + * @param Collection $collection * * @throws FireflyException */ @@ -386,8 +395,8 @@ class SearchRuleEngine implements RuleEngineInterface } /** - * @param Rule $rule - * @param array $group + * @param Rule $rule + * @param array $group * * @throws FireflyException */ @@ -401,15 +410,15 @@ class SearchRuleEngine implements RuleEngineInterface } /** - * @param Rule $rule - * @param array $transaction + * @param Rule $rule + * @param array $transaction * * @throws FireflyException */ private function processTransactionJournal(Rule $rule, array $transaction): void { Log::debug(sprintf('SearchRuleEngine:: Will now execute actions on transaction journal #%d', $transaction['transaction_journal_id'])); - $actions = $rule->ruleActions()->get(); + $actions = $rule->ruleActions()->orderBy('order', 'ASC')->get(); /** @var RuleAction $ruleAction */ foreach ($actions as $ruleAction) { if (false === $ruleAction->active) { @@ -423,8 +432,8 @@ class SearchRuleEngine implements RuleEngineInterface } /** - * @param RuleAction $ruleAction - * @param array $transaction + * @param RuleAction $ruleAction + * @param array $transaction * * @return bool * @throws FireflyException @@ -463,7 +472,7 @@ class SearchRuleEngine implements RuleEngineInterface /** * Return true if the rule is fired (the collection is larger than zero). * - * @param Rule $rule + * @param Rule $rule * * @return bool * @throws FireflyException @@ -480,7 +489,7 @@ class SearchRuleEngine implements RuleEngineInterface } /** - * @param RuleGroup $group + * @param RuleGroup $group * * @return void * @throws FireflyException @@ -502,7 +511,6 @@ class SearchRuleEngine implements RuleEngineInterface return; } } - } /** @@ -534,7 +542,6 @@ class SearchRuleEngine implements RuleEngineInterface */ public function setRules(Collection $rules): void { - Log::debug(__METHOD__); foreach ($rules as $rule) { if ($rule instanceof Rule) { @@ -543,13 +550,4 @@ class SearchRuleEngine implements RuleEngineInterface } } } - - /** - * @inheritDoc - */ - public function setUser(User $user): void - { - $this->user = $user; - $this->operators = []; - } } diff --git a/app/TransactionRules/Factory/ActionFactory.php b/app/TransactionRules/Factory/ActionFactory.php index 23c7da3248..5627727ea6 100644 --- a/app/TransactionRules/Factory/ActionFactory.php +++ b/app/TransactionRules/Factory/ActionFactory.php @@ -1,4 +1,5 @@ parameters = new ParameterBag(); $this->repository = app(AccountRepositoryInterface::class); } /** * Transform the account. * - * @param Account $account + * @param Account $account * * @return array * @throws JsonException @@ -61,8 +63,8 @@ class AccountTransformer extends AbstractTransformer // get account type: $fullType = $account->accountType->type; - $accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType)); - $liabilityType = (string) config(sprintf('firefly.shortLiabilityNameByFullName.%s', $fullType)); + $accountType = (string)config(sprintf('firefly.shortNamesByFullName.%s', $fullType)); + $liabilityType = (string)config(sprintf('firefly.shortLiabilityNameByFullName.%s', $fullType)); $liabilityType = '' === $liabilityType ? null : strtolower($liabilityType); $liabilityDirection = $this->repository->getMetaValue($account, 'liability_direction'); @@ -85,17 +87,17 @@ class AccountTransformer extends AbstractTransformer if (null !== $location) { $longitude = $location->longitude; $latitude = $location->latitude; - $zoomLevel = (int) $location->zoom_level; + $zoomLevel = (int)$location->zoom_level; } // no order for some accounts: - $order = (int) $account->order; - if (!in_array(strtolower($accountType), ['liability', 'liabilities', 'asset'])) { + $order = (int)$account->order; + if (!in_array(strtolower($accountType), ['liability', 'liabilities', 'asset'], true)) { $order = null; } return [ - 'id' => (string) $account->id, + 'id' => (string)$account->id, 'created_at' => $account->created_at->toAtomString(), 'updated_at' => $account->updated_at->toAtomString(), 'active' => $account->active, @@ -130,23 +132,23 @@ class AccountTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/accounts/' . $account->id, + 'uri' => '/accounts/'.$account->id, ], ], ]; } /** - * @param Account $account + * @param Account $account * - * @param string $accountType + * @param string $accountType * * @return string|null */ private function getAccountRole(Account $account, string $accountType): ?string { $accountRole = $this->repository->getMetaValue($account, 'account_role'); - if ('asset' !== $accountType || '' === (string) $accountRole) { + if ('asset' !== $accountType || '' === (string)$accountRole) { $accountRole = null; } @@ -154,6 +156,7 @@ class AccountTransformer extends AbstractTransformer } /** + * TODO duplicated in the V2 transformer. * @return Carbon */ private function getDate(): Carbon @@ -167,7 +170,7 @@ class AccountTransformer extends AbstractTransformer } /** - * @param Account $account + * @param Account $account * * @return array * @throws FireflyException @@ -181,7 +184,7 @@ class AccountTransformer extends AbstractTransformer if (null === $currency) { $currency = app('amount')->getDefaultCurrencyByUser($account->user); } - $currencyId = (string) $currency->id; + $currencyId = (string)$currency->id; $currencyCode = $currency->code; $decimalPlaces = $currency->decimal_places; $currencySymbol = $currency->symbol; @@ -190,9 +193,9 @@ class AccountTransformer extends AbstractTransformer } /** - * @param Account $account - * @param string|null $accountRole - * @param string $accountType + * @param Account $account + * @param string|null $accountRole + * @param string $accountType * * @return array */ @@ -212,12 +215,12 @@ class AccountTransformer extends AbstractTransformer } /** - * @param Account $account - * @param string $accountType + * @param Account $account + * @param string $accountType * * @return array * - * See reference nr. 20 + * TODO refactor call to get~OpeningBalanceAmount / Date because it is a lot of queries. */ private function getOpeningBalance(Account $account, string $accountType): array { @@ -236,8 +239,8 @@ class AccountTransformer extends AbstractTransformer } /** - * @param Account $account - * @param string $accountType + * @param Account $account + * @param string $accountType * * @return array */ diff --git a/app/Transformers/AttachmentTransformer.php b/app/Transformers/AttachmentTransformer.php index 430feeb9b1..e816a8ba3f 100644 --- a/app/Transformers/AttachmentTransformer.php +++ b/app/Transformers/AttachmentTransformer.php @@ -46,7 +46,7 @@ class AttachmentTransformer extends AbstractTransformer /** * Transform attachment. * - * @param Attachment $attachment + * @param Attachment $attachment * * @return array */ @@ -55,10 +55,10 @@ class AttachmentTransformer extends AbstractTransformer $this->repository->setUser($attachment->user); return [ - 'id' => (string) $attachment->id, + 'id' => (string)$attachment->id, 'created_at' => $attachment->created_at->toAtomString(), 'updated_at' => $attachment->updated_at->toAtomString(), - 'attachable_id' => (string) $attachment->attachable_id, + 'attachable_id' => (string)$attachment->attachable_id, 'attachable_type' => str_replace('FireflyIII\\Models\\', '', $attachment->attachable_type), 'md5' => $attachment->md5, 'filename' => $attachment->filename, @@ -67,14 +67,13 @@ class AttachmentTransformer extends AbstractTransformer 'title' => $attachment->title, 'notes' => $this->repository->getNoteText($attachment), 'mime' => $attachment->mime, - 'size' => (int) $attachment->size, + 'size' => (int)$attachment->size, 'links' => [ [ 'rel' => 'self', - 'uri' => '/attachment/' . $attachment->id, + 'uri' => '/attachment/'.$attachment->id, ], ], ]; } - } diff --git a/app/Transformers/AvailableBudgetTransformer.php b/app/Transformers/AvailableBudgetTransformer.php index 62944bab86..ec7cdd1b23 100644 --- a/app/Transformers/AvailableBudgetTransformer.php +++ b/app/Transformers/AvailableBudgetTransformer.php @@ -52,7 +52,7 @@ class AvailableBudgetTransformer extends AbstractTransformer /** * Transform the note. * - * @param AvailableBudget $availableBudget + * @param AvailableBudget $availableBudget * * @return array */ @@ -62,13 +62,13 @@ class AvailableBudgetTransformer extends AbstractTransformer $currency = $availableBudget->transactionCurrency; $data = [ - 'id' => (string) $availableBudget->id, + 'id' => (string)$availableBudget->id, 'created_at' => $availableBudget->created_at->toAtomString(), 'updated_at' => $availableBudget->updated_at->toAtomString(), - 'currency_id' => (string) $currency->id, + 'currency_id' => (string)$currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => (int) $currency->decimal_places, + 'currency_decimal_places' => (int)$currency->decimal_places, 'amount' => app('steam')->bcround($availableBudget->amount, $currency->decimal_places), 'start' => $availableBudget->start_date->toAtomString(), 'end' => $availableBudget->end_date->endOfDay()->toAtomString(), @@ -77,7 +77,7 @@ class AvailableBudgetTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/available_budgets/' . $availableBudget->id, + 'uri' => '/available_budgets/'.$availableBudget->id, ], ], ]; diff --git a/app/Transformers/BillTransformer.php b/app/Transformers/BillTransformer.php index 8b6ec658be..e88ddc7786 100644 --- a/app/Transformers/BillTransformer.php +++ b/app/Transformers/BillTransformer.php @@ -52,7 +52,7 @@ class BillTransformer extends AbstractTransformer /** * Transform the bill. * - * @param Bill $bill + * @param Bill $bill * * @return array */ @@ -72,8 +72,8 @@ class BillTransformer extends AbstractTransformer /** @var ObjectGroup $objectGroup */ $objectGroup = $bill->objectGroups->first(); if (null !== $objectGroup) { - $objectGroupId = (int) $objectGroup->id; - $objectGroupOrder = (int) $objectGroup->order; + $objectGroupId = (int)$objectGroup->id; + $objectGroupOrder = (int)$objectGroup->order; $objectGroupTitle = $objectGroup->title; } @@ -107,13 +107,13 @@ class BillTransformer extends AbstractTransformer unset($temp, $temp2); return [ - 'id' => (int) $bill->id, + 'id' => (int)$bill->id, 'created_at' => $bill->created_at->toAtomString(), 'updated_at' => $bill->updated_at->toAtomString(), - 'currency_id' => (string) $bill->transaction_currency_id, + 'currency_id' => (string)$bill->transaction_currency_id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => (int) $currency->decimal_places, + 'currency_decimal_places' => (int)$currency->decimal_places, 'name' => $bill->name, 'amount_min' => app('steam')->bcround($bill->amount_min, $currency->decimal_places), 'amount_max' => app('steam')->bcround($bill->amount_max, $currency->decimal_places), @@ -121,11 +121,11 @@ class BillTransformer extends AbstractTransformer 'end_date' => $bill->end_date?->toAtomString(), 'extension_date' => $bill->extension_date?->toAtomString(), 'repeat_freq' => $bill->repeat_freq, - 'skip' => (int) $bill->skip, + 'skip' => (int)$bill->skip, 'active' => $bill->active, - 'order' => (int) $bill->order, + 'order' => (int)$bill->order, 'notes' => $notes, - 'object_group_id' => $objectGroupId ? (string) $objectGroupId : null, + 'object_group_id' => $objectGroupId ? (string)$objectGroupId : null, 'object_group_order' => $objectGroupOrder, 'object_group_title' => $objectGroupTitle, @@ -137,7 +137,7 @@ class BillTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/bills/' . $bill->id, + 'uri' => '/bills/'.$bill->id, ], ], ]; @@ -146,7 +146,7 @@ class BillTransformer extends AbstractTransformer /** * Get the data the bill was paid and predict the next expected match. * - * @param Bill $bill + * @param Bill $bill * * @return array */ @@ -203,8 +203,8 @@ class BillTransformer extends AbstractTransformer $result = []; foreach ($set as $entry) { $result[] = [ - 'transaction_group_id' => (int) $entry->transaction_group_id, - 'transaction_journal_id' => (int) $entry->id, + 'transaction_group_id' => (int)$entry->transaction_group_id, + 'transaction_journal_id' => (int)$entry->id, 'date' => $entry->date->format('Y-m-d'), ]; } @@ -220,8 +220,8 @@ class BillTransformer extends AbstractTransformer /** * Returns the latest date in the set, or start when set is empty. * - * @param Collection $dates - * @param Carbon $default + * @param Collection $dates + * @param Carbon $default * * @return Carbon */ @@ -242,7 +242,7 @@ class BillTransformer extends AbstractTransformer } /** - * @param Bill $bill + * @param Bill $bill * * @return array */ @@ -254,7 +254,7 @@ class BillTransformer extends AbstractTransformer return []; } - $set = new Collection; + $set = new Collection(); $currentStart = clone $this->parameters->get('start'); $loop = 0; while ($currentStart <= $this->parameters->get('end')) { @@ -285,8 +285,8 @@ class BillTransformer extends AbstractTransformer * Given a bill and a date, this method will tell you at which moment this bill expects its next * transaction. Whether or not it is there already, is not relevant. * - * @param Bill $bill - * @param Carbon $date + * @param Bill $bill + * @param Carbon $date * * @return Carbon */ diff --git a/app/Transformers/BudgetLimitTransformer.php b/app/Transformers/BudgetLimitTransformer.php index 26570b4e6b..1afb62ae2b 100644 --- a/app/Transformers/BudgetLimitTransformer.php +++ b/app/Transformers/BudgetLimitTransformer.php @@ -42,19 +42,19 @@ class BudgetLimitTransformer extends AbstractTransformer /** * Include Budget * - * @param BudgetLimit $limit + * @param BudgetLimit $limit * * @return Item */ public function includeBudget(BudgetLimit $limit) { - return $this->item($limit->budget, new BudgetTransformer, 'budgets'); + return $this->item($limit->budget, new BudgetTransformer(), 'budgets'); } /** * Transform the note. * - * @param BudgetLimit $budgetLimit + * @param BudgetLimit $budgetLimit * * @return array */ @@ -63,7 +63,11 @@ class BudgetLimitTransformer extends AbstractTransformer $repository = app(OperationsRepository::class); $repository->setUser($budgetLimit->budget->user); $expenses = $repository->sumExpenses( - $budgetLimit->start_date, $budgetLimit->end_date, null, new Collection([$budgetLimit->budget]), $budgetLimit->transactionCurrency + $budgetLimit->start_date, + $budgetLimit->end_date, + null, + new Collection([$budgetLimit->budget]), + $budgetLimit->transactionCurrency ); $currency = $budgetLimit->transactionCurrency; $amount = $budgetLimit->amount; @@ -74,7 +78,7 @@ class BudgetLimitTransformer extends AbstractTransformer $currencySymbol = null; if (null !== $currency) { $amount = $budgetLimit->amount; - $currencyId = (int) $currency->id; + $currencyId = (int)$currency->id; $currencyName = $currency->name; $currencyCode = $currency->code; $currencySymbol = $currency->symbol; @@ -83,13 +87,13 @@ class BudgetLimitTransformer extends AbstractTransformer $amount = app('steam')->bcround($amount, $currencyDecimalPlaces); return [ - 'id' => (string) $budgetLimit->id, + 'id' => (string)$budgetLimit->id, 'created_at' => $budgetLimit->created_at->toAtomString(), 'updated_at' => $budgetLimit->updated_at->toAtomString(), 'start' => $budgetLimit->start_date->toAtomString(), 'end' => $budgetLimit->end_date->endOfDay()->toAtomString(), - 'budget_id' => (string) $budgetLimit->budget_id, - 'currency_id' => (string) $currencyId, + 'budget_id' => (string)$budgetLimit->budget_id, + 'currency_id' => (string)$currencyId, 'currency_code' => $currencyCode, 'currency_name' => $currencyName, 'currency_decimal_places' => $currencyDecimalPlaces, @@ -100,7 +104,7 @@ class BudgetLimitTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/budgets/limits/' . $budgetLimit->id, + 'uri' => '/budgets/limits/'.$budgetLimit->id, ], ], ]; diff --git a/app/Transformers/BudgetTransformer.php b/app/Transformers/BudgetTransformer.php index ef76034750..2450415f83 100644 --- a/app/Transformers/BudgetTransformer.php +++ b/app/Transformers/BudgetTransformer.php @@ -53,7 +53,7 @@ class BudgetTransformer extends AbstractTransformer /** * Transform a budget. * - * @param Budget $budget + * @param Budget $budget * * @return array */ @@ -81,7 +81,7 @@ class BudgetTransformer extends AbstractTransformer ]; if (null !== $autoBudget) { - $abCurrencyId = (string) $autoBudget->transactionCurrency->id; + $abCurrencyId = (string)$autoBudget->transactionCurrency->id; $abCurrencyCode = $autoBudget->transactionCurrency->code; $abType = $types[$autoBudget->auto_budget_type]; $abAmount = app('steam')->bcround($autoBudget->amount, $autoBudget->transactionCurrency->decimal_places); @@ -89,7 +89,7 @@ class BudgetTransformer extends AbstractTransformer } return [ - 'id' => (string) $budget->id, + 'id' => (string)$budget->id, 'created_at' => $budget->created_at->toAtomString(), 'updated_at' => $budget->updated_at->toAtomString(), 'active' => $budget->active, @@ -105,14 +105,14 @@ class BudgetTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/budgets/' . $budget->id, + 'uri' => '/budgets/'.$budget->id, ], ], ]; } /** - * @param array $array + * @param array $array * * @return array */ @@ -120,11 +120,10 @@ class BudgetTransformer extends AbstractTransformer { $return = []; foreach ($array as $data) { - $data['sum'] = app('steam')->bcround($data['sum'], (int) $data['currency_decimal_places']); + $data['sum'] = app('steam')->bcround($data['sum'], (int)$data['currency_decimal_places']); $return[] = $data; } return $return; } - } diff --git a/app/Transformers/CategoryTransformer.php b/app/Transformers/CategoryTransformer.php index 81fe257bf8..739a025726 100644 --- a/app/Transformers/CategoryTransformer.php +++ b/app/Transformers/CategoryTransformer.php @@ -50,7 +50,7 @@ class CategoryTransformer extends AbstractTransformer /** * Convert category. * - * @param Category $category + * @param Category $category * * @return array */ @@ -70,7 +70,7 @@ class CategoryTransformer extends AbstractTransformer $notes = $this->repository->getNoteText($category); return [ - 'id' => (int) $category->id, + 'id' => (int)$category->id, 'created_at' => $category->created_at->toAtomString(), 'updated_at' => $category->updated_at->toAtomString(), 'name' => $category->name, @@ -80,14 +80,14 @@ class CategoryTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/categories/' . $category->id, + 'uri' => '/categories/'.$category->id, ], ], ]; } /** - * @param array $array + * @param array $array * * @return array */ @@ -95,7 +95,7 @@ class CategoryTransformer extends AbstractTransformer { $return = []; foreach ($array as $data) { - $data['sum'] = app('steam')->bcround($data['sum'], (int) $data['currency_decimal_places']); + $data['sum'] = app('steam')->bcround($data['sum'], (int)$data['currency_decimal_places']); $return[] = $data; } diff --git a/app/Transformers/CurrencyTransformer.php b/app/Transformers/CurrencyTransformer.php index ab78269e8e..3d3afef4d2 100644 --- a/app/Transformers/CurrencyTransformer.php +++ b/app/Transformers/CurrencyTransformer.php @@ -30,11 +30,10 @@ use FireflyIII\Models\TransactionCurrency; */ class CurrencyTransformer extends AbstractTransformer { - /** * Transform the currency. * - * @param TransactionCurrency $currency + * @param TransactionCurrency $currency * * @return array */ @@ -43,11 +42,11 @@ class CurrencyTransformer extends AbstractTransformer $isDefault = false; $defaultCurrency = $this->parameters->get('defaultCurrency'); if (null !== $defaultCurrency) { - $isDefault = (int) $defaultCurrency->id === (int) $currency->id; + $isDefault = (int)$defaultCurrency->id === (int)$currency->id; } return [ - 'id' => (int) $currency->id, + 'id' => (int)$currency->id, 'created_at' => $currency->created_at->toAtomString(), 'updated_at' => $currency->updated_at->toAtomString(), 'default' => $isDefault, @@ -55,11 +54,11 @@ class CurrencyTransformer extends AbstractTransformer 'name' => $currency->name, 'code' => $currency->code, 'symbol' => $currency->symbol, - 'decimal_places' => (int) $currency->decimal_places, + 'decimal_places' => (int)$currency->decimal_places, 'links' => [ [ 'rel' => 'self', - 'uri' => '/currencies/' . $currency->id, + 'uri' => '/currencies/'.$currency->id, ], ], ]; diff --git a/app/Transformers/LinkTypeTransformer.php b/app/Transformers/LinkTypeTransformer.php index b1e1097ed5..6fd860acc6 100644 --- a/app/Transformers/LinkTypeTransformer.php +++ b/app/Transformers/LinkTypeTransformer.php @@ -34,14 +34,14 @@ class LinkTypeTransformer extends AbstractTransformer /** * Transform the currency. * - * @param LinkType $linkType + * @param LinkType $linkType * * @return array */ public function transform(LinkType $linkType): array { return [ - 'id' => (int) $linkType->id, + 'id' => (int)$linkType->id, 'created_at' => $linkType->created_at->toAtomString(), 'updated_at' => $linkType->updated_at->toAtomString(), 'name' => $linkType->name, @@ -51,7 +51,7 @@ class LinkTypeTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/link_types/' . $linkType->id, + 'uri' => '/link_types/'.$linkType->id, ], ], ]; diff --git a/app/Transformers/ObjectGroupTransformer.php b/app/Transformers/ObjectGroupTransformer.php index 3f350d79cf..86f7d1e37a 100644 --- a/app/Transformers/ObjectGroupTransformer.php +++ b/app/Transformers/ObjectGroupTransformer.php @@ -47,7 +47,7 @@ class ObjectGroupTransformer extends AbstractTransformer /** * Transform the account. * - * @param ObjectGroup $objectGroup + * @param ObjectGroup $objectGroup * * @return array */ @@ -56,18 +56,17 @@ class ObjectGroupTransformer extends AbstractTransformer $this->repository->setUser($objectGroup->user); return [ - 'id' => (string) $objectGroup->id, + 'id' => (string)$objectGroup->id, 'created_at' => $objectGroup->created_at?->toAtomString(), 'updated_at' => $objectGroup->updated_at?->toAtomString(), 'title' => $objectGroup->title, - 'order' => (int) $objectGroup->order, + 'order' => (int)$objectGroup->order, 'links' => [ [ 'rel' => 'self', - 'uri' => '/object_groups/' . $objectGroup->id, + 'uri' => '/object_groups/'.$objectGroup->id, ], ], ]; } - } diff --git a/app/Transformers/PiggyBankEventTransformer.php b/app/Transformers/PiggyBankEventTransformer.php index 37e7d60fbd..78dc72f53b 100644 --- a/app/Transformers/PiggyBankEventTransformer.php +++ b/app/Transformers/PiggyBankEventTransformer.php @@ -23,10 +23,12 @@ declare(strict_types=1); namespace FireflyIII\Transformers; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\PiggyBankEvent; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; +use JsonException; /** * Class PiggyBankEventTransformer @@ -52,11 +54,11 @@ class PiggyBankEventTransformer extends AbstractTransformer /** * Convert piggy bank event. * - * @param PiggyBankEvent $event + * @param PiggyBankEvent $event * * @return array - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException + * @throws FireflyException + * @throws JsonException */ public function transform(PiggyBankEvent $event): array { @@ -74,29 +76,28 @@ class PiggyBankEventTransformer extends AbstractTransformer // get associated journal and transaction, if any: $journalId = $event->transaction_journal_id; $groupId = null; - if (0 !== (int) $journalId) { - $groupId = (int) $event->transactionJournal->transaction_group_id; - $journalId = (int) $journalId; + if (0 !== (int)$journalId) { + $groupId = (int)$event->transactionJournal->transaction_group_id; + $journalId = (int)$journalId; } return [ - 'id' => (string) $event->id, + 'id' => (string)$event->id, 'created_at' => $event->created_at->toAtomString(), 'updated_at' => $event->updated_at->toAtomString(), 'amount' => app('steam')->bcround($event->amount, $currency->decimal_places), - 'currency_id' => (string) $currency->id, + 'currency_id' => (string)$currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => (int) $currency->decimal_places, - 'transaction_journal_id' => $journalId ? (string) $journalId : null, - 'transaction_group_id' => $groupId ? (string) $groupId : null, + 'currency_decimal_places' => (int)$currency->decimal_places, + 'transaction_journal_id' => $journalId ? (string)$journalId : null, + 'transaction_group_id' => $groupId ? (string)$groupId : null, 'links' => [ [ 'rel' => 'self', - 'uri' => '/piggy_bank_events/' . $event->id, + 'uri' => '/piggy_bank_events/'.$event->id, ], ], ]; } - } diff --git a/app/Transformers/PiggyBankTransformer.php b/app/Transformers/PiggyBankTransformer.php index 016a0d5481..4b97997ce6 100644 --- a/app/Transformers/PiggyBankTransformer.php +++ b/app/Transformers/PiggyBankTransformer.php @@ -23,11 +23,13 @@ declare(strict_types=1); namespace FireflyIII\Transformers; +use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\ObjectGroup; use FireflyIII\Models\PiggyBank; use FireflyIII\Repositories\Account\AccountRepositoryInterface; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use FireflyIII\Repositories\PiggyBank\PiggyBankRepositoryInterface; +use JsonException; /** * Class PiggyBankTransformer @@ -56,8 +58,8 @@ class PiggyBankTransformer extends AbstractTransformer * @param PiggyBank $piggyBank * * @return array - * @throws \FireflyIII\Exceptions\FireflyException - * @throws \JsonException + * @throws FireflyException + * @throws JsonException */ public function transform(PiggyBank $piggyBank): array { diff --git a/app/Transformers/PreferenceTransformer.php b/app/Transformers/PreferenceTransformer.php index 402966786f..34298d9b4f 100644 --- a/app/Transformers/PreferenceTransformer.php +++ b/app/Transformers/PreferenceTransformer.php @@ -33,20 +33,18 @@ class PreferenceTransformer extends AbstractTransformer /** * Transform the preference * - * @param Preference $preference + * @param Preference $preference * * @return array */ public function transform(Preference $preference): array { return [ - 'id' => (int) $preference->id, + 'id' => (int)$preference->id, 'created_at' => $preference->created_at->toAtomString(), 'updated_at' => $preference->updated_at->toAtomString(), 'name' => $preference->name, 'data' => $preference->data, ]; - } - } diff --git a/app/Transformers/RecurrenceTransformer.php b/app/Transformers/RecurrenceTransformer.php index 61e6f89aa2..c6571aba99 100644 --- a/app/Transformers/RecurrenceTransformer.php +++ b/app/Transformers/RecurrenceTransformer.php @@ -60,13 +60,12 @@ class RecurrenceTransformer extends AbstractTransformer $this->factory = app(CategoryFactory::class); $this->budgetRepos = app(BudgetRepositoryInterface::class); $this->billRepos = app(BillRepositoryInterface::class); - } /** * Transform the recurring transaction. * - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return array * @throws FireflyException @@ -80,14 +79,14 @@ class RecurrenceTransformer extends AbstractTransformer $this->budgetRepos->setUser($recurrence->user); Log::debug('Set user.'); - $shortType = (string) config(sprintf('firefly.transactionTypesToShort.%s', $recurrence->transactionType->type)); + $shortType = (string)config(sprintf('firefly.transactionTypesToShort.%s', $recurrence->transactionType->type)); $notes = $this->repository->getNoteText($recurrence); - $reps = 0 === (int) $recurrence->repetitions ? null : (int) $recurrence->repetitions; + $reps = 0 === (int)$recurrence->repetitions ? null : (int)$recurrence->repetitions; Log::debug('Get basic data.'); // basic data. return [ - 'id' => (string) $recurrence->id, + 'id' => (string)$recurrence->id, 'created_at' => $recurrence->created_at->toAtomString(), 'updated_at' => $recurrence->updated_at->toAtomString(), 'type' => $shortType, @@ -105,14 +104,14 @@ class RecurrenceTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/recurring/' . $recurrence->id, + 'uri' => '/recurring/'.$recurrence->id, ], ], ]; } /** - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return array * @throws FireflyException @@ -126,19 +125,19 @@ class RecurrenceTransformer extends AbstractTransformer /** @var RecurrenceRepetition $repetition */ foreach ($recurrence->recurrenceRepetitions as $repetition) { $repetitionArray = [ - 'id' => (string) $repetition->id, + 'id' => (string)$repetition->id, 'created_at' => $repetition->created_at->toAtomString(), 'updated_at' => $repetition->updated_at->toAtomString(), 'type' => $repetition->repetition_type, 'moment' => $repetition->repetition_moment, - 'skip' => (int) $repetition->repetition_skip, - 'weekend' => (int) $repetition->weekend, + 'skip' => (int)$repetition->repetition_skip, + 'weekend' => (int)$repetition->weekend, 'description' => $this->repository->repetitionDescription($repetition), 'occurrences' => [], ]; // get the (future) occurrences for this specific type of repetition: - $occurrences = $this->repository->getXOccurrencesSince($repetition, $fromDate, new Carbon, 5); + $occurrences = $this->repository->getXOccurrencesSince($repetition, $fromDate, new Carbon(), 5); /** @var Carbon $carbon */ foreach ($occurrences as $carbon) { $repetitionArray['occurrences'][] = $carbon->toAtomString(); @@ -151,7 +150,7 @@ class RecurrenceTransformer extends AbstractTransformer } /** - * @param Recurrence $recurrence + * @param Recurrence $recurrence * * @return array * @throws FireflyException @@ -163,7 +162,6 @@ class RecurrenceTransformer extends AbstractTransformer // get all transactions: /** @var RecurrenceTransaction $transaction */ foreach ($recurrence->recurrenceTransactions()->get() as $transaction) { - $sourceAccount = $transaction->sourceAccount; $destinationAccount = $transaction->destinationAccount; $foreignCurrencyCode = null; @@ -171,10 +169,10 @@ class RecurrenceTransformer extends AbstractTransformer $foreignCurrencyDp = null; $foreignCurrencyId = null; if (null !== $transaction->foreign_currency_id) { - $foreignCurrencyId = (int) $transaction->foreign_currency_id; + $foreignCurrencyId = (int)$transaction->foreign_currency_id; $foreignCurrencyCode = $transaction->foreignCurrency->code; $foreignCurrencySymbol = $transaction->foreignCurrency->symbol; - $foreignCurrencyDp = (int) $transaction->foreignCurrency->decimal_places; + $foreignCurrencyDp = (int)$transaction->foreignCurrency->decimal_places; } // source info: @@ -184,7 +182,7 @@ class RecurrenceTransformer extends AbstractTransformer $sourceIban = null; if (null !== $sourceAccount) { $sourceName = $sourceAccount->name; - $sourceId = (int) $sourceAccount->id; + $sourceId = (int)$sourceAccount->id; $sourceType = $sourceAccount->accountType->type; $sourceIban = $sourceAccount->iban; } @@ -194,7 +192,7 @@ class RecurrenceTransformer extends AbstractTransformer $destinationIban = null; if (null !== $destinationAccount) { $destinationName = $destinationAccount->name; - $destinationId = (int) $destinationAccount->id; + $destinationId = (int)$destinationAccount->id; $destinationType = $destinationAccount->accountType->type; $destinationIban = $destinationAccount->iban; } @@ -204,19 +202,19 @@ class RecurrenceTransformer extends AbstractTransformer $foreignAmount = app('steam')->bcround($transaction->foreign_amount, $foreignCurrencyDp); } $transactionArray = [ - 'currency_id' => (string) $transaction->transaction_currency_id, + 'currency_id' => (string)$transaction->transaction_currency_id, 'currency_code' => $transaction->transactionCurrency->code, 'currency_symbol' => $transaction->transactionCurrency->symbol, - 'currency_decimal_places' => (int) $transaction->transactionCurrency->decimal_places, - 'foreign_currency_id' => null === $foreignCurrencyId ? null : (string) $foreignCurrencyId, + 'currency_decimal_places' => (int)$transaction->transactionCurrency->decimal_places, + 'foreign_currency_id' => null === $foreignCurrencyId ? null : (string)$foreignCurrencyId, 'foreign_currency_code' => $foreignCurrencyCode, 'foreign_currency_symbol' => $foreignCurrencySymbol, 'foreign_currency_decimal_places' => $foreignCurrencyDp, - 'source_id' => (string) $sourceId, + 'source_id' => (string)$sourceId, 'source_name' => $sourceName, 'source_iban' => $sourceIban, 'source_type' => $sourceType, - 'destination_id' => (string) $destinationId, + 'destination_id' => (string)$destinationId, 'destination_name' => $destinationName, 'destination_iban' => $destinationIban, 'destination_type' => $destinationType, @@ -239,8 +237,8 @@ class RecurrenceTransformer extends AbstractTransformer } /** - * @param RecurrenceTransaction $transaction - * @param array $array + * @param RecurrenceTransaction $transaction + * @param array $array * * @return array * @throws FireflyException @@ -264,9 +262,9 @@ class RecurrenceTransformer extends AbstractTransformer default: throw new FireflyException(sprintf('Recurrence transformer cant handle field "%s"', $transactionMeta->name)); case 'bill_id': - $bill = $this->billRepos->find((int) $transactionMeta->value); + $bill = $this->billRepos->find((int)$transactionMeta->value); if (null !== $bill) { - $array['bill_id'] = (string) $bill->id; + $array['bill_id'] = (string)$bill->id; $array['bill_name'] = $bill->name; } break; @@ -274,30 +272,30 @@ class RecurrenceTransformer extends AbstractTransformer $array['tags'] = json_decode($transactionMeta->value); break; case 'piggy_bank_id': - $piggy = $this->piggyRepos->find((int) $transactionMeta->value); + $piggy = $this->piggyRepos->find((int)$transactionMeta->value); if (null !== $piggy) { - $array['piggy_bank_id'] = (string) $piggy->id; + $array['piggy_bank_id'] = (string)$piggy->id; $array['piggy_bank_name'] = $piggy->name; } break; case 'category_id': - $category = $this->factory->findOrCreate((int) $transactionMeta->value, null); + $category = $this->factory->findOrCreate((int)$transactionMeta->value, null); if (null !== $category) { - $array['category_id'] = (string) $category->id; + $array['category_id'] = (string)$category->id; $array['category_name'] = $category->name; } break; case 'category_name': $category = $this->factory->findOrCreate(null, $transactionMeta->value); if (null !== $category) { - $array['category_id'] = (string) $category->id; + $array['category_id'] = (string)$category->id; $array['category_name'] = $category->name; } break; case 'budget_id': - $budget = $this->budgetRepos->find((int) $transactionMeta->value); + $budget = $this->budgetRepos->find((int)$transactionMeta->value); if (null !== $budget) { - $array['budget_id'] = (string) $budget->id; + $array['budget_id'] = (string)$budget->id; $array['budget_name'] = $budget->name; } break; @@ -306,5 +304,4 @@ class RecurrenceTransformer extends AbstractTransformer return $array; } - } diff --git a/app/Transformers/RuleGroupTransformer.php b/app/Transformers/RuleGroupTransformer.php index 61748c86f6..0c7f4ba1c1 100644 --- a/app/Transformers/RuleGroupTransformer.php +++ b/app/Transformers/RuleGroupTransformer.php @@ -30,18 +30,17 @@ use FireflyIII\Models\RuleGroup; */ class RuleGroupTransformer extends AbstractTransformer { - /** * Transform the rule group * - * @param RuleGroup $ruleGroup + * @param RuleGroup $ruleGroup * * @return array */ public function transform(RuleGroup $ruleGroup): array { return [ - 'id' => (int) $ruleGroup->id, + 'id' => (int)$ruleGroup->id, 'created_at' => $ruleGroup->created_at->toAtomString(), 'updated_at' => $ruleGroup->updated_at->toAtomString(), 'title' => $ruleGroup->title, @@ -51,7 +50,7 @@ class RuleGroupTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/rule_groups/' . $ruleGroup->id, + 'uri' => '/rule_groups/'.$ruleGroup->id, ], ], ]; diff --git a/app/Transformers/RuleTransformer.php b/app/Transformers/RuleTransformer.php index b338bb767b..459dce79fe 100644 --- a/app/Transformers/RuleTransformer.php +++ b/app/Transformers/RuleTransformer.php @@ -50,7 +50,7 @@ class RuleTransformer extends AbstractTransformer /** * Transform the rule. * - * @param Rule $rule + * @param Rule $rule * * @return array * @throws FireflyException @@ -60,14 +60,14 @@ class RuleTransformer extends AbstractTransformer $this->ruleRepository->setUser($rule->user); return [ - 'id' => (string) $rule->id, + 'id' => (string)$rule->id, 'created_at' => $rule->created_at->toAtomString(), 'updated_at' => $rule->updated_at->toAtomString(), - 'rule_group_id' => (string) $rule->rule_group_id, - 'rule_group_title' => (string) $rule->ruleGroup->title, + 'rule_group_id' => (string)$rule->rule_group_id, + 'rule_group_title' => (string)$rule->ruleGroup->title, 'title' => $rule->title, 'description' => $rule->description, - 'order' => (int) $rule->order, + 'order' => (int)$rule->order, 'active' => $rule->active, 'strict' => $rule->strict, 'stop_processing' => $rule->stop_processing, @@ -77,14 +77,14 @@ class RuleTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/rules/' . $rule->id, + 'uri' => '/rules/'.$rule->id, ], ], ]; } /** - * @param Rule $rule + * @param Rule $rule * * @return string * @throws FireflyException @@ -107,7 +107,7 @@ class RuleTransformer extends AbstractTransformer } /** - * @param Rule $rule + * @param Rule $rule * * @return array */ @@ -121,7 +121,7 @@ class RuleTransformer extends AbstractTransformer continue; } $result[] = [ - 'id' => (string) $ruleTrigger->id, + 'id' => (string)$ruleTrigger->id, 'created_at' => $ruleTrigger->created_at->toAtomString(), 'updated_at' => $ruleTrigger->updated_at->toAtomString(), 'type' => $ruleTrigger->trigger_type, @@ -136,7 +136,7 @@ class RuleTransformer extends AbstractTransformer } /** - * @param Rule $rule + * @param Rule $rule * * @return array */ @@ -147,7 +147,7 @@ class RuleTransformer extends AbstractTransformer /** @var RuleAction $ruleAction */ foreach ($actions as $ruleAction) { $result[] = [ - 'id' => (string) $ruleAction->id, + 'id' => (string)$ruleAction->id, 'created_at' => $ruleAction->created_at->toAtomString(), 'updated_at' => $ruleAction->updated_at->toAtomString(), 'type' => $ruleAction->action_type, diff --git a/app/Transformers/TagTransformer.php b/app/Transformers/TagTransformer.php index b4c09c6560..ca650b4463 100644 --- a/app/Transformers/TagTransformer.php +++ b/app/Transformers/TagTransformer.php @@ -31,13 +31,12 @@ use FireflyIII\Models\Tag; */ class TagTransformer extends AbstractTransformer { - /** * Transform a tag. * - * See reference nr. 21 + * TODO add spent, earned, transferred, etc. * - * @param Tag $tag + * @param Tag $tag * * @return array */ @@ -52,11 +51,11 @@ class TagTransformer extends AbstractTransformer if (null !== $location) { $latitude = $location->latitude; $longitude = $location->longitude; - $zoomLevel = (int) $location->zoom_level; + $zoomLevel = (int)$location->zoom_level; } return [ - 'id' => (int) $tag->id, + 'id' => (int)$tag->id, 'created_at' => $tag->created_at->toAtomString(), 'updated_at' => $tag->updated_at->toAtomString(), 'tag' => $tag->tag, @@ -68,10 +67,9 @@ class TagTransformer extends AbstractTransformer 'links' => [ [ 'rel' => 'self', - 'uri' => '/tags/' . $tag->id, + 'uri' => '/tags/'.$tag->id, ], ], ]; } - } diff --git a/app/Transformers/TransactionGroupTransformer.php b/app/Transformers/TransactionGroupTransformer.php index 1e945a135b..0f055f1382 100644 --- a/app/Transformers/TransactionGroupTransformer.php +++ b/app/Transformers/TransactionGroupTransformer.php @@ -56,16 +56,29 @@ class TransactionGroupTransformer extends AbstractTransformer { $this->groupRepos = app(TransactionGroupRepositoryInterface::class); $this->metaFields = [ - 'sepa_cc', 'sepa_ct_op', 'sepa_ct_id', 'sepa_db', 'sepa_country', 'sepa_ep', - 'sepa_ci', 'sepa_batch_id', 'internal_reference', 'bunq_payment_id', 'import_hash_v2', - 'recurrence_id', 'external_id', 'original_source', 'external_url', - 'recurrence_count', 'recurrence_total', + 'sepa_cc', + 'sepa_ct_op', + 'sepa_ct_id', + 'sepa_db', + 'sepa_country', + 'sepa_ep', + 'sepa_ci', + 'sepa_batch_id', + 'internal_reference', + 'bunq_payment_id', + 'import_hash_v2', + 'recurrence_id', + 'external_id', + 'original_source', + 'external_url', + 'recurrence_count', + 'recurrence_total', ]; $this->metaDateFields = ['interest_date', 'book_date', 'process_date', 'due_date', 'payment_date', 'invoice_date']; } /** - * @param array $group + * @param array $group * * @return array */ @@ -75,23 +88,23 @@ class TransactionGroupTransformer extends AbstractTransformer $first = new NullArrayObject(reset($group['transactions'])); return [ - 'id' => (int) $first['transaction_group_id'], + 'id' => (int)$first['transaction_group_id'], 'created_at' => $first['created_at']->toAtomString(), 'updated_at' => $first['updated_at']->toAtomString(), - 'user' => (string) $data['user_id'], + 'user' => (string)$data['user_id'], 'group_title' => $data['title'], 'transactions' => $this->transformTransactions($data), 'links' => [ [ 'rel' => 'self', - 'uri' => '/transactions/' . $first['transaction_group_id'], + 'uri' => '/transactions/'.$first['transaction_group_id'], ], ], ]; } /** - * @param NullArrayObject $data + * @param NullArrayObject $data * * @return array */ @@ -107,7 +120,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param array $transaction + * @param array $transaction * * @return array */ @@ -116,20 +129,21 @@ class TransactionGroupTransformer extends AbstractTransformer $row = new NullArrayObject($transaction); // amount: - $type = $this->stringFromArray($transaction, 'transaction_type_type', TransactionType::WITHDRAWAL); $amount = app('steam')->positive((string)($row['amount'] ?? '0')); $foreignAmount = null; if (null !== $row['foreign_amount'] && '' !== $row['foreign_amount'] && bccomp('0', $row['foreign_amount']) !== 0) { $foreignAmount = app('steam')->positive($row['foreign_amount']); } - $metaFieldData = $this->groupRepos->getMetaFields((int) $row['transaction_journal_id'], $this->metaFields); - $metaDateData = $this->groupRepos->getMetaDateFields((int) $row['transaction_journal_id'], $this->metaDateFields); + $metaFieldData = $this->groupRepos->getMetaFields((int)$row['transaction_journal_id'], $this->metaFields); + $metaDateData = $this->groupRepos->getMetaDateFields((int)$row['transaction_journal_id'], $this->metaDateFields); + $type = $this->stringFromArray($transaction, 'transaction_type_type', TransactionType::WITHDRAWAL); + $longitude = null; $latitude = null; $zoomLevel = null; - $location = $this->getLocationById((int) $row['transaction_journal_id']); + $location = $this->getLocationById((int)$row['transaction_journal_id']); if (null !== $location) { $longitude = $location->longitude; $latitude = $location->latitude; @@ -137,17 +151,17 @@ class TransactionGroupTransformer extends AbstractTransformer } return [ - 'user' => (string) $row['user_id'], - 'transaction_journal_id' => (string) $row['transaction_journal_id'], + 'user' => (string)$row['user_id'], + 'transaction_journal_id' => (string)$row['transaction_journal_id'], 'type' => strtolower($type), 'date' => $row['date']->toAtomString(), 'order' => $row['order'], - 'currency_id' => (string) $row['currency_id'], + 'currency_id' => (string)$row['currency_id'], 'currency_code' => $row['currency_code'], 'currency_name' => $row['currency_name'], 'currency_symbol' => $row['currency_symbol'], - 'currency_decimal_places' => (int) $row['currency_decimal_places'], + 'currency_decimal_places' => (int)$row['currency_decimal_places'], 'foreign_currency_id' => $this->stringFromArray($transaction, 'foreign_currency_id', null), 'foreign_currency_code' => $row['foreign_currency_code'], @@ -159,12 +173,12 @@ class TransactionGroupTransformer extends AbstractTransformer 'description' => $row['description'], - 'source_id' => (string) $row['source_account_id'], + 'source_id' => (string)$row['source_account_id'], 'source_name' => $row['source_account_name'], 'source_iban' => $row['source_account_iban'], 'source_type' => $row['source_account_type'], - 'destination_id' => (string) $row['destination_account_id'], + 'destination_id' => (string)$row['destination_account_id'], 'destination_name' => $row['destination_account_name'], 'destination_iban' => $row['destination_account_iban'], 'destination_type' => $row['destination_account_type'], @@ -179,8 +193,8 @@ class TransactionGroupTransformer extends AbstractTransformer 'bill_name' => $row['bill_name'], 'reconciled' => $row['reconciled'], - 'notes' => $this->groupRepos->getNoteText((int) $row['transaction_journal_id']), - 'tags' => $this->groupRepos->getTags((int) $row['transaction_journal_id']), + 'notes' => $this->groupRepos->getNoteText((int)$row['transaction_journal_id']), + 'tags' => $this->groupRepos->getTags((int)$row['transaction_journal_id']), 'internal_reference' => $metaFieldData['internal_reference'], 'external_id' => $metaFieldData['external_id'], @@ -213,14 +227,14 @@ class TransactionGroupTransformer extends AbstractTransformer 'latitude' => $latitude, 'zoom_level' => $zoomLevel, - 'has_attachments' => $this->hasAttachments((int) $row['transaction_journal_id']), + 'has_attachments' => $this->hasAttachments((int)$row['transaction_journal_id']), ]; } /** - * @param array $array - * @param string $key - * @param string|null $default + * @param array $array + * @param string $key + * @param string|null $default * * @return string|null */ @@ -230,18 +244,18 @@ class TransactionGroupTransformer extends AbstractTransformer return null; } if (array_key_exists($key, $array) && null !== $array[$key]) { - return (string) $array[$key]; + return (string)$array[$key]; } if (null !== $default) { - return (string) $default; + return (string)$default; } return null; } /** - * @param int $journalId + * @param int $journalId * * @return Location|null */ @@ -251,23 +265,33 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param array $array - * @param string $key + * @param TransactionJournal $journal + * + * @return Location|null + */ + private function getLocation(TransactionJournal $journal): ?Location + { + return $journal->locations()->first(); + } + + /** + * @param array $array + * @param string $key * * @return int|null */ private function integerFromArray(array $array, string $key): ?int { if (array_key_exists($key, $array)) { - return (int) $array[$key]; + return (int)$array[$key]; } return null; } /** - * @param NullArrayObject $object - * @param string $key + * @param NullArrayObject $object + * @param string $key * * @return string|null */ @@ -281,7 +305,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param int $journalId + * @param int $journalId * * @return bool */ @@ -291,7 +315,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param TransactionGroup $group + * @param TransactionGroup $group * * @return array * @throws FireflyException @@ -300,16 +324,16 @@ class TransactionGroupTransformer extends AbstractTransformer { try { $result = [ - 'id' => (int) $group->id, + 'id' => (int)$group->id, 'created_at' => $group->created_at->toAtomString(), 'updated_at' => $group->updated_at->toAtomString(), - 'user' => (int) $group->user_id, + 'user' => (int)$group->user_id, 'group_title' => $group->title, 'transactions' => $this->transformJournals($group->transactionJournals), 'links' => [ [ 'rel' => 'self', - 'uri' => '/transactions/' . $group->id, + 'uri' => '/transactions/'.$group->id, ], ], ]; @@ -325,7 +349,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param Collection $transactionJournals + * @param Collection $transactionJournals * * @return array * @throws FireflyException @@ -342,7 +366,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return array * @throws FireflyException @@ -352,8 +376,8 @@ class TransactionGroupTransformer extends AbstractTransformer $source = $this->getSourceTransaction($journal); $destination = $this->getDestinationTransaction($journal); $type = $journal->transactionType->type; - $amount = $this->getAmount($type, (string) $source->amount); - $foreignAmount = $this->getForeignAmount($type, null === $source->foreign_amount ? null : (string) $source->foreign_amount); + $amount = $this->getAmount($type, (string)$source->amount); + $foreignAmount = $this->getForeignAmount($type, null === $source->foreign_amount ? null : (string)$source->foreign_amount); $metaFieldData = $this->groupRepos->getMetaFields($journal->id, $this->metaFields); $metaDates = $this->getDates($this->groupRepos->getMetaDateFields($journal->id, $this->metaDateFields)); $currency = $source->transactionCurrency; @@ -377,16 +401,16 @@ class TransactionGroupTransformer extends AbstractTransformer } return [ - 'user' => (int) $journal->user_id, - 'transaction_journal_id' => (int) $journal->id, + 'user' => (int)$journal->user_id, + 'transaction_journal_id' => (int)$journal->id, 'type' => strtolower($type), 'date' => $journal->date->toAtomString(), 'order' => $journal->order, - 'currency_id' => (int) $currency->id, + 'currency_id' => (int)$currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, - 'currency_decimal_places' => (int) $currency->decimal_places, + 'currency_decimal_places' => (int)$currency->decimal_places, 'foreign_currency_id' => $foreignCurrency['id'], 'foreign_currency_code' => $foreignCurrency['code'], @@ -398,12 +422,12 @@ class TransactionGroupTransformer extends AbstractTransformer 'description' => $journal->description, - 'source_id' => (int) $source->account_id, + 'source_id' => (int)$source->account_id, 'source_name' => $source->account->name, 'source_iban' => $source->account->iban, 'source_type' => $source->account->accountType->type, - 'destination_id' => (int) $destination->account_id, + 'destination_id' => (int)$destination->account_id, 'destination_name' => $destination->account->name, 'destination_iban' => $destination->account->iban, 'destination_type' => $destination->account->accountType->type, @@ -452,7 +476,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Transaction * @throws FireflyException @@ -461,7 +485,7 @@ class TransactionGroupTransformer extends AbstractTransformer { $result = $journal->transactions->first( static function (Transaction $transaction) { - return (float) $transaction->amount < 0; // lame but it works. + return (float)$transaction->amount < 0; // lame but it works. } ); if (null === $result) { @@ -472,7 +496,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param TransactionJournal $journal + * @param TransactionJournal $journal * * @return Transaction * @throws FireflyException @@ -481,7 +505,7 @@ class TransactionGroupTransformer extends AbstractTransformer { $result = $journal->transactions->first( static function (Transaction $transaction) { - return (float) $transaction->amount > 0; // lame but it works + return (float)$transaction->amount > 0; // lame but it works } ); if (null === $result) { @@ -492,8 +516,8 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param string $type - * @param string $amount + * @param string $type + * @param string $amount * * @return string */ @@ -508,8 +532,8 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param string $type - * @param string|null $foreignAmount + * @param string $type + * @param string|null $foreignAmount * * @return string|null */ @@ -524,7 +548,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param NullArrayObject $dates + * @param NullArrayObject $dates * * @return array */ @@ -550,7 +574,7 @@ class TransactionGroupTransformer extends AbstractTransformer } /** - * @param TransactionCurrency|null $currency + * @param TransactionCurrency|null $currency * * @return array */ @@ -565,16 +589,16 @@ class TransactionGroupTransformer extends AbstractTransformer if (null === $currency) { return $array; } - $array['id'] = (int) $currency->id; + $array['id'] = (int)$currency->id; $array['code'] = $currency->code; $array['symbol'] = $currency->symbol; - $array['decimal_places'] = (int) $currency->decimal_places; + $array['decimal_places'] = (int)$currency->decimal_places; return $array; } /** - * @param Budget|null $budget + * @param Budget|null $budget * * @return array */ @@ -587,14 +611,14 @@ class TransactionGroupTransformer extends AbstractTransformer if (null === $budget) { return $array; } - $array['id'] = (int) $budget->id; + $array['id'] = (int)$budget->id; $array['name'] = $budget->name; return $array; } /** - * @param Category|null $category + * @param Category|null $category * * @return array */ @@ -607,14 +631,14 @@ class TransactionGroupTransformer extends AbstractTransformer if (null === $category) { return $array; } - $array['id'] = (int) $category->id; + $array['id'] = (int)$category->id; $array['name'] = $category->name; return $array; } /** - * @param Bill|null $bill + * @param Bill|null $bill * * @return array */ @@ -627,19 +651,9 @@ class TransactionGroupTransformer extends AbstractTransformer if (null === $bill) { return $array; } - $array['id'] = (string) $bill->id; + $array['id'] = (string)$bill->id; $array['name'] = $bill->name; return $array; } - - /** - * @param TransactionJournal $journal - * - * @return Location|null - */ - private function getLocation(TransactionJournal $journal): ?Location - { - return $journal->locations()->first(); - } } diff --git a/app/Transformers/TransactionLinkTransformer.php b/app/Transformers/TransactionLinkTransformer.php index e8a865e93d..47185d812d 100644 --- a/app/Transformers/TransactionLinkTransformer.php +++ b/app/Transformers/TransactionLinkTransformer.php @@ -46,7 +46,7 @@ class TransactionLinkTransformer extends AbstractTransformer } /** - * @param TransactionJournalLink $link + * @param TransactionJournalLink $link * * @return array */ @@ -55,17 +55,17 @@ class TransactionLinkTransformer extends AbstractTransformer $notes = $this->repository->getLinkNoteText($link); return [ - 'id' => (string) $link->id, + 'id' => (string)$link->id, 'created_at' => $link->created_at->toAtomString(), 'updated_at' => $link->updated_at->toAtomString(), - 'inward_id' => (string) $link->source_id, - 'outward_id' => (string) $link->destination_id, - 'link_type_id' => (string) $link->link_type_id, + 'inward_id' => (string)$link->source_id, + 'outward_id' => (string)$link->destination_id, + 'link_type_id' => (string)$link->link_type_id, 'notes' => '' === $notes ? null : $notes, 'links' => [ [ 'rel' => 'self', - 'uri' => '/transaction_links/' . $link->id, + 'uri' => '/transaction_links/'.$link->id, ], ], ]; diff --git a/app/Transformers/UserTransformer.php b/app/Transformers/UserTransformer.php index 8b8ca5b5ee..a24f521251 100644 --- a/app/Transformers/UserTransformer.php +++ b/app/Transformers/UserTransformer.php @@ -37,7 +37,7 @@ class UserTransformer extends AbstractTransformer /** * Transform user. * - * @param User $user + * @param User $user * * @return array */ @@ -46,20 +46,19 @@ class UserTransformer extends AbstractTransformer $this->repository = $this->repository ?? app(UserRepositoryInterface::class); return [ - 'id' => (int) $user->id, + 'id' => (int)$user->id, 'created_at' => $user->created_at->toAtomString(), 'updated_at' => $user->updated_at->toAtomString(), 'email' => $user->email, - 'blocked' => 1 === (int) $user->blocked, + 'blocked' => 1 === (int)$user->blocked, 'blocked_code' => '' === $user->blocked_code ? null : $user->blocked_code, 'role' => $this->repository->getRoleByUser($user), 'links' => [ [ 'rel' => 'self', - 'uri' => '/users/' . $user->id, + 'uri' => '/users/'.$user->id, ], ], ]; } - } diff --git a/app/Transformers/V2/AbstractTransformer.php b/app/Transformers/V2/AbstractTransformer.php new file mode 100644 index 0000000000..6a46d8f1b5 --- /dev/null +++ b/app/Transformers/V2/AbstractTransformer.php @@ -0,0 +1,60 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers\V2; + +use Illuminate\Support\Collection; +use League\Fractal\TransformerAbstract; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class AbstractTransformer + */ +abstract class AbstractTransformer extends TransformerAbstract +{ + protected ParameterBag $parameters; + + /** + * @param Collection $objects + * @return void + */ + abstract public function collectMetaData(Collection $objects): void; + + + /** + * @return ParameterBag + */ + final public function getParameters(): ParameterBag + { + return $this->parameters; + } + + /** + * @param ParameterBag $parameters + */ + final public function setParameters(ParameterBag $parameters): void + { + $this->parameters = $parameters; + } +} diff --git a/app/Transformers/V2/AccountTransformer.php b/app/Transformers/V2/AccountTransformer.php new file mode 100644 index 0000000000..4c534a5dd0 --- /dev/null +++ b/app/Transformers/V2/AccountTransformer.php @@ -0,0 +1,149 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers\V2; + +use Carbon\Carbon; +use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Models\Account; +use FireflyIII\Models\AccountMeta; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; +use Illuminate\Support\Collection; + +/** + * Class AccountTransformer + */ +class AccountTransformer extends AbstractTransformer +{ + private array $accountMeta; + private array $balances; + private array $currencies; + private ?TransactionCurrency $currency; + + /** + * @inheritDoc + * @throws FireflyException + */ + public function collectMetaData(Collection $objects): void + { + $this->currency = null; + $this->currencies = []; + $this->accountMeta = []; + $this->balances = app('steam')->balancesByAccounts($objects, $this->getDate()); + $repository = app(CurrencyRepositoryInterface::class); + $this->currency = app('amount')->getDefaultCurrency(); + + // get currencies: + $accountIds = $objects->pluck('id')->toArray(); + $meta = AccountMeta::whereIn('account_id', $accountIds) + ->where('name', 'currency_id') + ->get(['account_meta.id', 'account_meta.account_id', 'account_meta.name', 'account_meta.data']); + $currencyIds = $meta->pluck('data')->toArray(); + + $currencies = $repository->getByIds($currencyIds); + foreach ($currencies as $currency) { + $id = (int)$currency->id; + $this->currencies[$id] = $currency; + } + foreach ($meta as $entry) { + $id = (int)$entry->account_id; + $this->accountMeta[$id][$entry->name] = $entry->data; + } + } + + /** + * Transform the account. + * + * @param Account $account + * + * @return array + */ + public function transform(Account $account): array + { + //$fullType = $account->accountType->type; + //$accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType)); + $id = (int)$account->id; + + // no currency? use default + $currency = $this->currency; + if (0 !== (int)$this->accountMeta[$id]['currency_id']) { + $currency = $this->currencies[(int)$this->accountMeta[$id]['currency_id']]; + } + + return [ + 'id' => (string)$account->id, + 'created_at' => $account->created_at->toAtomString(), + 'updated_at' => $account->updated_at->toAtomString(), + 'active' => $account->active, + //'order' => $order, + 'name' => $account->name, + // 'type' => strtolower($accountType), + // 'account_role' => $accountRole, + 'currency_id' => $currency->id, + 'currency_code' => $currency->code, + 'currency_symbol' => $currency->symbol, + 'currency_decimal_places' => $currency->decimal_places, + 'current_balance' => $this->balances[$id] ?? null, + 'current_balance_date' => $this->getDate(), + // 'notes' => $this->repository->getNoteText($account), + // 'monthly_payment_date' => $monthlyPaymentDate, + // 'credit_card_type' => $creditCardType, + // 'account_number' => $this->repository->getMetaValue($account, 'account_number'), + 'iban' => '' === $account->iban ? null : $account->iban, + // 'bic' => $this->repository->getMetaValue($account, 'BIC'), + // 'virtual_balance' => number_format((float) $account->virtual_balance, $decimalPlaces, '.', ''), + // 'opening_balance' => $openingBalance, + // 'opening_balance_date' => $openingBalanceDate, + // 'liability_type' => $liabilityType, + // 'liability_direction' => $liabilityDirection, + // 'interest' => $interest, + // 'interest_period' => $interestPeriod, + // 'current_debt' => $this->repository->getMetaValue($account, 'current_debt'), + // 'include_net_worth' => $includeNetWorth, + // 'longitude' => $longitude, + // 'latitude' => $latitude, + // 'zoom_level' => $zoomLevel, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => '/accounts/'.$account->id, + ], + ], + ]; + } + + /** + * @return Carbon + */ + private function getDate(): Carbon + { + $date = today(config('app.timezone')); + if (null !== $this->parameters->get('date')) { + $date = $this->parameters->get('date'); + } + + return $date; + } +} diff --git a/app/Transformers/V2/BudgetLimitTransformer.php b/app/Transformers/V2/BudgetLimitTransformer.php new file mode 100644 index 0000000000..470410cab7 --- /dev/null +++ b/app/Transformers/V2/BudgetLimitTransformer.php @@ -0,0 +1,115 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers\V2; + +use FireflyIII\Models\BudgetLimit; +use Illuminate\Support\Collection; +use League\Fractal\Resource\Item; + +/** + * Class BudgetLimitTransformer + */ +class BudgetLimitTransformer extends AbstractTransformer +{ + /** @var string[] */ + protected array $availableIncludes + = [ + 'budget', + ]; + + /** + * @inheritDoc + */ + public function collectMetaData(Collection $objects): void + { + // TODO: Implement collectMetaData() method. + } + + /** + * Include Budget + * + * @param BudgetLimit $limit + * + * @return Item + */ + public function includeBudget(BudgetLimit $limit) + { + return $this->item($limit->budget, new BudgetTransformer(), 'budgets'); + } + + /** + * Transform the note. + * + * @param BudgetLimit $budgetLimit + * + * @return array + */ + public function transform(BudgetLimit $budgetLimit): array + { +// $repository = app(OperationsRepository::class); +// $repository->setUser($budgetLimit->budget->user); +// $expenses = $repository->sumExpenses( +// $budgetLimit->start_date, $budgetLimit->end_date, null, new Collection([$budgetLimit->budget]), $budgetLimit->transactionCurrency +// ); + $currency = $budgetLimit->transactionCurrency; + $amount = $budgetLimit->amount; + $currencyDecimalPlaces = 2; + $currencyId = null; + $currencyName = null; + $currencyCode = null; + $currencySymbol = null; + if (null !== $currency) { + $amount = $budgetLimit->amount; + $currencyId = (int)$currency->id; + $currencyName = $currency->name; + $currencyCode = $currency->code; + $currencySymbol = $currency->symbol; + $currencyDecimalPlaces = $currency->decimal_places; + } + $amount = number_format((float)$amount, $currencyDecimalPlaces, '.', ''); + + return [ + 'id' => (string)$budgetLimit->id, + 'created_at' => $budgetLimit->created_at->toAtomString(), + 'updated_at' => $budgetLimit->updated_at->toAtomString(), + 'start' => $budgetLimit->start_date->toAtomString(), + 'end' => $budgetLimit->end_date->endOfDay()->toAtomString(), + 'budget_id' => (string)$budgetLimit->budget_id, + 'currency_id' => (string)$currencyId, + 'currency_code' => $currencyCode, + 'currency_name' => $currencyName, + 'currency_decimal_places' => $currencyDecimalPlaces, + 'currency_symbol' => $currencySymbol, + 'amount' => $amount, + 'period' => $budgetLimit->period, + //'spent' => $expenses[$currencyId]['sum'] ?? '0', + 'links' => [ + [ + 'rel' => 'self', + 'uri' => sprintf('/budget-limits/%d', $budgetLimit->id), + ], + ], + ]; + } +} diff --git a/app/Transformers/V2/BudgetTransformer.php b/app/Transformers/V2/BudgetTransformer.php new file mode 100644 index 0000000000..80793dd5d0 --- /dev/null +++ b/app/Transformers/V2/BudgetTransformer.php @@ -0,0 +1,134 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers\V2; + +use FireflyIII\Models\Budget; +use Illuminate\Support\Collection; +use Symfony\Component\HttpFoundation\ParameterBag; + +/** + * Class BudgetTransformer + */ +class BudgetTransformer extends AbstractTransformer +{ + //private OperationsRepositoryInterface $opsRepository; + //private BudgetRepositoryInterface $repository; + + /** + * BudgetTransformer constructor. + * + * @codeCoverageIgnore + */ + public function __construct() + { + //$this->opsRepository = app(OperationsRepositoryInterface::class); + //$this->repository = app(BudgetRepositoryInterface::class); + $this->parameters = new ParameterBag(); + } + + /** + * @inheritDoc + */ + public function collectMetaData(Collection $objects): void + { + // TODO: Implement collectMetaData() method. + } + + /** + * Transform a budget. + * + * @param Budget $budget + * + * @return array + */ + public function transform(Budget $budget): array + { + //$this->opsRepository->setUser($budget->user); + $start = $this->parameters->get('start'); + $end = $this->parameters->get('end'); + //$autoBudget = $this->repository->getAutoBudget($budget); +// $spent = []; +// if (null !== $start && null !== $end) { +// $spent = $this->beautify($this->opsRepository->sumExpenses($start, $end, null, new Collection([$budget]))); +// } + +// $abCurrencyId = null; +// $abCurrencyCode = null; +// $abType = null; +// $abAmount = null; +// $abPeriod = null; +// $notes = $this->repository->getNoteText($budget); +// +// $types = [ +// AutoBudget::AUTO_BUDGET_RESET => 'reset', +// AutoBudget::AUTO_BUDGET_ROLLOVER => 'rollover', +// ]; +// +// if (null !== $autoBudget) { +// $abCurrencyId = (string) $autoBudget->transactionCurrency->id; +// $abCurrencyCode = $autoBudget->transactionCurrency->code; +// $abType = $types[$autoBudget->auto_budget_type]; +// $abAmount = number_format((float) $autoBudget->amount, $autoBudget->transactionCurrency->decimal_places, '.', ''); +// $abPeriod = $autoBudget->period; +// } + + return [ + 'id' => (string)$budget->id, + 'created_at' => $budget->created_at->toAtomString(), + 'updated_at' => $budget->updated_at->toAtomString(), + 'active' => $budget->active, + 'name' => $budget->name, + 'order' => $budget->order, + // 'notes' => $notes, + // 'auto_budget_type' => $abType, + // 'auto_budget_period' => $abPeriod, + // 'auto_budget_currency_id' => $abCurrencyId, + // 'auto_budget_currency_code' => $abCurrencyCode, + // 'auto_budget_amount' => $abAmount, + // 'spent' => $spent, + 'links' => [ + [ + 'rel' => 'self', + 'uri' => sprintf('/budgets/%d', $budget->id), + ], + ], + ]; + } + + /** + * @param array $array + * + * @return array + */ + private function beautify(array $array): array + { + $return = []; + foreach ($array as $data) { + $data['sum'] = number_format((float)$data['sum'], (int)$data['currency_decimal_places'], '.', ''); + $return[] = $data; + } + + return $return; + } +} diff --git a/app/Transformers/V2/PreferenceTransformer.php b/app/Transformers/V2/PreferenceTransformer.php new file mode 100644 index 0000000000..20e8fc1671 --- /dev/null +++ b/app/Transformers/V2/PreferenceTransformer.php @@ -0,0 +1,59 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers\V2; + +use FireflyIII\Models\Preference; +use Illuminate\Support\Collection; + +/** + * Class PreferenceTransformer + */ +class PreferenceTransformer extends AbstractTransformer +{ + /** + * @inheritDoc + */ + public function collectMetaData(Collection $objects): void + { + // TODO: Implement collectMetaData() method. + } + + /** + * Transform the preference + * + * @param Preference $preference + * + * @return array + */ + public function transform(Preference $preference): array + { + return [ + 'id' => (int)$preference->id, + 'created_at' => $preference->created_at->toAtomString(), + 'updated_at' => $preference->updated_at->toAtomString(), + 'name' => $preference->name, + 'data' => $preference->data, + ]; + } +} diff --git a/app/Transformers/V2/TransactionGroupTransformer.php b/app/Transformers/V2/TransactionGroupTransformer.php new file mode 100644 index 0000000000..20b88d7485 --- /dev/null +++ b/app/Transformers/V2/TransactionGroupTransformer.php @@ -0,0 +1,271 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Transformers\V2; + +use Carbon\Carbon; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\Models\TransactionJournalMeta; +use FireflyIII\Models\TransactionType; +use FireflyIII\Support\Http\Api\ConvertsExchangeRates; +use FireflyIII\Support\NullArrayObject; +use Illuminate\Support\Collection; +use Illuminate\Support\Facades\Log; + +/** + * Class TransactionGroupTransformer + */ +class TransactionGroupTransformer extends AbstractTransformer +{ + use ConvertsExchangeRates; + + private array $currencies = []; + private TransactionCurrency $default; + private array $meta; + + /** + * @inheritDoc + */ + public function collectMetaData(Collection $objects): void + { + // start with currencies: + $currencies = []; + $journals = []; + /** @var array $object */ + foreach ($objects as $object) { + foreach ($object['sums'] as $sum) { + $id = $sum['currency_id']; + if (!array_key_exists($id, $currencies)) { + $currencyObject = TransactionCurrency::find($sum['currency_id']); + $currencies[$id] = $currencyObject; + } + } + /** @var array $transaction */ + foreach ($object['transactions'] as $transaction) { + $id = $transaction['transaction_journal_id']; + $journals[$id] = []; + } + } + $this->currencies = $currencies; + $this->default = app('amount')->getDefaultCurrency(); + + // grab meta for all journals: + $meta = TransactionJournalMeta::whereIn('transaction_journal_id', array_keys($journals))->get(); + /** @var TransactionJournalMeta $entry */ + foreach ($meta as $entry) { + $id = (int)$entry->transaction_journal_id; + $this->meta[$id][$entry->name] = $entry->data; + } + } + + /** + * @param array $group + * + * @return array + */ + public function transform(array $group): array + { + $first = reset($group['transactions']); + return [ + 'id' => (string)$group['id'], + 'created_at' => $first['created_at']->toAtomString(), + 'updated_at' => $first['updated_at']->toAtomString(), + 'user' => (string)$first['user_id'], + 'group_title' => $group['title'] ?? null, + 'transactions' => $this->transformTransactions($group['transactions'] ?? []), + 'links' => [ + [ + 'rel' => 'self', + 'uri' => sprintf('/transactions/%d', $group['id']), + ], + ], + ]; + } + + /** + * @param array $transactions + * @return array + */ + private function transformTransactions(array $transactions): array + { + $return = []; + /** @var array $transaction */ + foreach ($transactions as $transaction) { + $return[] = $this->transformTransaction($transaction); + } + return $return; + } + + private function transformTransaction(array $transaction): array + { + $transaction = new NullArrayObject($transaction); + $journalId = (int)$transaction['transaction_journal_id']; + $meta = new NullArrayObject($this->meta[$journalId] ?? []); + $type = $this->stringFromArray($transaction, 'transaction_type_type', TransactionType::WITHDRAWAL); + $amount = app('steam')->positive((string)($transaction['amount'] ?? '0')); + $foreignAmount = null; + $nativeForeignAmount = null; + if (null !== $transaction['foreign_amount']) { + $foreignAmount = app('steam')->positive($transaction['foreign_amount']); + $nativeForeignAmount = $foreignAmount; + if ($transaction['foreign_currency_id'] !== $this->default->id) { + $rate = $this->getRate($this->currencies[$transaction['foreign_currency_id']], $this->default, $transaction['date']); + $nativeForeignAmount = bcmul($foreignAmount, $rate); + } + } + + $nativeAmount = $amount; + if ($transaction['currency_id'] !== $this->default->id) { + $rate = $this->getRate($this->currencies[$transaction['currency_id']], $this->default, $transaction['date']); + $nativeAmount = bcmul($amount, $rate); + } + + return [ + 'user' => (string)$transaction['user_id'], + 'transaction_journal_id' => (string)$transaction['transaction_journal_id'], + 'type' => strtolower($type), + 'date' => $transaction['date']->toAtomString(), + 'order' => $transaction['order'], + 'currency_id' => (string)$transaction['currency_id'], + 'currency_code' => $transaction['currency_code'], + 'currency_name' => $transaction['currency_name'], + 'currency_symbol' => $transaction['currency_symbol'], + 'currency_decimal_places' => (int)$transaction['currency_decimal_places'], + + // converted to native currency + 'native_currency_converted' => $transaction['currency_id'] !== $this->default->id, + 'native_currency_id' => (string)$this->default->id, + 'native_currency_code' => $this->default->code, + 'native_currency_name' => $this->default->name, + 'native_currency_symbol' => $this->default->symbol, + 'native_currency_decimal_places' => (int)$this->default->decimal_places, + + 'foreign_currency_id' => $this->stringFromArray($transaction, 'foreign_currency_id', null), + 'foreign_currency_code' => $transaction['foreign_currency_code'], + 'foreign_currency_name' => $transaction['foreign_currency_name'], + 'foreign_currency_symbol' => $transaction['foreign_currency_symbol'], + 'foreign_currency_decimal_places' => $transaction['foreign_currency_decimal_places'], + + // foreign converted to native currency: + 'foreign_currency_converted' => null !== $transaction['foreign_currency_id'] && $transaction['foreign_currency_id'] !== $this->default->id, + + 'amount' => $amount, + 'native_amount' => $nativeAmount, + 'foreign_amount' => $foreignAmount, + 'native_foreign_amount' => $nativeForeignAmount, + 'description' => $transaction['description'], + 'source_id' => (string)$transaction['source_account_id'], + 'source_name' => $transaction['source_account_name'], + 'source_iban' => $transaction['source_account_iban'], + 'source_type' => $transaction['source_account_type'], + 'destination_id' => (string)$transaction['destination_account_id'], + 'destination_name' => $transaction['destination_account_name'], + 'destination_iban' => $transaction['destination_account_iban'], + 'destination_type' => $transaction['destination_account_type'], + 'budget_id' => $this->stringFromArray($transaction, 'budget_id', null), + 'budget_name' => $transaction['budget_name'], + 'category_id' => $this->stringFromArray($transaction, 'category_id', null), + 'category_name' => $transaction['category_name'], + 'bill_id' => $this->stringFromArray($transaction, 'bill_id', null), + 'bill_name' => $transaction['bill_name'], + 'reconciled' => $transaction['reconciled'], + + //'notes' => $this->groupRepos->getNoteText((int) $row['transaction_journal_id']), + //'tags' => $this->groupRepos->getTags((int) $row['transaction_journal_id']), + + 'internal_reference' => $meta['internal_reference'], + 'external_id' => $meta['external_id'], + 'original_source' => $meta['original_source'], + 'recurrence_id' => $meta['recurrence_id'], + 'recurrence_total' => $meta['recurrence_total'], + 'recurrence_count' => $meta['recurrence_count'], + 'bunq_payment_id' => $meta['bunq_payment_id'], + 'external_url' => $meta['external_url'], + 'import_hash_v2' => $meta['import_hash_v2'], + 'sepa_cc' => $meta['sepa_cc'], + 'sepa_ct_op' => $meta['sepa_ct_op'], + 'sepa_ct_id' => $meta['sepa_ct_id'], + 'sepa_db' => $meta['sepa_db'], + 'sepa_country' => $meta['sepa_country'], + 'sepa_ep' => $meta['sepa_ep'], + 'sepa_ci' => $meta['sepa_ci'], + 'sepa_batch_id' => $meta['sepa_batch_id'], + + 'interest_date' => $this->date($meta['interest_date']), + 'book_date' => $this->date($meta['book_date']), + 'process_date' => $this->date($meta['process_date']), + 'due_date' => $this->date($meta['due_date']), + 'payment_date' => $this->date($meta['payment_date']), + 'invoice_date' => $this->date($meta['invoice_date']), + + // location data + // 'longitude' => $longitude, + // 'latitude' => $latitude, + // 'zoom_level' => $zoomLevel, + // + // 'has_attachments' => $this->hasAttachments((int) $row['transaction_journal_id']), + ]; + } + + /** + * TODO also in the old transformer. + * + * @param NullArrayObject $array + * @param string $key + * @param string|null $default + * + * @return string|null + */ + private function stringFromArray(NullArrayObject $array, string $key, ?string $default): ?string + { + if (null === $array[$key] && null === $default) { + return null; + } + if (null !== $array[$key]) { + return (string)$array[$key]; + } + + if (null !== $default) { + return $default; + } + + return null; + } + + /** + * @param string|null $string + * @return Carbon|null + */ + private function date(?string $string): ?Carbon + { + if (null === $string) { + return null; + } + Log::debug(sprintf('Now in date("%s")', $string)); + if(10 === strlen($string)) { + return Carbon::createFromFormat('Y-m-d', $string, config('app.timezone')); + } + return Carbon::createFromFormat('Y-m-d H:i:s', $string, config('app.timezone')); + } +} diff --git a/app/Transformers/WebhookAttemptTransformer.php b/app/Transformers/WebhookAttemptTransformer.php index a271a917d3..00fcb767d8 100644 --- a/app/Transformers/WebhookAttemptTransformer.php +++ b/app/Transformers/WebhookAttemptTransformer.php @@ -33,21 +33,20 @@ class WebhookAttemptTransformer extends AbstractTransformer /** * Transform the preference * - * @param WebhookAttempt $attempt + * @param WebhookAttempt $attempt * * @return array */ public function transform(WebhookAttempt $attempt): array { return [ - 'id' => (string) $attempt->id, + 'id' => (string)$attempt->id, 'created_at' => $attempt->created_at->toAtomString(), 'updated_at' => $attempt->updated_at->toAtomString(), - 'webhook_message_id' => (string) $attempt->webhook_message_id, - 'status_code' => (int) $attempt->status_code, + 'webhook_message_id' => (string)$attempt->webhook_message_id, + 'status_code' => (int)$attempt->status_code, 'logs' => $attempt->logs, 'response' => $attempt->response, ]; } - } diff --git a/app/Transformers/WebhookMessageTransformer.php b/app/Transformers/WebhookMessageTransformer.php index 9ed9c76d16..599738e2de 100644 --- a/app/Transformers/WebhookMessageTransformer.php +++ b/app/Transformers/WebhookMessageTransformer.php @@ -35,13 +35,12 @@ class WebhookMessageTransformer extends AbstractTransformer /** * Transform the preference * - * @param WebhookMessage $message + * @param WebhookMessage $message * * @return array */ public function transform(WebhookMessage $message): array { - $json = '{}'; try { $json = json_encode($message->message, JSON_THROW_ON_ERROR); @@ -50,15 +49,14 @@ class WebhookMessageTransformer extends AbstractTransformer } return [ - 'id' => (string) $message->id, + 'id' => (string)$message->id, 'created_at' => $message->created_at->toAtomString(), 'updated_at' => $message->updated_at->toAtomString(), 'sent' => $message->sent, 'errored' => $message->errored, - 'webhook_id' => (string) $message->webhook_id, + 'webhook_id' => (string)$message->webhook_id, 'uuid' => $message->uuid, 'message' => $json, ]; } - } diff --git a/app/Transformers/WebhookTransformer.php b/app/Transformers/WebhookTransformer.php index bc43d58c6c..63bc4a8dfa 100644 --- a/app/Transformers/WebhookTransformer.php +++ b/app/Transformers/WebhookTransformer.php @@ -24,6 +24,9 @@ declare(strict_types=1); namespace FireflyIII\Transformers; +use FireflyIII\Enums\WebhookDelivery; +use FireflyIII\Enums\WebhookResponse; +use FireflyIII\Enums\WebhookTrigger; use FireflyIII\Models\Webhook; /** @@ -38,29 +41,27 @@ class WebhookTransformer extends AbstractTransformer */ public function __construct() { - // array merge kills the keys - $this->enums = config('firefly.webhooks.triggers') + config('firefly.webhooks.responses') + config('firefly.webhooks.deliveries'); } /** * Transform webhook. * - * @param Webhook $webhook + * @param Webhook $webhook * * @return array */ public function transform(Webhook $webhook): array { return [ - 'id' => (int) $webhook->id, + 'id' => (int)$webhook->id, 'created_at' => $webhook->created_at->toAtomString(), 'updated_at' => $webhook->updated_at->toAtomString(), 'active' => $webhook->active, 'title' => $webhook->title, 'secret' => $webhook->secret, - 'trigger' => $this->getEnum($webhook->trigger), - 'response' => $this->getEnum($webhook->response), - 'delivery' => $this->getEnum($webhook->delivery), + 'trigger' => $this->getEnum('trigger', $webhook->trigger), + 'response' => $this->getEnum('response', $webhook->response), + 'delivery' => $this->getEnum('delivery', $webhook->delivery), 'url' => $webhook->url, 'links' => [ [ @@ -71,8 +72,19 @@ class WebhookTransformer extends AbstractTransformer ]; } - private function getEnum(int $value) + /** + * @param string $type + * @param int $value + * @return string + */ + private function getEnum(string $type, int $value): string { - return $this->enums[$value] ?? 'UNKNOWN_VALUE'; + if ('trigger' === $type) { + return WebhookTrigger::from($value)->name; + } + if ('response' === $type) { + return WebhookResponse::from($value)->name; + } + return WebhookDelivery::from($value)->name; } } diff --git a/app/User.php b/app/User.php index 5c0da04984..b4e0134ff0 100644 --- a/app/User.php +++ b/app/User.php @@ -48,6 +48,10 @@ use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; use FireflyIII\Models\UserGroup; use FireflyIII\Models\Webhook; +use FireflyIII\Notifications\Admin\TestNotification; +use FireflyIII\Notifications\Admin\UserInvitation; +use FireflyIII\Notifications\Admin\UserRegistration; +use FireflyIII\Notifications\Admin\VersionCheckResult; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsToMany; @@ -57,8 +61,10 @@ use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\DatabaseNotification; use Illuminate\Notifications\DatabaseNotificationCollection; use Illuminate\Notifications\Notifiable; +use Illuminate\Notifications\Notification; use Illuminate\Support\Carbon; use Illuminate\Support\Collection; +use Illuminate\Support\Str; use Laravel\Passport\Client; use Laravel\Passport\HasApiTokens; use Laravel\Passport\Token; @@ -68,39 +74,39 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * Class User. * - * @property int $id - * @property string $email - * @property bool $isAdmin - * @property bool $has2FA - * @property array $prefs - * @property string $password - * @property string $mfa_secret - * @property Collection $roles - * @property string $blocked_code - * @property bool $blocked - * @property Carbon|null $created_at - * @property Carbon|null $updated_at - * @property string|null $remember_token - * @property string|null $reset - * @property-read \Illuminate\Database\Eloquent\Collection|Account[] $accounts - * @property-read \Illuminate\Database\Eloquent\Collection|Attachment[] $attachments - * @property-read \Illuminate\Database\Eloquent\Collection|AvailableBudget[] $availableBudgets - * @property-read \Illuminate\Database\Eloquent\Collection|Bill[] $bills - * @property-read \Illuminate\Database\Eloquent\Collection|Budget[] $budgets - * @property-read \Illuminate\Database\Eloquent\Collection|Category[] $categories - * @property-read \Illuminate\Database\Eloquent\Collection|Client[] $clients + * @property int $id + * @property string $email + * @property bool $isAdmin + * @property bool $has2FA + * @property array $prefs + * @property string $password + * @property string $mfa_secret + * @property Collection $roles + * @property string $blocked_code + * @property bool $blocked + * @property Carbon|null $created_at + * @property Carbon|null $updated_at + * @property string|null $remember_token + * @property string|null $reset + * @property-read \Illuminate\Database\Eloquent\Collection|Account[] $accounts + * @property-read \Illuminate\Database\Eloquent\Collection|Attachment[] $attachments + * @property-read \Illuminate\Database\Eloquent\Collection|AvailableBudget[] $availableBudgets + * @property-read \Illuminate\Database\Eloquent\Collection|Bill[] $bills + * @property-read \Illuminate\Database\Eloquent\Collection|Budget[] $budgets + * @property-read \Illuminate\Database\Eloquent\Collection|Category[] $categories + * @property-read \Illuminate\Database\Eloquent\Collection|Client[] $clients * @property-read \Illuminate\Database\Eloquent\Collection|CurrencyExchangeRate[] $currencyExchangeRates - * @property-read DatabaseNotificationCollection|DatabaseNotification[] $notifications - * @property-read \Illuminate\Database\Eloquent\Collection|PiggyBank[] $piggyBanks - * @property-read \Illuminate\Database\Eloquent\Collection|Preference[] $preferences - * @property-read \Illuminate\Database\Eloquent\Collection|Recurrence[] $recurrences - * @property-read \Illuminate\Database\Eloquent\Collection|RuleGroup[] $ruleGroups - * @property-read \Illuminate\Database\Eloquent\Collection|Rule[] $rules - * @property-read \Illuminate\Database\Eloquent\Collection|Tag[] $tags - * @property-read \Illuminate\Database\Eloquent\Collection|Token[] $tokens - * @property-read \Illuminate\Database\Eloquent\Collection|TransactionGroup[] $transactionGroups - * @property-read \Illuminate\Database\Eloquent\Collection|TransactionJournal[] $transactionJournals - * @property-read \Illuminate\Database\Eloquent\Collection|Transaction[] $transactions + * @property-read DatabaseNotificationCollection|DatabaseNotification[] $notifications + * @property-read \Illuminate\Database\Eloquent\Collection|PiggyBank[] $piggyBanks + * @property-read \Illuminate\Database\Eloquent\Collection|Preference[] $preferences + * @property-read \Illuminate\Database\Eloquent\Collection|Recurrence[] $recurrences + * @property-read \Illuminate\Database\Eloquent\Collection|RuleGroup[] $ruleGroups + * @property-read \Illuminate\Database\Eloquent\Collection|Rule[] $rules + * @property-read \Illuminate\Database\Eloquent\Collection|Tag[] $tags + * @property-read \Illuminate\Database\Eloquent\Collection|Token[] $tokens + * @property-read \Illuminate\Database\Eloquent\Collection|TransactionGroup[] $transactionGroups + * @property-read \Illuminate\Database\Eloquent\Collection|TransactionJournal[] $transactionJournals + * @property-read \Illuminate\Database\Eloquent\Collection|Transaction[] $transactions * @method static Builder|User newModelQuery() * @method static Builder|User newQuery() * @method static Builder|User query() @@ -114,52 +120,53 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; * @method static Builder|User whereReset($value) * @method static Builder|User whereUpdatedAt($value) * @mixin Eloquent - * @property string|null $objectguid - * @property-read int|null $accounts_count - * @property-read int|null $attachments_count - * @property-read int|null $available_budgets_count - * @property-read int|null $bills_count - * @property-read int|null $budgets_count - * @property-read int|null $categories_count - * @property-read int|null $clients_count - * @property-read int|null $currency_exchange_rates_count - * @property-read int|null $notifications_count - * @property-read int|null $piggy_banks_count - * @property-read int|null $preferences_count - * @property-read int|null $recurrences_count - * @property-read int|null $roles_count - * @property-read int|null $rule_groups_count - * @property-read int|null $rules_count - * @property-read int|null $tags_count - * @property-read int|null $tokens_count - * @property-read int|null $transaction_groups_count - * @property-read int|null $transaction_journals_count - * @property-read int|null $transactions_count + * @property string|null $objectguid + * @property-read int|null $accounts_count + * @property-read int|null $attachments_count + * @property-read int|null $available_budgets_count + * @property-read int|null $bills_count + * @property-read int|null $budgets_count + * @property-read int|null $categories_count + * @property-read int|null $clients_count + * @property-read int|null $currency_exchange_rates_count + * @property-read int|null $notifications_count + * @property-read int|null $piggy_banks_count + * @property-read int|null $preferences_count + * @property-read int|null $recurrences_count + * @property-read int|null $roles_count + * @property-read int|null $rule_groups_count + * @property-read int|null $rules_count + * @property-read int|null $tags_count + * @property-read int|null $tokens_count + * @property-read int|null $transaction_groups_count + * @property-read int|null $transaction_journals_count + * @property-read int|null $transactions_count * @method static Builder|User whereMfaSecret($value) * @method static Builder|User whereObjectguid($value) - * @property string|null $provider + * @property string|null $provider * @method static Builder|User whereProvider($value) - * @property-read \Illuminate\Database\Eloquent\Collection|ObjectGroup[] $objectGroups - * @property-read int|null $object_groups_count - * @property-read \Illuminate\Database\Eloquent\Collection|Webhook[] $webhooks - * @property-read int|null $webhooks_count - * @property string|null $two_factor_secret - * @property string|null $two_factor_recovery_codes - * @property string|null $guid - * @property string|null $domain + * @property-read \Illuminate\Database\Eloquent\Collection|ObjectGroup[] $objectGroups + * @property-read int|null $object_groups_count + * @property-read \Illuminate\Database\Eloquent\Collection|Webhook[] $webhooks + * @property-read int|null $webhooks_count + * @property string|null $two_factor_secret + * @property string|null $two_factor_recovery_codes + * @property string|null $guid + * @property string|null $domain * @method static Builder|User whereDomain($value) * @method static Builder|User whereGuid($value) * @method static Builder|User whereTwoFactorRecoveryCodes($value) * @method static Builder|User whereTwoFactorSecret($value) - * @property int|null $user_group_id - * @property-read \Illuminate\Database\Eloquent\Collection|GroupMembership[] $groupMemberships - * @property-read int|null $group_memberships_count - * @property-read UserGroup|null $userGroup + * @property int|null $user_group_id + * @property-read \Illuminate\Database\Eloquent\Collection|GroupMembership[] $groupMemberships + * @property-read int|null $group_memberships_count + * @property-read UserGroup|null $userGroup * @method static Builder|User whereUserGroupId($value) */ class User extends Authenticatable { - use Notifiable, HasApiTokens; + use Notifiable; + use HasApiTokens; /** * The attributes that should be cast to native types. @@ -192,7 +199,7 @@ class User extends Authenticatable protected $table = 'users'; /** - * @param string $value + * @param string $value * * @return User * @throws NotFoundHttpException @@ -200,13 +207,13 @@ class User extends Authenticatable public static function routeBinder(string $value): User { if (auth()->check()) { - $userId = (int) $value; + $userId = (int)$value; $user = self::find($userId); if (null !== $user) { return $user; } } - throw new NotFoundHttpException; + throw new NotFoundHttpException(); } /** @@ -354,27 +361,6 @@ class User extends Authenticatable return $this->hasMany(GroupMembership::class)->with(['userGroup', 'userRole']); } - /** - * @param string $role - * - * @return bool - */ - public function hasRole(string $role): bool - { - return $this->roles()->where('name', $role)->count() === 1; - } - - /** - * @codeCoverageIgnore - * Link to roles. - * - * @return BelongsToMany - */ - public function roles(): BelongsToMany - { - return $this->belongsToMany(Role::class); - } - /** * @codeCoverageIgnore * Link to object groups. @@ -419,6 +405,81 @@ class User extends Authenticatable return $this->hasMany(Recurrence::class); } + /** + * Get the notification routing information for the given driver. + * + * @param string $driver + * @param Notification|null $notification + * @return mixed + */ + public function routeNotificationFor($driver, $notification = null) + { + if (method_exists($this, $method = 'routeNotificationFor'.Str::studly($driver))) { + return $this->{$method}($notification); + } + $email = $this->email; + // see if user has alternative email address: + $pref = app('preferences')->getForUser($this, 'remote_guard_alt_email'); + if (null !== $pref) { + $email = $pref->data; + } + // if user is demo user, send to owner: + if ($this->hasRole('demo')) { + $email = config('firefly.site_owner'); + } + + return match ($driver) { + 'database' => $this->notifications(), + 'mail' => $email, + default => null, + }; + } + + /** + * @param string $role + * + * @return bool + */ + public function hasRole(string $role): bool + { + return $this->roles()->where('name', $role)->count() === 1; + } + + /** + * @codeCoverageIgnore + * Link to roles. + * + * @return BelongsToMany + */ + public function roles(): BelongsToMany + { + return $this->belongsToMany(Role::class); + } + + /** + * Route notifications for the Slack channel. + * + * @param Notification $notification + * @return string + */ + public function routeNotificationForSlack(Notification $notification): string + { + // this check does not validate if the user is owner, Should be done by notification itself. + if ($notification instanceof TestNotification) { + return app('fireflyconfig')->get('slack_webhook_url', '')->data; + } + if ($notification instanceof UserRegistration) { + return app('fireflyconfig')->get('slack_webhook_url', '')->data; + } + if ($notification instanceof VersionCheckResult) { + return app('fireflyconfig')->get('slack_webhook_url', '')->data; + } + if ($notification instanceof UserInvitation) { + return app('fireflyconfig')->get('slack_webhook_url', '')->data; + } + return app('preferences')->getForUser($this, 'slack_webhook_url', '')->data; + } + /** * @codeCoverageIgnore * Link to rule groups. @@ -445,7 +506,7 @@ class User extends Authenticatable * @codeCoverageIgnore * Send the password reset notification. * - * @param string $token + * @param string $token */ public function sendPasswordResetNotification($token): void { @@ -454,9 +515,11 @@ class User extends Authenticatable event(new RequestedNewPassword($this, $token, $ipAddress)); } + // start LDAP related code + /** * Set the models LDAP domain. - * @param string $domain + * @param string $domain * * @return void * @deprecated @@ -469,7 +532,7 @@ class User extends Authenticatable /** * Set the models LDAP GUID. - * @param string $guid + * @param string $guid * * @return void * @deprecated @@ -479,8 +542,6 @@ class User extends Authenticatable $this->{$this->getLdapGuidColumn()} = $guid; } - // start LDAP related code - /** * @codeCoverageIgnore * Link to tags. @@ -531,7 +592,7 @@ class User extends Authenticatable */ public function userGroup(): BelongsTo { - return $this->belongsTo(UserGroup::class,); + return $this->belongsTo(UserGroup::class, ); } /** @@ -545,5 +606,4 @@ class User extends Authenticatable { return $this->hasMany(Webhook::class); } - // end LDAP related code } diff --git a/app/Validation/Account/AccountValidatorProperties.php b/app/Validation/Account/AccountValidatorProperties.php index 61197490ab..b77f592bdf 100644 --- a/app/Validation/Account/AccountValidatorProperties.php +++ b/app/Validation/Account/AccountValidatorProperties.php @@ -31,5 +31,4 @@ namespace FireflyIII\Validation\Account; */ trait AccountValidatorProperties { - } diff --git a/app/Validation/Account/DepositValidation.php b/app/Validation/Account/DepositValidation.php index 9e71bde252..d315f65e3b 100644 --- a/app/Validation/Account/DepositValidation.php +++ b/app/Validation/Account/DepositValidation.php @@ -33,22 +33,7 @@ use Log; trait DepositValidation { /** - * @param array $accountTypes - * - * @return bool - */ - abstract protected function canCreateTypes(array $accountTypes): bool; - - /** - * @param array $validTypes - * @param array $data - * - * @return Account|null - */ - abstract protected function findExistingAccount(array $validTypes, array $data): ?Account; - - /** - * @param array $array + * @param array $array * * @return bool */ @@ -65,7 +50,7 @@ trait DepositValidation if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) { // if both values are NULL we return false, // because the destination of a deposit can't be created. - $this->destError = (string) trans('validation.deposit_dest_need_data'); + $this->destError = (string)trans('validation.deposit_dest_need_data'); Log::error('Both values are NULL, cant create deposit destination.'); $result = false; } @@ -80,7 +65,7 @@ trait DepositValidation $search = $this->findExistingAccount($validTypes, $array); if (null === $search) { Log::debug('findExistingAccount() returned NULL, so the result is false.'); - $this->destError = (string) trans('validation.deposit_dest_bad_data', ['id' => $accountId, 'name' => $accountName]); + $this->destError = (string)trans('validation.deposit_dest_bad_data', ['id' => $accountId, 'name' => $accountName]); $result = false; } if (null !== $search) { @@ -89,14 +74,28 @@ trait DepositValidation $result = true; } } - $result = $result ?? false; Log::debug(sprintf('validateDepositDestination will return %s', var_export($result, true))); return $result; } /** - * @param array $array + * @param array $accountTypes + * + * @return bool + */ + abstract protected function canCreateTypes(array $accountTypes): bool; + + /** + * @param array $validTypes + * @param array $data + * + * @return Account|null + */ + abstract protected function findExistingAccount(array $validTypes, array $data): ?Account; + + /** + * @param array $array * * @return bool */ @@ -114,7 +113,7 @@ trait DepositValidation // if both values are NULL return false, // because the source of a deposit can't be created. // (this never happens). - $this->sourceError = (string) trans('validation.deposit_source_need_data'); + $this->sourceError = (string)trans('validation.deposit_source_need_data'); $result = false; } @@ -153,7 +152,7 @@ trait DepositValidation $result = true; // set the source to be a (dummy) revenue account. - $account = new Account; + $account = new Account(); $accountType = AccountType::whereType(AccountType::REVENUE)->first(); $account->accountType = $accountType; $this->source = $account; diff --git a/app/Validation/Account/LiabilityValidation.php b/app/Validation/Account/LiabilityValidation.php index 683eabe2d2..feb8c155dc 100644 --- a/app/Validation/Account/LiabilityValidation.php +++ b/app/Validation/Account/LiabilityValidation.php @@ -24,7 +24,6 @@ declare(strict_types=1); namespace FireflyIII\Validation\Account; - use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use Log; @@ -34,62 +33,80 @@ use Log; */ trait LiabilityValidation { - /** - * @param array $array + * @param array $array * * @return bool */ protected function validateLCDestination(array $array): bool { Log::debug('Now in validateLCDestination', $array); - $result = null; - $accountId = array_key_exists('id', $array) ? $array['id'] : null; - $validTypes = config('firefly.valid_liabilities'); + $result = null; + $accountId = array_key_exists('id', $array) ? $array['id'] : null; + $accountName = array_key_exists('name', $array) ? $array['name'] : null; + $validTypes = config('firefly.valid_liabilities'); - if (null === $accountId) { - $this->sourceError = (string) trans('validation.lc_destination_need_data'); - $result = false; + // if the ID is not null the source account should be a dummy account of the type liability credit. + // the ID of the destination must belong to a liability. + if (null !== $accountId) { + if (AccountType::LIABILITY_CREDIT !== $this?->source?->accountType?->type) { + Log::error('Source account is not a liability.'); + return false; + } + $result = $this->findExistingAccount($validTypes, $array); + if (null === $result) { + Log::error('Destination account is not a liability.'); + return false; + } + return true; } - Log::debug('Destination ID is not null.'); - $search = $this->accountRepository->find($accountId); - - // the source resulted in an account, but it's not of a valid type. - if (null !== $search && !in_array($search->accountType->type, $validTypes, true)) { - $message = sprintf('User submitted only an ID (#%d), which is a "%s", so this is not a valid destination.', $accountId, $search->accountType->type); - Log::debug($message); - $this->sourceError = $message; - $result = false; + if (null !== $accountName && '' !== $accountName) { + Log::debug('Destination ID is null, now we can assume the destination is a (new) liability credit account.'); + return true; } - // the source resulted in an account, AND it's of a valid type. - if (null !== $search && in_array($search->accountType->type, $validTypes, true)) { - Log::debug(sprintf('Found account of correct type: #%d, "%s"', $search->id, $search->name)); - $this->source = $search; - $result = true; - } - - return $result ?? false; + Log::error('Destination ID is null, but destination name is also NULL.'); + return false; } /** - * Source of an liability credit must be a liability. + * Source of a liability credit must be a liability or liability credit account. * - * @param array $array + * @param array $array * * @return bool */ protected function validateLCSource(array $array): bool { + Log::debug('Now in validateLCSource', $array); + // if the array has an ID and ID is not null, try to find it and check type. + // this account must be a liability + $accountId = array_key_exists('id', $array) ? $array['id'] : null; + if (null !== $accountId) { + Log::debug('Source ID is not null, assume were looking for a liability.'); + // find liability credit: + $result = $this->findExistingAccount(config('firefly.valid_liabilities'), $array); + if (null === $result) { + Log::error('Did not find a liability account, return false.'); + return false; + } + Log::debug(sprintf('Return true, found #%d ("%s")', $result->id, $result->name)); + $this->source = $result; + return true; + } + + // if array has name and is not null, return true. $accountName = array_key_exists('name', $array) ? $array['name'] : null; - $result = true; - Log::debug('Now in validateLCDestination', $array); + + $result = true; if ('' === $accountName || null === $accountName) { + Log::error('Array must have a name, is not the case, return false.'); $result = false; } if (true === $result) { + Log::error('Array has a name, return true.'); // set the source to be a (dummy) revenue account. - $account = new Account; + $account = new Account(); $accountType = AccountType::whereType(AccountType::LIABILITY_CREDIT)->first(); $account->accountType = $accountType; $this->source = $account; @@ -97,5 +114,4 @@ trait LiabilityValidation return $result; } - } diff --git a/app/Validation/Account/OBValidation.php b/app/Validation/Account/OBValidation.php index 60b107da9a..9f738c7b6c 100644 --- a/app/Validation/Account/OBValidation.php +++ b/app/Validation/Account/OBValidation.php @@ -34,14 +34,7 @@ use Log; trait OBValidation { /** - * @param array $accountTypes - * - * @return bool - */ - abstract protected function canCreateTypes(array $accountTypes): bool; - - /** - * @param array $array + * @param array $array * * @return bool */ @@ -57,7 +50,7 @@ trait OBValidation if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) { // if both values are NULL we return false, // because the destination of a deposit can't be created. - $this->destError = (string) trans('validation.ob_dest_need_data'); + $this->destError = (string)trans('validation.ob_dest_need_data'); Log::error('Both values are NULL, cant create OB destination.'); $result = false; } @@ -72,7 +65,7 @@ trait OBValidation $search = $this->findExistingAccount($validTypes, $array); if (null === $search) { Log::debug('findExistingAccount() returned NULL, so the result is false.', $validTypes); - $this->destError = (string) trans('validation.ob_dest_bad_data', ['id' => $accountId, 'name' => $accountName]); + $this->destError = (string)trans('validation.ob_dest_bad_data', ['id' => $accountId, 'name' => $accountName]); $result = false; } if (null !== $search) { @@ -81,17 +74,23 @@ trait OBValidation $result = true; } } - $result = $result ?? false; Log::debug(sprintf('validateOBDestination(%d, "%s") will return %s', $accountId, $accountName, var_export($result, true))); return $result; } + /** + * @param array $accountTypes + * + * @return bool + */ + abstract protected function canCreateTypes(array $accountTypes): bool; + /** * Source of an opening balance can either be an asset account * or an "initial balance account". The latter can be created. * - * @param array $array + * @param array $array * * @return bool */ @@ -108,7 +107,7 @@ trait OBValidation // if both values are NULL return false, // because the source of a deposit can't be created. // (this never happens). - $this->sourceError = (string) trans('validation.ob_source_need_data'); + $this->sourceError = (string)trans('validation.ob_source_need_data'); $result = false; } @@ -139,7 +138,7 @@ trait OBValidation $result = true; // set the source to be a (dummy) initial balance account. - $account = new Account; + $account = new Account(); $accountType = AccountType::whereType(AccountType::INITIAL_BALANCE)->first(); $account->accountType = $accountType; $this->source = $account; diff --git a/app/Validation/Account/ReconciliationValidation.php b/app/Validation/Account/ReconciliationValidation.php index c0e3ddae9a..f964a01585 100644 --- a/app/Validation/Account/ReconciliationValidation.php +++ b/app/Validation/Account/ReconciliationValidation.php @@ -25,7 +25,6 @@ declare(strict_types=1); namespace FireflyIII\Validation\Account; use FireflyIII\Models\Account; -use FireflyIII\Models\AccountType; use Log; /** @@ -37,82 +36,74 @@ trait ReconciliationValidation public ?Account $source; /** - * @param array $array + * @param array $array * * @return bool */ protected function validateReconciliationDestination(array $array): bool { - $accountId = array_key_exists('id', $array) ? $array['id'] : null; - Log::debug('Now in validateReconciliationDestination', $array); - if (null === $accountId) { - Log::debug('Return FALSE'); - - return false; - } - $result = $this->accountRepository->find($accountId); - if (null === $result) { - $this->destError = (string) trans('validation.deposit_dest_bad_data', ['id' => $accountId, 'name' => '']); - Log::debug('Return FALSE'); - - return false; - } - // types depends on type of source: - $types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]; - // if source is reconciliation, destination can't be. - if (null !== $this->source && AccountType::RECONCILIATION === $this->source->accountType->type) { - $types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE]; - } - // if source is not reconciliation, destination MUST be. - if (null !== $this->source - && in_array( - $this->source->accountType->type, [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], true - )) { - $types = [AccountType::RECONCILIATION]; - } - - if (in_array($result->accountType->type, $types, true)) { - $this->destination = $result; - Log::debug('Return TRUE'); + $accountId = array_key_exists('id', $array) ? $array['id'] : null; + $accountName = array_key_exists('name', $array) ? $array['name'] : null; + // if both are NULL, the destination is valid because the reconciliation + // is expected to be "negative", i.e. the money flows towards the + // destination to the asset account which is the source. + if (null === $accountId && null === $accountName) { return true; } - $this->destError = (string) trans('validation.deposit_dest_wrong_type'); - Log::debug('Return FALSE'); - return false; + // after that, search for it expecting an asset account or a liability. + Log::debug('Now in validateReconciliationDestination', $array); + + // source can be any of the following types. + $validTypes = array_keys($this->combinations[$this->transactionType]); + $search = $this->findExistingAccount($validTypes, $array); + if (null === $search) { + $this->sourceError = (string)trans('validation.reconciliation_source_bad_data', ['id' => $accountId, 'name' => $accountName]); + app('log')->warning('Not a valid source. Cant find it.', $validTypes); + + return false; + } + $this->source = $search; + Log::debug('Valid source account!'); + + return true; } /** - * @param array $array + * Basically the same check + * @param array $array * * @return bool */ protected function validateReconciliationSource(array $array): bool { - $accountId = array_key_exists('id', $array) ? $array['id'] : null; - Log::debug('In validateReconciliationSource', $array); - if (null === $accountId) { - Log::debug('Return FALSE'); - - return false; - } - $result = $this->accountRepository->find($accountId); - $types = [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, AccountType::RECONCILIATION]; - if (null === $result) { - Log::debug('Return FALSE'); - - return false; - } - if (in_array($result->accountType->type, $types, true)) { - $this->source = $result; - Log::debug('Return TRUE'); - + $accountId = array_key_exists('id', $array) ? $array['id'] : null; + $accountName = array_key_exists('name', $array) ? $array['name'] : null; + // if both are NULL, the source is valid because the reconciliation + // is expected to be "positive", i.e. the money flows from the + // source to the asset account that is the destination. + if (null === $accountId && null === $accountName) { + Log::debug('The source is valid because ID and name are NULL.'); + $this->source = new Account(); return true; } - Log::debug('Return FALSE'); - return false; + // after that, search for it expecting an asset account or a liability. + Log::debug('Now in validateReconciliationSource', $array); + + // source can be any of the following types. + $validTypes = array_keys($this->combinations[$this->transactionType]); + $search = $this->findExistingAccount($validTypes, $array); + if (null === $search) { + $this->sourceError = (string)trans('validation.reconciliation_source_bad_data', ['id' => $accountId, 'name' => $accountName]); + app('log')->warning('Not a valid source. Cant find it.', $validTypes); + + return false; + } + $this->source = $search; + Log::debug('Valid source account!'); + + return true; } - } diff --git a/app/Validation/Account/TransferValidation.php b/app/Validation/Account/TransferValidation.php index 06e49a8665..9daa1c7bf4 100644 --- a/app/Validation/Account/TransferValidation.php +++ b/app/Validation/Account/TransferValidation.php @@ -32,22 +32,7 @@ use Log; trait TransferValidation { /** - * @param array $accountTypes - * - * @return bool - */ - abstract protected function canCreateTypes(array $accountTypes): bool; - - /** - * @param array $validTypes - * @param array $data - * - * @return Account|null - */ - abstract protected function findExistingAccount(array $validTypes, array $data): ?Account; - - /** - * @param array $array + * @param array $array * * @return bool */ @@ -61,7 +46,7 @@ trait TransferValidation if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) { // if both values are NULL we return false, // because the destination of a transfer can't be created. - $this->destError = (string) trans('validation.transfer_dest_need_data'); + $this->destError = (string)trans('validation.transfer_dest_need_data'); Log::error('Both values are NULL, cant create transfer destination.'); return false; @@ -70,7 +55,7 @@ trait TransferValidation // or try to find the account: $search = $this->findExistingAccount($validTypes, $array); if (null === $search) { - $this->destError = (string) trans('validation.transfer_dest_bad_data', ['id' => $accountId, 'name' => $accountName]); + $this->destError = (string)trans('validation.transfer_dest_bad_data', ['id' => $accountId, 'name' => $accountName]); return false; } @@ -88,7 +73,22 @@ trait TransferValidation } /** - * @param array $array + * @param array $accountTypes + * + * @return bool + */ + abstract protected function canCreateTypes(array $accountTypes): bool; + + /** + * @param array $validTypes + * @param array $data + * + * @return Account|null + */ + abstract protected function findExistingAccount(array $validTypes, array $data): ?Account; + + /** + * @param array $array * * @return bool */ @@ -102,8 +102,8 @@ trait TransferValidation if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) { // if both values are NULL we return false, // because the source of a withdrawal can't be created. - $this->sourceError = (string) trans('validation.transfer_source_need_data'); - Log::warning('Not a valid source, need more data.'); + $this->sourceError = (string)trans('validation.transfer_source_need_data'); + app('log')->warning('Not a valid source, need more data.'); return false; } @@ -111,8 +111,8 @@ trait TransferValidation // otherwise try to find the account: $search = $this->findExistingAccount($validTypes, $array); if (null === $search) { - $this->sourceError = (string) trans('validation.transfer_source_bad_data', ['id' => $accountId, 'name' => $accountName]); - Log::warning('Not a valid source, cant find it.', $validTypes); + $this->sourceError = (string)trans('validation.transfer_source_bad_data', ['id' => $accountId, 'name' => $accountName]); + app('log')->warning('Not a valid source, cant find it.', $validTypes); return false; } diff --git a/app/Validation/Account/WithdrawalValidation.php b/app/Validation/Account/WithdrawalValidation.php index 5200b16e7c..bb5d758f76 100644 --- a/app/Validation/Account/WithdrawalValidation.php +++ b/app/Validation/Account/WithdrawalValidation.php @@ -33,22 +33,7 @@ use Log; trait WithdrawalValidation { /** - * @param array $accountTypes - * - * @return bool - */ - abstract protected function canCreateTypes(array $accountTypes): bool; - - /** - * @param array $validTypes - * @param array $data - * - * @return Account|null - */ - abstract protected function findExistingAccount(array $validTypes, array $data): ?Account; - - /** - * @param array $array + * @param array $array * * @return bool */ @@ -62,8 +47,8 @@ trait WithdrawalValidation if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) { // if both values are NULL we return TRUE // because we assume the user doesnt want to submit / change anything. - $this->sourceError = (string) trans('validation.withdrawal_source_need_data'); - Log::warning('[a] Not a valid source. Need more data.'); + $this->sourceError = (string)trans('validation.withdrawal_source_need_data'); + app('log')->warning('[a] Not a valid source. Need more data.'); return false; } @@ -71,8 +56,8 @@ trait WithdrawalValidation // otherwise try to find the account: $search = $this->findExistingAccount($validTypes, $array); if (null === $search) { - $this->sourceError = (string) trans('validation.withdrawal_source_bad_data', ['id' => $accountId, 'name' => $accountName]); - Log::warning('Not a valid source. Cant find it.', $validTypes); + $this->sourceError = (string)trans('validation.withdrawal_source_bad_data', ['id' => $accountId, 'name' => $accountName]); + app('log')->warning('Not a valid source. Cant find it.', $validTypes); return false; } @@ -83,7 +68,22 @@ trait WithdrawalValidation } /** - * @param array $array + * @param array $accountTypes + * + * @return bool + */ + abstract protected function canCreateTypes(array $accountTypes): bool; + + /** + * @param array $validTypes + * @param array $data + * + * @return Account|null + */ + abstract protected function findExistingAccount(array $validTypes, array $data): ?Account; + + /** + * @param array $array * * @return bool */ @@ -97,7 +97,7 @@ trait WithdrawalValidation if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) { // if both values are NULL return false, // because the destination of a withdrawal can never be created automatically. - $this->destError = (string) trans('validation.withdrawal_dest_need_data'); + $this->destError = (string)trans('validation.withdrawal_dest_need_data'); return false; } @@ -110,7 +110,7 @@ trait WithdrawalValidation if (in_array($type, $validTypes, true)) { return true; } - $this->destError = (string) trans('validation.withdrawal_dest_bad_data', ['id' => $accountId, 'name' => $accountName]); + $this->destError = (string)trans('validation.withdrawal_dest_bad_data', ['id' => $accountId, 'name' => $accountName]); return false; } @@ -121,7 +121,7 @@ trait WithdrawalValidation } /** - * @param array $array + * @param array $array * * @return bool */ @@ -136,8 +136,8 @@ trait WithdrawalValidation if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) { // if both values are NULL we return false, // because the source of a withdrawal can't be created. - $this->sourceError = (string) trans('validation.withdrawal_source_need_data'); - Log::warning('[b] Not a valid source. Need more data.'); + $this->sourceError = (string)trans('validation.withdrawal_source_need_data'); + app('log')->warning('[b] Not a valid source. Need more data.'); return false; } @@ -145,8 +145,8 @@ trait WithdrawalValidation // otherwise try to find the account: $search = $this->findExistingAccount($validTypes, $array); if (null === $search) { - $this->sourceError = (string) trans('validation.withdrawal_source_bad_data', ['id' => $accountId, 'name' => $accountName]); - Log::warning('Not a valid source. Cant find it.', $validTypes); + $this->sourceError = (string)trans('validation.withdrawal_source_bad_data', ['id' => $accountId, 'name' => $accountName]); + app('log')->warning('Not a valid source. Cant find it.', $validTypes); return false; } diff --git a/app/Validation/AccountValidator.php b/app/Validation/AccountValidator.php index 16bb89c58c..a91ad2c261 100644 --- a/app/Validation/AccountValidator.php +++ b/app/Validation/AccountValidator.php @@ -42,7 +42,13 @@ use Log; */ class AccountValidator { - use AccountValidatorProperties, WithdrawalValidation, DepositValidation, TransferValidation, ReconciliationValidation, OBValidation, LiabilityValidation; + use AccountValidatorProperties; + use WithdrawalValidation; + use DepositValidation; + use TransferValidation; + use ReconciliationValidation; + use OBValidation; + use LiabilityValidation; public bool $createMode; public string $destError; @@ -77,7 +83,7 @@ class AccountValidator } /** - * @param string $transactionType + * @param string $transactionType */ public function setTransactionType(string $transactionType): void { @@ -86,7 +92,7 @@ class AccountValidator } /** - * @param User $user + * @param User $user */ public function setUser(User $user): void { @@ -95,7 +101,7 @@ class AccountValidator } /** - * @param array $array + * @param array $array * * @return bool */ @@ -140,7 +146,7 @@ class AccountValidator } /** - * @param array $array + * @param array $array * * @return bool */ @@ -178,7 +184,7 @@ class AccountValidator } /** - * @param array $accountTypes + * @param array $accountTypes * * @return bool */ @@ -199,7 +205,7 @@ class AccountValidator } /** - * @param string $accountType + * @param string $accountType * * @return bool */ @@ -214,8 +220,8 @@ class AccountValidator } /** - * @param array $validTypes - * @param array $data + * @param array $validTypes + * @param array $data * * @return Account|null */ @@ -236,7 +242,7 @@ class AccountValidator } // find by iban - if (null !== $accountIban && '' !== (string) $accountIban) { + if (null !== $accountIban && '' !== (string)$accountIban) { $first = $this->accountRepository->findByIbanNull($accountIban, $validTypes); if ((null !== $first) && in_array($first->accountType->type, $validTypes, true)) { return $first; @@ -244,7 +250,7 @@ class AccountValidator } // find by number - if (null !== $accountNumber && '' !== (string) $accountNumber) { + if (null !== $accountNumber && '' !== (string)$accountNumber) { $first = $this->accountRepository->findByAccountNumber($accountNumber, $validTypes); if ((null !== $first) && in_array($first->accountType->type, $validTypes, true)) { return $first; @@ -252,11 +258,10 @@ class AccountValidator } // find by name: - if ('' !== (string) $accountName) { + if ('' !== (string)$accountName) { return $this->accountRepository->findByName($accountName, $validTypes); } return null; } - } diff --git a/app/Validation/Api/Data/Bulk/ValidatesBulkTransactionQuery.php b/app/Validation/Api/Data/Bulk/ValidatesBulkTransactionQuery.php index b67d03384d..35126c6359 100644 --- a/app/Validation/Api/Data/Bulk/ValidatesBulkTransactionQuery.php +++ b/app/Validation/Api/Data/Bulk/ValidatesBulkTransactionQuery.php @@ -34,7 +34,7 @@ use JsonException; trait ValidatesBulkTransactionQuery { /** - * @param Validator $validator + * @param Validator $validator * * @throws JsonException */ @@ -50,28 +50,27 @@ trait ValidatesBulkTransactionQuery // find both accounts, must be same type. // already validated: belongs to this user. $repository = app(AccountRepositoryInterface::class); - $source = $repository->find((int) $json['where']['account_id']); - $dest = $repository->find((int) $json['update']['account_id']); + $source = $repository->find((int)$json['where']['account_id']); + $dest = $repository->find((int)$json['update']['account_id']); if (null === $source) { - $validator->errors()->add('query', sprintf((string) trans('validation.invalid_query_data'), 'where', 'account_id')); + $validator->errors()->add('query', sprintf((string)trans('validation.invalid_query_data'), 'where', 'account_id')); return; } if (null === $dest) { - $validator->errors()->add('query', sprintf((string) trans('validation.invalid_query_data'), 'update', 'account_id')); + $validator->errors()->add('query', sprintf((string)trans('validation.invalid_query_data'), 'update', 'account_id')); return; } if ($source->accountType->type !== $dest->accountType->type) { - $validator->errors()->add('query', (string) trans('validation.invalid_query_account_type')); + $validator->errors()->add('query', (string)trans('validation.invalid_query_account_type')); return; } // must have same currency: if ($repository->getAccountCurrency($source)->id !== $repository->getAccountCurrency($dest)->id) { - $validator->errors()->add('query', (string) trans('validation.invalid_query_currency')); + $validator->errors()->add('query', (string)trans('validation.invalid_query_currency')); } } } - } diff --git a/app/Validation/AutoBudget/ValidatesAutoBudgetRequest.php b/app/Validation/AutoBudget/ValidatesAutoBudgetRequest.php index eb3eeca742..f35ca252ae 100644 --- a/app/Validation/AutoBudget/ValidatesAutoBudgetRequest.php +++ b/app/Validation/AutoBudget/ValidatesAutoBudgetRequest.php @@ -31,7 +31,7 @@ use Illuminate\Validation\Validator; trait ValidatesAutoBudgetRequest { /** - * @param Validator $validator + * @param Validator $validator */ protected function validateAutoBudgetAmount(Validator $validator): void { @@ -39,36 +39,36 @@ trait ValidatesAutoBudgetRequest $type = $data['auto_budget_type'] ?? ''; $amount = array_key_exists('auto_budget_amount', $data) ? $data['auto_budget_amount'] : null; $period = array_key_exists('auto_budget_period', $data) ? $data['auto_budget_period'] : null; - $currencyId = array_key_exists('auto_budget_currency_id', $data) ? (int) $data['auto_budget_currency_id'] : null; + $currencyId = array_key_exists('auto_budget_currency_id', $data) ? (int)$data['auto_budget_currency_id'] : null; $currencyCode = array_key_exists('auto_budget_currency_code', $data) ? $data['auto_budget_currency_code'] : null; if (is_numeric($type)) { - $type = (int) $type; + $type = (int)$type; } if ('' === $type || 0 === $type) { return; } // basic float check: if (!is_numeric($amount)) { - $validator->errors()->add('auto_budget_amount', (string) trans('validation.amount_required_for_auto_budget')); + $validator->errors()->add('auto_budget_amount', (string)trans('validation.amount_required_for_auto_budget')); return; } if ('' === $amount) { - $validator->errors()->add('auto_budget_amount', (string) trans('validation.amount_required_for_auto_budget')); + $validator->errors()->add('auto_budget_amount', (string)trans('validation.amount_required_for_auto_budget')); } - if (1 !== bccomp((string) $amount, '0')) { - $validator->errors()->add('auto_budget_amount', (string) trans('validation.auto_budget_amount_positive')); + if (1 !== bccomp((string)$amount, '0')) { + $validator->errors()->add('auto_budget_amount', (string)trans('validation.auto_budget_amount_positive')); } if ('' === $period) { - $validator->errors()->add('auto_budget_period', (string) trans('validation.auto_budget_period_mandatory')); + $validator->errors()->add('auto_budget_period', (string)trans('validation.auto_budget_period_mandatory')); } if (null !== $currencyId && null !== $currencyCode && '' === $currencyCode && 0 === $currencyId) { - $validator->errors()->add('auto_budget_amount', (string) trans('validation.require_currency_info')); + $validator->errors()->add('auto_budget_amount', (string)trans('validation.require_currency_info')); } // too big amount - if((int)$amount > 268435456) { - $validator->errors()->add('auto_budget_amount', (string) trans('validation.amount_required_for_auto_budget')); + if ((int)$amount > 268435456) { + $validator->errors()->add('auto_budget_amount', (string)trans('validation.amount_required_for_auto_budget')); return; } } diff --git a/app/Validation/CurrencyValidation.php b/app/Validation/CurrencyValidation.php index a1cc7cf921..172f2e0769 100644 --- a/app/Validation/CurrencyValidation.php +++ b/app/Validation/CurrencyValidation.php @@ -34,10 +34,11 @@ use Log; */ trait CurrencyValidation { + const TEST = 'Test'; /** * If the transactions contain foreign amounts, there must also be foreign currency information. * - * @param Validator $validator + * @param Validator $validator */ protected function validateForeignCurrencyInformation(Validator $validator): void { @@ -49,30 +50,32 @@ trait CurrencyValidation if (array_key_exists('foreign_amount', $transaction) && !(array_key_exists('foreign_currency_id', $transaction) || array_key_exists( - 'foreign_currency_code', $transaction + 'foreign_currency_code', + $transaction )) && 0 !== bccomp('0', $transaction['foreign_amount']) ) { $validator->errors()->add( - 'transactions.' . $index . '.foreign_amount', - (string) trans('validation.require_currency_info') + 'transactions.'.$index.'.foreign_amount', + (string)trans('validation.require_currency_info') ); } // if the currency is present, then the amount must be present as well. if ((array_key_exists('foreign_currency_id', $transaction) || array_key_exists('foreign_currency_code', $transaction)) && !array_key_exists( - 'foreign_amount', $transaction + 'foreign_amount', + $transaction )) { $validator->errors()->add( - 'transactions.' . $index . '.foreign_amount', - (string) trans('validation.require_currency_amount') + 'transactions.'.$index.'.foreign_amount', + (string)trans('validation.require_currency_amount') ); } } } /** - * @param Validator $validator + * @param Validator $validator * * @return array */ diff --git a/app/Validation/FireflyValidator.php b/app/Validation/FireflyValidator.php index a20ee3737f..3181cd4ac1 100644 --- a/app/Validation/FireflyValidator.php +++ b/app/Validation/FireflyValidator.php @@ -1,4 +1,5 @@ where('user_id', auth()->user()->id)->where($field, $value)->count(); @@ -100,8 +101,8 @@ class FireflyValidator extends Validator } /** - * @param mixed $attribute - * @param mixed $value + * @param mixed $attribute + * @param mixed $value * * @return bool */ @@ -120,14 +121,14 @@ class FireflyValidator extends Validator } /** - * @param mixed $attribute - * @param mixed $value + * @param mixed $attribute + * @param mixed $value * * @return bool */ - public function validateIban($attribute, $value): bool + public function validateIban(mixed $attribute, mixed $value): bool { - if (null === $value || !is_string($value) || strlen($value) < 6) { + if (!is_string($value) || strlen($value) < 6) { return false; } // strip spaces @@ -188,13 +189,40 @@ class FireflyValidator extends Validator // replace characters outside of ASCI range. $value = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $value); $search = [' ', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']; - $replace = ['', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', - '32', '33', '34', '35',]; + $replace = [ + '', + '10', + '11', + '12', + '13', + '14', + '15', + '16', + '17', + '18', + '19', + '20', + '21', + '22', + '23', + '24', + '25', + '26', + '27', + '28', + '29', + '30', + '31', + '32', + '33', + '34', + '35', + ]; // take $first = substr($value, 0, 4); $last = substr($value, 4); - $iban = $last . $first; + $iban = $last.$first; $iban = trim(str_replace($search, $replace, $iban)); if (0 === strlen($iban)) { return false; @@ -209,13 +237,13 @@ class FireflyValidator extends Validator return false; } - return 1 === (int) $checksum; + return 1 === (int)$checksum; } /** - * @param mixed $attribute - * @param mixed $value - * @param mixed $parameters + * @param mixed $attribute + * @param mixed $value + * @param mixed $parameters * * @return bool */ @@ -224,13 +252,13 @@ class FireflyValidator extends Validator /** @var mixed $compare */ $compare = $parameters[0] ?? '0'; - return bccomp((string) $value, (string) $compare) < 0; + return bccomp((string)$value, (string)$compare) < 0; } /** - * @param mixed $attribute - * @param mixed $value - * @param mixed $parameters + * @param mixed $attribute + * @param mixed $value + * @param mixed $parameters * * @return bool */ @@ -239,13 +267,13 @@ class FireflyValidator extends Validator /** @var mixed $compare */ $compare = $parameters[0] ?? '0'; - return bccomp((string) $value, (string) $compare) > 0; + return bccomp((string)$value, (string)$compare) > 0; } /** - * @param mixed $attribute - * @param mixed $value - * @param mixed $parameters + * @param mixed $attribute + * @param mixed $value + * @param mixed $parameters * * @return bool */ @@ -253,7 +281,7 @@ class FireflyValidator extends Validator { $field = $parameters[1] ?? 'id'; - if (0 === (int) $value) { + if (0 === (int)$value) { return true; } $count = DB::table($parameters[0])->where($field, $value)->count(); @@ -262,9 +290,9 @@ class FireflyValidator extends Validator } /** - * @param string $attribute + * @param string $attribute * - * @param string|null $value + * @param string|null $value * * @return bool */ @@ -273,7 +301,7 @@ class FireflyValidator extends Validator // first, get the index from this string: $value = $value ?? ''; $parts = explode('.', $attribute); - $index = (int) ($parts[1] ?? '0'); + $index = (int)($parts[1] ?? '0'); // get the name of the trigger from the data array: $actionType = $this->data['actions'][$index]['type'] ?? 'invalid'; @@ -306,8 +334,14 @@ class FireflyValidator extends Validator $repository = app(AccountRepositoryInterface::class); $account = $repository->findByName( $value, - [AccountType::DEFAULT, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, - AccountType::CREDITCARD] + [ + AccountType::DEFAULT, + AccountType::ASSET, + AccountType::LOAN, + AccountType::DEBT, + AccountType::MORTGAGE, + AccountType::CREDITCARD, + ] ); return null !== $account; @@ -328,8 +362,8 @@ class FireflyValidator extends Validator /** * $attribute has the format triggers.%d.value. * - * @param string $attribute - * @param string|null $value + * @param string $attribute + * @param string|null $value * * @return bool */ @@ -337,7 +371,7 @@ class FireflyValidator extends Validator { // first, get the index from this string: $parts = explode('.', $attribute); - $index = (int) ($parts[1] ?? '0'); + $index = (int)($parts[1] ?? '0'); // get the name of the trigger from the data array: $triggerType = $this->data['triggers'][$index]['type'] ?? 'invalid'; @@ -354,18 +388,35 @@ class FireflyValidator extends Validator } // these trigger types need a simple strlen check: - $length = ['source_account_starts', 'source_account_ends', 'source_account_is', 'source_account_contains', 'destination_account_starts', - 'destination_account_ends', - 'destination_account_is', 'destination_account_contains', 'description_starts', 'description_ends', 'description_contains', 'description_is', - 'category_is', - 'budget_is', 'tag_is', 'currency_is', 'notes_contain', 'notes_start', 'notes_end', 'notes_are',]; + $length = [ + 'source_account_starts', + 'source_account_ends', + 'source_account_is', + 'source_account_contains', + 'destination_account_starts', + 'destination_account_ends', + 'destination_account_is', + 'destination_account_contains', + 'description_starts', + 'description_ends', + 'description_contains', + 'description_is', + 'category_is', + 'budget_is', + 'tag_is', + 'currency_is', + 'notes_contain', + 'notes_start', + 'notes_end', + 'notes_are', + ]; if (in_array($triggerType, $length, true)) { return '' !== $value; } // check if it's an existing account. - if (in_array($triggerType, ['destination_account_id', 'source_account_id'])) { - return is_numeric($value) && (int) $value > 0; + if (in_array($triggerType, ['destination_account_id', 'source_account_id'], true)) { + return is_numeric($value) && (int)$value > 0; } // check transaction type. @@ -382,7 +433,6 @@ class FireflyValidator extends Validator try { $parser->parseDate($value); } catch (FireflyException $e) { - Log::error($e->getMessage()); return false; @@ -390,12 +440,11 @@ class FireflyValidator extends Validator } return true; - } /** - * @param mixed $attribute - * @param mixed $value + * @param mixed $attribute + * @param mixed $value * * @return bool */ @@ -403,7 +452,7 @@ class FireflyValidator extends Validator { $verify = false; if (array_key_exists('verify_password', $this->data)) { - $verify = 1 === (int) $this->data['verify_password']; + $verify = 1 === (int)$this->data['verify_password']; } if ($verify) { /** @var Verifier $service */ @@ -416,15 +465,14 @@ class FireflyValidator extends Validator } /** - * @param mixed $attribute - * @param mixed $value - * @param mixed $parameters + * @param mixed $attribute + * @param mixed $value + * @param mixed $parameters * * @return bool */ public function validateUniqueAccountForUser($attribute, $value, $parameters): bool { - // because a user does not have to be logged in (tests and what-not). if (!auth()->check()) { return $this->validateAccountAnonymously(); @@ -433,14 +481,14 @@ class FireflyValidator extends Validator return $this->validateByAccountTypeString($value, $parameters, $this->data['objectType']); } if (array_key_exists('type', $this->data)) { - return $this->validateByAccountTypeString($value, $parameters, $this->data['type']); + return $this->validateByAccountTypeString($value, $parameters, (string)$this->data['type']); } if (array_key_exists('account_type_id', $this->data)) { return $this->validateByAccountTypeId($value, $parameters); } $parameterId = $parameters[0] ?? null; if (null !== $parameterId) { - return $this->validateByParameterId((int) $parameterId, $value); + return $this->validateByParameterId((int)$parameterId, $value); } if (array_key_exists('id', $this->data)) { return $this->validateByAccountId($value); @@ -474,23 +522,23 @@ class FireflyValidator extends Validator } /** - * @param string $value - * @param array $parameters - * @param string $type + * @param string $value + * @param array $parameters + * @param string $type * * @return bool */ private function validateByAccountTypeString(string $value, array $parameters, string $type): bool { /** @var array|null $search */ - $search = Config::get('firefly.accountTypeByIdentifier.' . $type); + $search = Config::get('firefly.accountTypeByIdentifier.'.$type); if (null === $search) { return false; } $accountTypes = AccountType::whereIn('type', $search)->get(); - $ignore = (int) ($parameters[0] ?? 0.0); + $ignore = (int)($parameters[0] ?? 0.0); $accountTypeIds = $accountTypes->pluck('id')->toArray(); /** @var Collection $set */ $set = auth()->user()->accounts()->whereIn('account_type_id', $accountTypeIds)->where('id', '!=', $ignore)->get(); @@ -501,19 +549,18 @@ class FireflyValidator extends Validator ); return null === $result; - } /** - * @param mixed $value - * @param mixed $parameters + * @param mixed $value + * @param mixed $parameters * * @return bool */ private function validateByAccountTypeId($value, $parameters): bool { $type = AccountType::find($this->data['account_type_id'])->first(); - $ignore = (int) ($parameters[0] ?? 0.0); + $ignore = (int)($parameters[0] ?? 0.0); /** @var Collection $set */ $set = auth()->user()->accounts()->where('account_type_id', $type->id)->where('id', '!=', $ignore)->get(); @@ -528,8 +575,8 @@ class FireflyValidator extends Validator } /** - * @param int $accountId - * @param mixed $value + * @param int $accountId + * @param mixed $value * * @return bool */ @@ -549,7 +596,7 @@ class FireflyValidator extends Validator } /** - * @param mixed $value + * @param mixed $value * * @return bool */ @@ -569,7 +616,7 @@ class FireflyValidator extends Validator } /** - * @param string $value + * @param string $value * * @return bool */ @@ -579,17 +626,17 @@ class FireflyValidator extends Validator } /** - * @param mixed $attribute - * @param mixed $value - * @param mixed $parameters + * @param mixed $attribute + * @param mixed $value + * @param mixed $parameters * * @return bool */ public function validateUniqueAccountNumberForUser($attribute, $value, $parameters): bool { - $accountId = (int) ($this->data['id'] ?? 0.0); + $accountId = (int)($this->data['id'] ?? 0.0); if (0 === $accountId) { - $accountId = (int) ($parameters[0] ?? 0.0); + $accountId = (int)($parameters[0] ?? 0.0); } $query = AccountMeta::leftJoin('accounts', 'accounts.id', '=', 'account_meta.account_id') @@ -613,7 +660,7 @@ class FireflyValidator extends Validator } $type = $this->data['objectType'] ?? 'unknown'; if ('expense' !== $type && 'revenue' !== $type) { - Log::warning(sprintf('Account number "%s" is not unique and account type "%s" cannot share its account number.', $value, $type)); + app('log')->warning(sprintf('Account number "%s" is not unique and account type "%s" cannot share its account number.', $value, $type)); return false; } Log::debug(sprintf('Account number "%s" is not unique but account type "%s" may share its account number.', $value, $type)); @@ -621,7 +668,7 @@ class FireflyValidator extends Validator /** @var AccountMeta $entry */ foreach ($set as $entry) { $otherAccount = $entry->account; - $otherType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $otherAccount->accountType->type)); + $otherType = (string)config(sprintf('firefly.shortNamesByFullName.%s', $otherAccount->accountType->type)); if (('expense' === $otherType || 'revenue' === $otherType) && $otherType !== $type) { Log::debug(sprintf('The other account with this account number is a "%s" so return true.', $otherType)); return true; @@ -638,23 +685,13 @@ class FireflyValidator extends Validator */ public function validateUniqueCurrencyCode($attribute, $value): bool { - return $this->validateUniqueCurrency('code', (string) $attribute, (string) $value); + return $this->validateUniqueCurrency('code', (string)$attribute, (string)$value); } /** - * @param $attribute - * @param $value - * @return bool - */ - public function validateUniqueCurrencyName($attribute, $value): bool - { - return $this->validateUniqueCurrency('name', (string) $attribute, (string) $value); - } - - /** - * @param string $field - * @param string $attribute - * @param string $value + * @param string $field + * @param string $attribute + * @param string $value * @return bool */ public function validateUniqueCurrency(string $field, string $attribute, string $value): bool @@ -667,27 +704,37 @@ class FireflyValidator extends Validator * @param $value * @return bool */ - public function validateUniqueCurrencySymbol($attribute, $value): bool + public function validateUniqueCurrencyName($attribute, $value): bool { - return $this->validateUniqueCurrency('symbol', (string) $attribute, (string) $value); + return $this->validateUniqueCurrency('name', (string)$attribute, (string)$value); } /** - * @param mixed $value - * @param mixed $parameters - * @param mixed $something + * @param $attribute + * @param $value + * @return bool + */ + public function validateUniqueCurrencySymbol($attribute, $value): bool + { + return $this->validateUniqueCurrency('symbol', (string)$attribute, (string)$value); + } + + /** + * @param mixed $value + * @param mixed $parameters + * @param mixed $something * * @return bool */ public function validateUniqueExistingWebhook($value, $parameters, $something): bool { - $existingId = (int) ($something[0] ?? 0); + $existingId = (int)($something[0] ?? 0); $trigger = 0; $response = 0; $delivery = 0; - $triggers = array_flip(config('firefly.webhooks.triggers')); - $responses = array_flip(config('firefly.webhooks.responses')); - $deliveries = array_flip(config('firefly.webhooks.deliveries')); + $triggers = Webhook::getTriggersForValidation(); + $responses = Webhook::getResponsesForValidation(); + $deliveries = Webhook::getDeliveriesForValidation(); if (auth()->check()) { // get existing webhook value: if (0 !== $existingId) { @@ -728,24 +775,24 @@ class FireflyValidator extends Validator * parameter 1: the field * parameter 2: an id to ignore (when editing) * - * @param mixed $attribute - * @param mixed $value - * @param mixed $parameters + * @param mixed $attribute + * @param mixed $value + * @param mixed $parameters * * @return bool */ public function validateUniqueObjectForUser($attribute, $value, $parameters): bool { [$table, $field] = $parameters; - $exclude = (int) ($parameters[2] ?? 0.0); + $exclude = (int)($parameters[2] ?? 0.0); /* * If other data (in $this->getData()) contains * ID field, set that field to be the $exclude. */ $data = $this->getData(); - if (!array_key_exists(2, $parameters) && array_key_exists('id', $data) && (int) $data['id'] > 0) { - $exclude = (int) $data['id']; + if (!array_key_exists(2, $parameters) && array_key_exists('id', $data) && (int)$data['id'] > 0) { + $exclude = (int)$data['id']; } // get entries from table $set = DB::table($table)->where('user_id', auth()->user()->id)->whereNull('deleted_at') @@ -763,9 +810,9 @@ class FireflyValidator extends Validator } /** - * @param mixed $attribute - * @param mixed $value - * @param mixed $parameters + * @param mixed $attribute + * @param mixed $value + * @param mixed $parameters * * @return bool */ @@ -777,18 +824,16 @@ class FireflyValidator extends Validator ->where('object_groups.user_id', auth()->user()->id) ->where('object_groups.title', $value); if (null !== $exclude) { - $query->where('object_groups.id', '!=', (int) $exclude); + $query->where('object_groups.id', '!=', (int)$exclude); } return 0 === $query->count(); } /** - * @param mixed $attribute - * @param mixed $value - * @param mixed $parameters - * - * See reference nr. 107 + * @param mixed $attribute + * @param mixed $value + * @param mixed $parameters * * @return bool */ @@ -798,7 +843,7 @@ class FireflyValidator extends Validator $query = DB::table('piggy_banks')->whereNull('piggy_banks.deleted_at') ->leftJoin('accounts', 'accounts.id', '=', 'piggy_banks.account_id')->where('accounts.user_id', auth()->user()->id); if (null !== $exclude) { - $query->where('piggy_banks.id', '!=', (int) $exclude); + $query->where('piggy_banks.id', '!=', (int)$exclude); } $query->where('piggy_banks.name', $value); @@ -806,18 +851,17 @@ class FireflyValidator extends Validator } /** - * @param mixed $value - * @param mixed $parameters + * @param mixed $value + * @param mixed $parameters * * @return bool */ public function validateUniqueWebhook($value, $parameters): bool { if (auth()->check()) { - // possible values - $triggers = array_flip(config('firefly.webhooks.triggers')); - $responses = array_flip(config('firefly.webhooks.responses')); - $deliveries = array_flip(config('firefly.webhooks.deliveries')); + $triggers = Webhook::getTriggersForValidation(); + $responses = Webhook::getResponsesForValidation(); + $deliveries = Webhook::getDeliveriesForValidation(); // integers $trigger = $triggers[$this->data['trigger']] ?? 0; diff --git a/app/Validation/GroupValidation.php b/app/Validation/GroupValidation.php index d4802bcc9e..eede3b3b91 100644 --- a/app/Validation/GroupValidation.php +++ b/app/Validation/GroupValidation.php @@ -35,49 +35,58 @@ use Log; */ trait GroupValidation { - /** - * @param Validator $validator - * - * @return array - */ - abstract protected function getTransactionsArray(Validator $validator): array; - - /** - * @param Validator $validator + * @param Validator $validator */ protected function preventNoAccountInfo(Validator $validator): void { $transactions = $this->getTransactionsArray($validator); - $keys = ['source_id', 'destination_id', 'source_name', 'destination_name', 'source_iban', 'destination_iban', 'source_number', 'destination_number']; + $keys = [ + 'source_id', + 'destination_id', + 'source_name', + 'destination_name', + 'source_iban', + 'destination_iban', + 'source_number', + 'destination_number', + ]; /** @var array $transaction */ foreach ($transactions as $index => $transaction) { $hasAccountInfo = false; $hasJournalId = array_key_exists('transaction_journal_id', $transaction); foreach ($keys as $key) { - if (array_key_exists($key, $transaction) && '' !== (string) $transaction[$key]) { + if (array_key_exists($key, $transaction) && '' !== (string)$transaction[$key]) { $hasAccountInfo = true; } } // set errors: if (false === $hasAccountInfo && !$hasJournalId) { $validator->errors()->add( - sprintf('transactions.%d.source_id', $index), (string) trans('validation.generic_no_source') + sprintf('transactions.%d.source_id', $index), + (string)trans('validation.generic_no_source') ); $validator->errors()->add( - sprintf('transactions.%d.destination_id', $index), (string) trans('validation.generic_no_destination') + sprintf('transactions.%d.destination_id', $index), + (string)trans('validation.generic_no_destination') ); } } - // only an issue if there is no transaction_journal_id } + /** + * @param Validator $validator + * + * @return array + */ + abstract protected function getTransactionsArray(Validator $validator): array; + /** * Adds an error to the "description" field when the user has submitted no descriptions and no * journal description. * - * @param Validator $validator + * @param Validator $validator */ protected function validateDescriptions(Validator $validator): void { @@ -85,7 +94,7 @@ trait GroupValidation $transactions = $this->getTransactionsArray($validator); $validDescriptions = 0; foreach ($transactions as $transaction) { - if ('' !== (string) ($transaction['description'] ?? null)) { + if ('' !== (string)($transaction['description'] ?? null)) { $validDescriptions++; } } @@ -93,13 +102,14 @@ trait GroupValidation // no valid descriptions? if (0 === $validDescriptions) { $validator->errors()->add( - 'transactions.0.description', (string) trans('validation.filled', ['attribute' => (string) trans('validation.attributes.description')]) + 'transactions.0.description', + (string)trans('validation.filled', ['attribute' => (string)trans('validation.attributes.description')]) ); } } /** - * @param Validator $validator + * @param Validator $validator */ protected function validateGroupDescription(Validator $validator): void { @@ -109,7 +119,7 @@ trait GroupValidation $groupTitle = $data['group_title'] ?? ''; if ('' === $groupTitle && count($transactions) > 1) { - $validator->errors()->add('group_title', (string) trans('validation.group_title_mandatory')); + $validator->errors()->add('group_title', (string)trans('validation.group_title_mandatory')); } } @@ -117,8 +127,8 @@ trait GroupValidation * This method validates if the user has submitted transaction journal ID's for each array they submit, if they've submitted more than 1 transaction * journal. This check is necessary because Firefly III isn't able to distinguish between journals without the ID. * - * @param Validator $validator - * @param TransactionGroup $transactionGroup + * @param Validator $validator + * @param TransactionGroup $transactionGroup */ protected function validateJournalIds(Validator $validator, TransactionGroup $transactionGroup): void { @@ -133,7 +143,7 @@ trait GroupValidation } // check each array: /** - * @var int $index + * @var int $index * @var array $transaction */ foreach ($transactions as $index => $transaction) { @@ -144,10 +154,10 @@ trait GroupValidation /** * Do the validation required by validateJournalIds. * - * @param Validator $validator - * @param int $index - * @param array $transaction - * @param TransactionGroup $transactionGroup + * @param Validator $validator + * @param int $index + * @param array $transaction + * @param TransactionGroup $transactionGroup * * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ @@ -165,9 +175,9 @@ trait GroupValidation } $count = $transactionGroup->transactionJournals()->where('transaction_journals.id', $journalId)->count(); if (null === $journalId || 0 === $count) { - Log::warning(sprintf('Transaction group #%d has %d journals with ID %d', $transactionGroup->id, $count, $journalId)); - Log::warning('Invalid submission: Each split must have transaction_journal_id (either valid ID or 0).'); - $validator->errors()->add(sprintf('transactions.%d.source_name', $index), (string) trans('validation.need_id_in_edit')); + app('log')->warning(sprintf('Transaction group #%d has %d journals with ID %d', $transactionGroup->id, $count, $journalId)); + app('log')->warning('Invalid submission: Each split must have transaction_journal_id (either valid ID or 0).'); + $validator->errors()->add(sprintf('transactions.%d.source_name', $index), (string)trans('validation.need_id_in_edit')); } } } diff --git a/app/Validation/RecurrenceValidation.php b/app/Validation/RecurrenceValidation.php index d4400760ee..81b437fac1 100644 --- a/app/Validation/RecurrenceValidation.php +++ b/app/Validation/RecurrenceValidation.php @@ -41,9 +41,9 @@ trait RecurrenceValidation /** * Validate account information input for recurrences which are being updated. * - * See reference nr. 101 + * TODO Must always trigger when the type of the recurrence changes. * - * @param Validator $validator + * @param Validator $validator */ public function valUpdateAccountInfo(Validator $validator): void { @@ -66,7 +66,7 @@ trait RecurrenceValidation Log::debug(sprintf('Determined type to be %s.', $transactionType)); } if (null === $first) { - Log::warning('Just going to assume type is a withdrawal.'); + app('log')->warning('Just going to assume type is a withdrawal.'); $transactionType = 'withdrawal'; } } @@ -91,7 +91,7 @@ trait RecurrenceValidation continue; } // validate source account. - $sourceId = array_key_exists('source_id', $transaction) ? (int) $transaction['source_id'] : null; + $sourceId = array_key_exists('source_id', $transaction) ? (int)$transaction['source_id'] : null; $sourceName = $transaction['source_name'] ?? null; $validSource = $accountValidator->validateSource(['id' => $sourceId, 'name' => $sourceName]); @@ -103,7 +103,7 @@ trait RecurrenceValidation return; } // validate destination account - $destinationId = array_key_exists('destination_id', $transaction) ? (int) $transaction['destination_id'] : null; + $destinationId = array_key_exists('destination_id', $transaction) ? (int)$transaction['destination_id'] : null; $destinationName = $transaction['destination_name'] ?? null; $validDestination = $accountValidator->validateDestination(['id' => $destinationId, 'name' => $destinationName,]); // do something with result: @@ -119,22 +119,22 @@ trait RecurrenceValidation /** * Adds an error to the validator when there are no repetitions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ public function validateOneRepetition(Validator $validator): void { $data = $validator->getData(); $repetitions = $data['repetitions'] ?? []; // need at least one transaction - if (!is_countable($repetitions) || empty($repetitions)) { - $validator->errors()->add('repetitions', (string) trans('validation.at_least_one_repetition')); + if (!is_countable($repetitions) || 0 === count($repetitions)) { + $validator->errors()->add('repetitions', (string)trans('validation.at_least_one_repetition')); } } /** * Adds an error to the validator when there are no repetitions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ public function validateOneRepetitionUpdate(Validator $validator): void { @@ -144,8 +144,8 @@ trait RecurrenceValidation return; } // need at least one transaction - if (empty($repetitions)) { - $validator->errors()->add('repetitions', (string) trans('validation.at_least_one_repetition')); + if (0 === count($repetitions)) { + $validator->errors()->add('repetitions', (string)trans('validation.at_least_one_repetition')); } } @@ -153,7 +153,7 @@ trait RecurrenceValidation * 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 + * @param Validator $validator */ public function validateRecurrenceRepetition(Validator $validator): void { @@ -162,15 +162,15 @@ trait RecurrenceValidation $repeatUntil = $data['repeat_until'] ?? null; if (null !== $repetitions && null !== $repeatUntil) { // expect a date OR count: - $validator->errors()->add('repeat_until', (string) trans('validation.require_repeat_until')); - $validator->errors()->add('nr_of_repetitions', (string) trans('validation.require_repeat_until')); + $validator->errors()->add('repeat_until', (string)trans('validation.require_repeat_until')); + $validator->errors()->add('nr_of_repetitions', (string)trans('validation.require_repeat_until')); } } public function validateRecurringConfig(Validator $validator) { $data = $validator->getData(); - $reps = array_key_exists('nr_of_repetitions', $data) ? (int) $data['nr_of_repetitions'] : null; + $reps = array_key_exists('nr_of_repetitions', $data) ? (int)$data['nr_of_repetitions'] : null; $repeatUntil = array_key_exists('repeat_until', $data) ? new Carbon($data['repeat_until']) : null; if (null === $reps && null === $repeatUntil) { @@ -186,19 +186,19 @@ trait RecurrenceValidation } /** - * @param Validator $validator + * @param Validator $validator */ public function validateRepetitionMoment(Validator $validator): void { $data = $validator->getData(); $repetitions = $data['repetitions'] ?? []; if (!is_array($repetitions)) { - $validator->errors()->add(sprintf('repetitions.%d.type', 0), (string) trans('validation.valid_recurrence_rep_type')); + $validator->errors()->add(sprintf('repetitions.%d.type', 0), (string)trans('validation.valid_recurrence_rep_type')); return; } /** - * @var int $index + * @var int $index * @var array $repetition */ foreach ($repetitions as $index => $repetition) { @@ -211,23 +211,23 @@ trait RecurrenceValidation $repetition['moment'] = $repetition['moment'] ?? 'invalid'; switch ($repetition['type'] ?? 'empty') { default: - $validator->errors()->add(sprintf('repetitions.%d.type', $index), (string) trans('validation.valid_recurrence_rep_type')); + $validator->errors()->add(sprintf('repetitions.%d.type', $index), (string)trans('validation.valid_recurrence_rep_type')); return; case 'daily': - $this->validateDaily($validator, $index, (string) $repetition['moment']); + $this->validateDaily($validator, $index, (string)$repetition['moment']); break; case 'monthly': - $this->validateMonthly($validator, $index, (int) $repetition['moment']); + $this->validateMonthly($validator, $index, (int)$repetition['moment']); break; case 'ndom': - $this->validateNdom($validator, $index, (string) $repetition['moment']); + $this->validateNdom($validator, $index, (string)$repetition['moment']); break; case 'weekly': - $this->validateWeekly($validator, $index, (int) $repetition['moment']); + $this->validateWeekly($validator, $index, (int)$repetition['moment']); break; case 'yearly': - $this->validateYearly($validator, $index, (string) $repetition['moment']); + $this->validateYearly($validator, $index, (string)$repetition['moment']); break; } } @@ -236,28 +236,28 @@ trait RecurrenceValidation /** * If the repetition type is daily, the moment should be empty. * - * @param Validator $validator - * @param int $index - * @param string $moment + * @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), (string) trans('validation.valid_recurrence_rep_moment')); + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string)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 + * @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), (string) trans('validation.valid_recurrence_rep_moment')); + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string)trans('validation.valid_recurrence_rep_moment')); } } @@ -265,50 +265,50 @@ trait RecurrenceValidation * 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 + * @param Validator $validator + * @param int $index + * @param string $moment */ protected function validateNdom(Validator $validator, int $index, string $moment): void { $parameters = explode(',', $moment); if (2 !== count($parameters)) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string) trans('validation.valid_recurrence_rep_moment')); + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string)trans('validation.valid_recurrence_rep_moment')); return; } - $nthDay = (int) ($parameters[0] ?? 0.0); - $dayOfWeek = (int) ($parameters[1] ?? 0.0); + $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), (string) trans('validation.valid_recurrence_rep_moment')); + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string)trans('validation.valid_recurrence_rep_moment')); return; } if ($dayOfWeek < 1 || $dayOfWeek > 7) { - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string) trans('validation.valid_recurrence_rep_moment')); + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string)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 + * @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), (string) trans('validation.valid_recurrence_rep_moment')); + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string)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 + * @param Validator $validator + * @param int $index + * @param string $moment */ protected function validateYearly(Validator $validator, int $index, string $moment): void { @@ -316,7 +316,7 @@ trait RecurrenceValidation Carbon::createFromFormat('Y-m-d', $moment); } catch (InvalidArgumentException $e) { Log::debug(sprintf('Invalid argument for Carbon: %s', $e->getMessage())); - $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string) trans('validation.valid_recurrence_rep_moment')); + $validator->errors()->add(sprintf('repetitions.%d.moment', $index), (string)trans('validation.valid_recurrence_rep_moment')); } } } diff --git a/app/Validation/TransactionValidation.php b/app/Validation/TransactionValidation.php index a364583632..0c5dcfb61e 100644 --- a/app/Validation/TransactionValidation.php +++ b/app/Validation/TransactionValidation.php @@ -27,6 +27,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\Transaction; use FireflyIII\Models\TransactionGroup; use FireflyIII\Models\TransactionJournal; +use FireflyIII\Models\TransactionType; use Illuminate\Validation\Validator; use Log; @@ -38,7 +39,7 @@ trait TransactionValidation /** * Validates the given account information. Switches on given transaction type. * - * @param Validator $validator + * @param Validator $validator */ public function validateAccountInformation(Validator $validator): void { @@ -50,7 +51,7 @@ trait TransactionValidation Log::debug(sprintf('Going to loop %d transaction(s)', count($transactions))); /** - * @var int $index + * @var int $index * @var array $transaction */ foreach ($transactions as $index => $transaction) { @@ -62,7 +63,7 @@ trait TransactionValidation } /** - * @param Validator $validator + * @param Validator $validator * * @return array */ @@ -86,10 +87,10 @@ trait TransactionValidation } /** - * @param Validator $validator - * @param int $index - * @param string $transactionType - * @param array $transaction + * @param Validator $validator + * @param int $index + * @param string $transactionType + * @param array $transaction */ protected function validateSingleAccount(Validator $validator, int $index, string $transactionType, array $transaction): void { @@ -100,17 +101,17 @@ trait TransactionValidation $accountValidator->setTransactionType($transactionType); // validate source account. - $sourceId = array_key_exists('source_id', $transaction) ? (int) $transaction['source_id'] : null; - $sourceName = array_key_exists('source_name', $transaction) ? (string) $transaction['source_name'] : null; - $sourceIban = array_key_exists('source_iban', $transaction) ? (string) $transaction['source_iban'] : null; - $sourceNumber = array_key_exists('source_number', $transaction) ? (string) $transaction['source_number'] : null; - $array = [ + $sourceId = array_key_exists('source_id', $transaction) ? (int)$transaction['source_id'] : null; + $sourceName = array_key_exists('source_name', $transaction) ? (string)$transaction['source_name'] : null; + $sourceIban = array_key_exists('source_iban', $transaction) ? (string)$transaction['source_iban'] : null; + $sourceNumber = array_key_exists('source_number', $transaction) ? (string)$transaction['source_number'] : null; + $source = [ 'id' => $sourceId, 'name' => $sourceName, 'iban' => $sourceIban, 'number' => $sourceNumber, ]; - $validSource = $accountValidator->validateSource($array); + $validSource = $accountValidator->validateSource($source); // do something with result: if (false === $validSource) { @@ -120,29 +121,64 @@ trait TransactionValidation return; } // validate destination account - $destinationId = array_key_exists('destination_id', $transaction) ? (int) $transaction['destination_id'] : null; - $destinationName = array_key_exists('destination_name', $transaction) ? (string) $transaction['destination_name'] : null; - $destinationIban = array_key_exists('destination_iban', $transaction) ? (string) $transaction['destination_iban'] : null; - $destinationNumber = array_key_exists('destination_number', $transaction) ? (string) $transaction['destination_number'] : null; - $array = [ + $destinationId = array_key_exists('destination_id', $transaction) ? (int)$transaction['destination_id'] : null; + $destinationName = array_key_exists('destination_name', $transaction) ? (string)$transaction['destination_name'] : null; + $destinationIban = array_key_exists('destination_iban', $transaction) ? (string)$transaction['destination_iban'] : null; + $destinationNumber = array_key_exists('destination_number', $transaction) ? (string)$transaction['destination_number'] : null; + $destination = [ 'id' => $destinationId, 'name' => $destinationName, 'iban' => $destinationIban, 'number' => $destinationNumber, ]; - $validDestination = $accountValidator->validateDestination($array); + $validDestination = $accountValidator->validateDestination($destination); // do something with result: if (false === $validDestination) { $validator->errors()->add(sprintf('transactions.%d.destination_id', $index), $accountValidator->destError); $validator->errors()->add(sprintf('transactions.%d.destination_name', $index), $accountValidator->destError); } + + // sanity check for reconciliation accounts. They can't both be null. + $this->sanityCheckReconciliation($validator, $transactionType, $index, $source, $destination); + } + + /** + * @param Validator $validator + * @param string $transactionType + * @param int $index + * @param array $source + * @param array $destination + * @return void + */ + protected function sanityCheckReconciliation(Validator $validator, string $transactionType, int $index, array $source, array $destination): void + { + Log::debug('Now in sanityCheckReconciliation'); + if (TransactionType::RECONCILIATION === ucfirst($transactionType) && + null === $source['id'] && null === $source['name'] && null === $destination['id'] && null === $destination['name'] + ) { + Log::debug('Both are NULL, error!'); + $validator->errors()->add(sprintf('transactions.%d.source_id', $index), trans('validation.reconciliation_either_account')); + $validator->errors()->add(sprintf('transactions.%d.source_name', $index), trans('validation.reconciliation_either_account')); + $validator->errors()->add(sprintf('transactions.%d.destination_id', $index), trans('validation.reconciliation_either_account')); + $validator->errors()->add(sprintf('transactions.%d.destination_name', $index), trans('validation.reconciliation_either_account')); + } + + if (TransactionType::RECONCILIATION === $transactionType && + (null !== $source['id'] || null !== $source['name']) && + (null !== $destination['id'] || null !== $destination['name'])) { + Log::debug('Both are not NULL, error!'); + $validator->errors()->add(sprintf('transactions.%d.source_id', $index), trans('validation.reconciliation_either_account')); + $validator->errors()->add(sprintf('transactions.%d.source_name', $index), trans('validation.reconciliation_either_account')); + $validator->errors()->add(sprintf('transactions.%d.destination_id', $index), trans('validation.reconciliation_either_account')); + $validator->errors()->add(sprintf('transactions.%d.destination_name', $index), trans('validation.reconciliation_either_account')); + } } /** * Validates the given account information. Switches on given transaction type. * - * @param Validator $validator - * @param TransactionGroup $transactionGroup + * @param Validator $validator + * @param TransactionGroup $transactionGroup */ public function validateAccountInformationUpdate(Validator $validator, TransactionGroup $transactionGroup): void { @@ -150,7 +186,7 @@ trait TransactionValidation $transactions = $this->getTransactionsArray($validator); /** - * @var int $index + * @var int $index * @var array $transaction */ foreach ($transactions as $index => $transaction) { @@ -159,10 +195,10 @@ trait TransactionValidation } /** - * @param Validator $validator - * @param int $index - * @param array $transaction - * @param TransactionGroup $transactionGroup + * @param Validator $validator + * @param int $index + * @param array $transaction + * @param TransactionGroup $transactionGroup */ protected function validateSingleUpdate(Validator $validator, int $index, array $transaction, TransactionGroup $transactionGroup): void { @@ -188,13 +224,13 @@ trait TransactionValidation // validate if the submitted source and / or name are valid if (array_key_exists('source_id', $transaction) || array_key_exists('source_name', $transaction)) { Log::debug('Will try to validate source account information.'); - $sourceId = (int) ($transaction['source_id'] ?? 0); + $sourceId = (int)($transaction['source_id'] ?? 0); $sourceName = $transaction['source_name'] ?? null; $validSource = $accountValidator->validateSource(['id' => $sourceId, 'name' => $sourceName]); // do something with result: if (false === $validSource) { - Log::warning('Looks like the source account is not valid so complain to the user about it.'); + app('log')->warning('Looks like the source account is not valid so complain to the user about it.'); $validator->errors()->add(sprintf('transactions.%d.source_id', $index), $accountValidator->sourceError); $validator->errors()->add(sprintf('transactions.%d.source_name', $index), $accountValidator->sourceError); @@ -216,13 +252,13 @@ trait TransactionValidation $accountValidator->source = $source; } } - $destinationId = (int) ($transaction['destination_id'] ?? 0); + $destinationId = (int)($transaction['destination_id'] ?? 0); $destinationName = $transaction['destination_name'] ?? null; $array = ['id' => $destinationId, 'name' => $destinationName,]; $validDestination = $accountValidator->validateDestination($array); // do something with result: if (false === $validDestination) { - Log::warning('Looks like the destination account is not valid so complain to the user about it.'); + app('log')->warning('Looks like the destination account is not valid so complain to the user about it.'); $validator->errors()->add(sprintf('transactions.%d.destination_id', $index), $accountValidator->destError); $validator->errors()->add(sprintf('transactions.%d.destination_name', $index), $accountValidator->destError); } @@ -232,8 +268,8 @@ trait TransactionValidation } /** - * @param TransactionGroup $group - * @param array $transactions + * @param TransactionGroup $group + * @param array $transactions * * @return string */ @@ -243,8 +279,8 @@ trait TransactionValidation } /** - * @param array $transaction - * @param TransactionGroup $transactionGroup + * @param array $transaction + * @param TransactionGroup $transactionGroup * * @return Account|null */ @@ -257,7 +293,7 @@ trait TransactionValidation } /** @var TransactionJournal $journal */ foreach ($transactionGroup->transactionJournals as $journal) { - if ((int) $journal->id === (int) $transaction['transaction_journal_id']) { + if ((int)$journal->id === (int)$transaction['transaction_journal_id']) { return $journal->transactions()->where('amount', '<', 0)->first()->account; } } @@ -268,7 +304,7 @@ trait TransactionValidation /** * Adds an error to the validator when there are no transactions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ public function validateOneRecurrenceTransaction(Validator $validator): void { @@ -276,23 +312,23 @@ trait TransactionValidation $transactions = $this->getTransactionsArray($validator); // need at least one transaction - if (empty($transactions)) { - $validator->errors()->add('transactions', (string) trans('validation.at_least_one_transaction')); + if (0 === count($transactions)) { + $validator->errors()->add('transactions', (string)trans('validation.at_least_one_transaction')); } } /** * Adds an error to the validator when there are no transactions in the array of data. * - * @param Validator $validator + * @param Validator $validator */ public function validateOneTransaction(Validator $validator): void { Log::debug('Now in validateOneTransaction()'); $transactions = $this->getTransactionsArray($validator); // need at least one transaction - if (empty($transactions)) { - $validator->errors()->add('transactions.0.description', (string) trans('validation.at_least_one_transaction')); + if (0 === count($transactions)) { + $validator->errors()->add('transactions.0.description', (string)trans('validation.at_least_one_transaction')); Log::debug('Added error: at_least_one_transaction.'); return; @@ -301,14 +337,14 @@ trait TransactionValidation } /** - * @param Validator $validator + * @param Validator $validator */ public function validateTransactionArray(Validator $validator): void { $transactions = $this->getTransactionsArray($validator); foreach ($transactions as $key => $value) { if (!is_int($key)) { - $validator->errors()->add('transactions.0.description', (string) trans('validation.at_least_one_transaction')); + $validator->errors()->add('transactions.0.description', (string)trans('validation.at_least_one_transaction')); Log::debug('Added error: at_least_one_transaction.'); return; @@ -319,7 +355,7 @@ trait TransactionValidation /** * All types of splits must be equal. * - * @param Validator $validator + * @param Validator $validator */ public function validateTransactionTypes(Validator $validator): void { @@ -332,20 +368,20 @@ trait TransactionValidation } $unique = array_unique($types); if (count($unique) > 1) { - $validator->errors()->add('transactions.0.type', (string) trans('validation.transaction_types_equal')); + $validator->errors()->add('transactions.0.type', (string)trans('validation.transaction_types_equal')); return; } $first = $unique[0] ?? 'invalid'; if ('invalid' === $first) { - $validator->errors()->add('transactions.0.type', (string) trans('validation.invalid_transaction_type')); + $validator->errors()->add('transactions.0.type', (string)trans('validation.invalid_transaction_type')); } } /** * All types of splits must be equal. * - * @param Validator $validator + * @param Validator $validator */ public function validateTransactionTypesForUpdate(Validator $validator): void { @@ -353,14 +389,14 @@ trait TransactionValidation $transactions = $this->getTransactionsArray($validator); $types = []; foreach ($transactions as $transaction) { - $originalType = $this->getOriginalType((int) ($transaction['transaction_journal_id'] ?? 0)); + $originalType = $this->getOriginalType((int)($transaction['transaction_journal_id'] ?? 0)); // if type is not set, fall back to the type of the journal, if one is given. $types[] = $transaction['type'] ?? $originalType; } $unique = array_unique($types); if (count($unique) > 1) { - Log::warning('Add error for mismatch transaction types.'); - $validator->errors()->add('transactions.0.type', (string) trans('validation.transaction_types_equal')); + app('log')->warning('Add error for mismatch transaction types.'); + $validator->errors()->add('transactions.0.type', (string)trans('validation.transaction_types_equal')); return; } @@ -368,7 +404,7 @@ trait TransactionValidation } /** - * @param int $journalId + * @param int $journalId * * @return string */ @@ -387,7 +423,7 @@ trait TransactionValidation } /** - * @param Validator $validator + * @param Validator $validator */ private function validateEqualAccounts(Validator $validator): void { @@ -411,26 +447,26 @@ trait TransactionValidation default: case 'withdrawal': if (count($sources) > 1) { - $validator->errors()->add('transactions.0.source_id', (string) trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.source_id', (string)trans('validation.all_accounts_equal')); } break; case 'deposit': if (count($dests) > 1) { - $validator->errors()->add('transactions.0.destination_id', (string) trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.destination_id', (string)trans('validation.all_accounts_equal')); } break; case'transfer': if (count($sources) > 1 || count($dests) > 1) { - $validator->errors()->add('transactions.0.source_id', (string) trans('validation.all_accounts_equal')); - $validator->errors()->add('transactions.0.destination_id', (string) trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.source_id', (string)trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.destination_id', (string)trans('validation.all_accounts_equal')); } break; } } /** - * @param Validator $validator - * @param TransactionGroup $transactionGroup + * @param Validator $validator + * @param TransactionGroup $transactionGroup */ private function validateEqualAccountsForUpdate(Validator $validator, TransactionGroup $transactionGroup): void { @@ -453,16 +489,16 @@ trait TransactionValidation $result = $this->compareAccountData($type, $comparison); if (false === $result) { if ('withdrawal' === $type) { - $validator->errors()->add('transactions.0.source_id', (string) trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.source_id', (string)trans('validation.all_accounts_equal')); } if ('deposit' === $type) { - $validator->errors()->add('transactions.0.destination_id', (string) trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.destination_id', (string)trans('validation.all_accounts_equal')); } if ('transfer' === $type) { - $validator->errors()->add('transactions.0.source_id', (string) trans('validation.all_accounts_equal')); - $validator->errors()->add('transactions.0.destination_id', (string) trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.source_id', (string)trans('validation.all_accounts_equal')); + $validator->errors()->add('transactions.0.destination_id', (string)trans('validation.all_accounts_equal')); } - Log::warning('Add error about equal accounts.'); + app('log')->warning('Add error about equal accounts.'); return; } @@ -470,7 +506,7 @@ trait TransactionValidation } /** - * @param array $transactions + * @param array $transactions * * @return array */ @@ -483,7 +519,7 @@ trait TransactionValidation /** @var array $transaction */ foreach ($transactions as $transaction) { // source or destination may be omitted. If this is the case, use the original source / destination name + ID. - $originalData = $this->getOriginalData((int) ($transaction['transaction_journal_id'] ?? 0)); + $originalData = $this->getOriginalData((int)($transaction['transaction_journal_id'] ?? 0)); // get field. $comparison[$field][] = $transaction[$field] ?? $originalData[$field]; @@ -494,7 +530,7 @@ trait TransactionValidation } /** - * @param int $journalId + * @param int $journalId * * @return array */ @@ -526,8 +562,8 @@ trait TransactionValidation } /** - * @param string $type - * @param array $comparison + * @param string $type + * @param array $comparison * * @return bool */ @@ -541,7 +577,7 @@ trait TransactionValidation } /** - * @param array $comparison + * @param array $comparison * * @return bool */ @@ -560,7 +596,7 @@ trait TransactionValidation } /** - * @param array $array + * @param array $array * * @return bool */ @@ -570,7 +606,7 @@ trait TransactionValidation } /** - * @param array $comparison + * @param array $comparison * * @return bool */ @@ -589,7 +625,7 @@ trait TransactionValidation } /** - * @param array $comparison + * @param array $comparison * * @return bool */ diff --git a/bootstrap/app.php b/bootstrap/app.php index 0fd478deb3..6f71022e3b 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -21,7 +21,6 @@ declare(strict_types=1); -use Illuminate\Contracts\View\Factory as ViewFactory; /* |-------------------------------------------------------------------------- | Create The Application @@ -37,8 +36,8 @@ bcscale(24); if (!function_exists('envNonEmpty')) { /** - * @param string $key - * @param null $default + * @param string $key + * @param null $default * * @return mixed|null */ @@ -55,8 +54,8 @@ if (!function_exists('envNonEmpty')) { if (!function_exists('str_is_equal')) { /** - * @param string $left - * @param string $right + * @param string $left + * @param string $right * * @return bool */ @@ -67,7 +66,7 @@ if (!function_exists('str_is_equal')) { } $app = new Illuminate\Foundation\Application( - realpath(__DIR__ . '/../') + realpath(__DIR__.'/../') ); /* diff --git a/changelog.md b/changelog.md index 48bd10e092..66e7dbe6fe 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,62 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 5.8.0-alpha.1 - 2023-01-08 + +This is the first release of the new 5.8.0 series of Firefly III. It should upgrade the database automatically BUT +make a backup of your database first! I guarantee nothing. + +### Warnings + +- ⚠ Make a backup of your database first! +- ⚠ This version requires **PHP 8.2**. + +You can access the new V3 layout under `/v3/`. If you decide to use or test it: + +- ⚠ Read the instructions under the ☠ icon FIRST. +- ⚠ The new layout is not yet finished. Use it to change your data at your own risk. + +### Added + +Lots of new stuff that I invite you to test and break. + +- [Issue 4975](https://github.com/firefly-iii/firefly-iii/issues/4975) Rules can copy/move description to notes and vice versa +- [Issue 5031](https://github.com/firefly-iii/firefly-iii/issues/5031) You can invite users to your installation when registration is off +- [Issue 5213](https://github.com/firefly-iii/firefly-iii/issues/5213) You can trigger recurring transactions beforehand +- [Issue 5592](https://github.com/firefly-iii/firefly-iii/issues/5592) Transactions have a little history box to show how rules changed them +- [Issue 5752](https://github.com/firefly-iii/firefly-iii/issues/5752) Firefly III can send Slack notifications instead of emails +- [Issue 5862](https://github.com/firefly-iii/firefly-iii/issues/5862) Search can filter on reconciled transactions +- [Issue 6086](https://github.com/firefly-iii/firefly-iii/issues/6086) All search filters can be negative by putting `-` in front of them +- [Issue 6441](https://github.com/firefly-iii/firefly-iii/issues/6441) Buttons to purge deleted data, which is easy for data imports +- [Issue 6457](https://github.com/firefly-iii/firefly-iii/issues/6457) Rule trigger 'transaction exists', that will always trigger +- [Issue 6526](https://github.com/firefly-iii/firefly-iii/issues/6526) Option to disable rules and/or webhooks when saving transactions +- [Issue 6605](https://github.com/firefly-iii/firefly-iii/issues/6605) You can search for external ID values +- Working beta of the new layout under `/v3/` +- New authentication screens that support dark mode. +- There is a page for webhooks. + +### Changed +- Firefly III requires PHP 8.2 +- Liabilities are no longer part of your net worth. +- Liabilities no longer need two transactions to be managed properly (see the documentation) + +### Removed +- [Issue 4198](https://github.com/firefly-iii/firefly-iii/issues/4198) The total available budget amount bar on the `/budgets` page is no longer manageable but will be auto-calculated + +### Fixed + +Not many bugfixes (yet). + +- [Issue 6581](https://github.com/firefly-iii/firefly-iii/issues/6581) Fields were not cleared in the transaction screen in some cases + +### API + +New `/v2/` endpoints are being implemented that prepare the application for (among other things) the ability +to manage multiple financial administrations. The documentation for these endpoints will be at +https://api-docs.firefly-iii.org/. + +- [Issue 6130](https://github.com/firefly-iii/firefly-iii/issues/6130) You can now create a reconciliation transaction + ## 5.7.18 - 2023-01-03 ### Fixed diff --git a/composer.json b/composer.json index c29ffc0664..f2f1441a81 100644 --- a/composer.json +++ b/composer.json @@ -65,7 +65,7 @@ } ], "require": { - "php": ">=8", + "php": ">=8.2", "ext-bcmath": "*", "ext-curl": "*", "ext-fileinfo": "*", @@ -91,6 +91,7 @@ "laravel/framework": "^9", "laravel/passport": "11.*", "laravel/sanctum": "^3.0", + "laravel/slack-notification-channel": "^2.4", "laravel/ui": "^4.1", "laravelcollective/html": "6.*", "league/commonmark": "2.*", @@ -109,10 +110,16 @@ }, "require-dev": { "barryvdh/laravel-ide-helper": "2.*", - "filp/whoops": "2.*", + "ergebnis/phpstan-rules": "^1.0", "fakerphp/faker": "1.*", + "filp/whoops": "2.*", "mockery/mockery": "1.*", - "phpunit/phpunit": "^9.5" + "nunomaduro/larastan": "^2.0", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-deprecation-rules": "^1.0", + "phpstan/phpstan-strict-rules": "^1.4", + "phpunit/phpunit": "^9.5", + "thecodingmachine/phpstan-strict-rules": "^1.0" }, "suggest": { }, @@ -193,6 +200,7 @@ "@php artisan firefly-iii:report-empty-objects", "@php artisan firefly-iii:report-sum", "@php artisan firefly-iii:restore-oauth-keys", + "@php artisan firefly-iii:upgrade-group-information", "@php artisan firefly-iii:set-latest-version --james-is-cool", "@php artisan firefly:instructions update", "@php artisan firefly-iii:verify-security-alerts", @@ -205,7 +213,7 @@ }, "config": { "platform": { - "php": "8.0.19" + "php": "8.2" }, "preferred-install": "dist", "sort-packages": true, diff --git a/composer.lock b/composer.lock index cdd8b066e0..cf858aaab5 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "aa2338cf980bee39c1e9ab48ace47a04", + "content-hash": "5dde180061b5fd718845ee783ca08b34", "packages": [ { "name": "bacon/bacon-qr-code", @@ -624,30 +624,29 @@ }, { "name": "doctrine/event-manager", - "version": "1.2.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/event-manager.git", - "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520" + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/event-manager/zipball/95aa4cb529f1e96576f3fda9f5705ada4056a520", - "reference": "95aa4cb529f1e96576f3fda9f5705ada4056a520", + "url": "https://api.github.com/repos/doctrine/event-manager/zipball/750671534e0241a7c50ea5b43f67e23eb5c96f32", + "reference": "750671534e0241a7c50ea5b43f67e23eb5c96f32", "shasum": "" }, "require": { - "doctrine/deprecations": "^0.5.3 || ^1", - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "conflict": { "doctrine/common": "<2.9" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^10", - "phpstan/phpstan": "~1.4.10 || ^1.8.8", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.24" + "doctrine/coding-standard": "^10", + "phpstan/phpstan": "^1.8.8", + "phpunit/phpunit": "^9.5", + "vimeo/psalm": "^4.28" }, "type": "library", "autoload": { @@ -696,7 +695,7 @@ ], "support": { "issues": "https://github.com/doctrine/event-manager/issues", - "source": "https://github.com/doctrine/event-manager/tree/1.2.0" + "source": "https://github.com/doctrine/event-manager/tree/2.0.0" }, "funding": [ { @@ -712,7 +711,7 @@ "type": "tidelift" } ], - "time": "2022-10-12T20:51:15+00:00" + "time": "2022-10-12T20:59:15+00:00" }, { "name": "doctrine/inflector", @@ -946,16 +945,16 @@ }, { "name": "egulias/email-validator", - "version": "3.2.4", + "version": "3.2.5", "source": { "type": "git", "url": "https://github.com/egulias/EmailValidator.git", - "reference": "5f35e41eba05fdfbabd95d72f83795c835fb7ed2" + "reference": "b531a2311709443320c786feb4519cfaf94af796" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/5f35e41eba05fdfbabd95d72f83795c835fb7ed2", - "reference": "5f35e41eba05fdfbabd95d72f83795c835fb7ed2", + "url": "https://api.github.com/repos/egulias/EmailValidator/zipball/b531a2311709443320c786feb4519cfaf94af796", + "reference": "b531a2311709443320c786feb4519cfaf94af796", "shasum": "" }, "require": { @@ -964,7 +963,6 @@ "symfony/polyfill-intl-idn": "^1.15" }, "require-dev": { - "php-coveralls/php-coveralls": "^2.2", "phpunit/phpunit": "^8.5.8|^9.3.3", "vimeo/psalm": "^4" }, @@ -1002,7 +1000,7 @@ ], "support": { "issues": "https://github.com/egulias/EmailValidator/issues", - "source": "https://github.com/egulias/EmailValidator/tree/3.2.4" + "source": "https://github.com/egulias/EmailValidator/tree/3.2.5" }, "funding": [ { @@ -1010,7 +1008,7 @@ "type": "github" } ], - "time": "2022-12-30T14:09:25+00:00" + "time": "2023-01-02T17:26:14+00:00" }, { "name": "facade/ignition-contracts", @@ -1858,16 +1856,16 @@ }, { "name": "laravel/framework", - "version": "v9.45.1", + "version": "v9.46.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "faeb20d3fc61b69790068161ab42bcf2d5faccbc" + "reference": "62b05b6de5733d89378a279e40230a71e5ab5d92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/faeb20d3fc61b69790068161ab42bcf2d5faccbc", - "reference": "faeb20d3fc61b69790068161ab42bcf2d5faccbc", + "url": "https://api.github.com/repos/laravel/framework/zipball/62b05b6de5733d89378a279e40230a71e5ab5d92", + "reference": "62b05b6de5733d89378a279e40230a71e5ab5d92", "shasum": "" }, "require": { @@ -2040,20 +2038,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-12-21T19:37:46+00:00" + "time": "2023-01-03T15:12:31+00:00" }, { "name": "laravel/passport", - "version": "v11.3.1", + "version": "v11.4.0", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "835febbfe875ba97306c026fdaa94f58f167363e" + "reference": "2d746b752b08e47f6b5bd69d8e76fbe477e23532" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/835febbfe875ba97306c026fdaa94f58f167363e", - "reference": "835febbfe875ba97306c026fdaa94f58f167363e", + "url": "https://api.github.com/repos/laravel/passport/zipball/2d746b752b08e47f6b5bd69d8e76fbe477e23532", + "reference": "2d746b752b08e47f6b5bd69d8e76fbe477e23532", "shasum": "" }, "require": { @@ -2117,20 +2115,20 @@ "issues": "https://github.com/laravel/passport/issues", "source": "https://github.com/laravel/passport" }, - "time": "2022-12-02T18:20:16+00:00" + "time": "2023-01-03T09:40:19+00:00" }, { "name": "laravel/sanctum", - "version": "v3.0.1", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "b71e80a3a8e8029e2ec8c1aa814b999609ce16dc" + "reference": "d823587299d50c3ae9c26fa1731ef0d5b725c788" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/b71e80a3a8e8029e2ec8c1aa814b999609ce16dc", - "reference": "b71e80a3a8e8029e2ec8c1aa814b999609ce16dc", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/d823587299d50c3ae9c26fa1731ef0d5b725c788", + "reference": "d823587299d50c3ae9c26fa1731ef0d5b725c788", "shasum": "" }, "require": { @@ -2182,7 +2180,7 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2022-07-29T21:33:30+00:00" + "time": "2023-01-03T09:38:46+00:00" }, { "name": "laravel/serializable-closure", @@ -2244,6 +2242,67 @@ }, "time": "2022-09-08T13:45:54+00:00" }, + { + "name": "laravel/slack-notification-channel", + "version": "v2.4.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/slack-notification-channel.git", + "reference": "060617a31562c88656c95c5971a36989122d4b53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/slack-notification-channel/zipball/060617a31562c88656c95c5971a36989122d4b53", + "reference": "060617a31562c88656c95c5971a36989122d4b53", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0|^7.0", + "illuminate/notifications": "~5.8.0|^6.0|^7.0|^8.0|^9.0", + "php": "^7.1.3|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^7.0|^8.0|^9.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.x-dev" + }, + "laravel": { + "providers": [ + "Illuminate\\Notifications\\SlackChannelServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Illuminate\\Notifications\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Slack Notification Channel for laravel.", + "keywords": [ + "laravel", + "notifications", + "slack" + ], + "support": { + "issues": "https://github.com/laravel/slack-notification-channel/issues", + "source": "https://github.com/laravel/slack-notification-channel/tree/v2.4.0" + }, + "time": "2022-01-12T18:07:54+00:00" + }, { "name": "laravel/ui", "version": "v4.1.1", @@ -2379,31 +2438,34 @@ }, { "name": "lcobucci/clock", - "version": "2.2.0", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/lcobucci/clock.git", - "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3" + "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/clock/zipball/fb533e093fd61321bfcbac08b131ce805fe183d3", - "reference": "fb533e093fd61321bfcbac08b131ce805fe183d3", + "url": "https://api.github.com/repos/lcobucci/clock/zipball/039ef98c6b57b101d10bd11d8fdfda12cbd996dc", + "reference": "039ef98c6b57b101d10bd11d8fdfda12cbd996dc", "shasum": "" }, "require": { - "php": "^8.0", - "stella-maris/clock": "^0.1.4" + "php": "~8.1.0 || ~8.2.0", + "psr/clock": "^1.0" + }, + "provide": { + "psr/clock-implementation": "1.0" }, "require-dev": { "infection/infection": "^0.26", - "lcobucci/coding-standard": "^8.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^0.12", - "phpstan/phpstan-deprecation-rules": "^0.12", - "phpstan/phpstan-phpunit": "^0.12", - "phpstan/phpstan-strict-rules": "^0.12", - "phpunit/phpunit": "^9.5" + "lcobucci/coding-standard": "^9.0", + "phpstan/extension-installer": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-deprecation-rules": "^1.1.1", + "phpstan/phpstan-phpunit": "^1.3.2", + "phpstan/phpstan-strict-rules": "^1.4.4", + "phpunit/phpunit": "^9.5.27" }, "type": "library", "autoload": { @@ -2424,7 +2486,7 @@ "description": "Yet another clock abstraction", "support": { "issues": "https://github.com/lcobucci/clock/issues", - "source": "https://github.com/lcobucci/clock/tree/2.2.0" + "source": "https://github.com/lcobucci/clock/tree/3.0.0" }, "funding": [ { @@ -2436,20 +2498,20 @@ "type": "patreon" } ], - "time": "2022-04-19T19:34:17+00:00" + "time": "2022-12-19T15:00:24+00:00" }, { "name": "lcobucci/jwt", - "version": "4.2.1", + "version": "4.3.0", "source": { "type": "git", "url": "https://github.com/lcobucci/jwt.git", - "reference": "72ac6d807ee51a70ad376ee03a2387e8646e10f3" + "reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/lcobucci/jwt/zipball/72ac6d807ee51a70ad376ee03a2387e8646e10f3", - "reference": "72ac6d807ee51a70ad376ee03a2387e8646e10f3", + "url": "https://api.github.com/repos/lcobucci/jwt/zipball/4d7de2fe0d51a96418c0d04004986e410e87f6b4", + "reference": "4d7de2fe0d51a96418c0d04004986e410e87f6b4", "shasum": "" }, "require": { @@ -2458,7 +2520,7 @@ "ext-mbstring": "*", "ext-openssl": "*", "ext-sodium": "*", - "lcobucci/clock": "^2.0", + "lcobucci/clock": "^2.0 || ^3.0", "php": "^7.4 || ^8.0" }, "require-dev": { @@ -2498,7 +2560,7 @@ ], "support": { "issues": "https://github.com/lcobucci/jwt/issues", - "source": "https://github.com/lcobucci/jwt/tree/4.2.1" + "source": "https://github.com/lcobucci/jwt/tree/4.3.0" }, "funding": [ { @@ -2510,7 +2572,7 @@ "type": "patreon" } ], - "time": "2022-08-19T23:14:07+00:00" + "time": "2023-01-02T13:28:00+00:00" }, { "name": "league/commonmark", @@ -2840,16 +2902,16 @@ }, { "name": "league/flysystem", - "version": "3.12.0", + "version": "3.12.1", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem.git", - "reference": "2aef65a47e44f2d6f9938f720f6dd697e7ba7b76" + "reference": "b934123c1f11ada6363d057d691e3065fa6d6d49" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/2aef65a47e44f2d6f9938f720f6dd697e7ba7b76", - "reference": "2aef65a47e44f2d6f9938f720f6dd697e7ba7b76", + "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/b934123c1f11ada6363d057d691e3065fa6d6d49", + "reference": "b934123c1f11ada6363d057d691e3065fa6d6d49", "shasum": "" }, "require": { @@ -2866,7 +2928,7 @@ "require-dev": { "async-aws/s3": "^1.5", "async-aws/simple-s3": "^1.1", - "aws/aws-sdk-php": "^3.198.1", + "aws/aws-sdk-php": "^3.220.0", "composer/semver": "^3.0", "ext-fileinfo": "*", "ext-ftp": "*", @@ -2911,7 +2973,7 @@ ], "support": { "issues": "https://github.com/thephpleague/flysystem/issues", - "source": "https://github.com/thephpleague/flysystem/tree/3.12.0" + "source": "https://github.com/thephpleague/flysystem/tree/3.12.1" }, "funding": [ { @@ -2927,7 +2989,7 @@ "type": "tidelift" } ], - "time": "2022-12-20T20:21:10+00:00" + "time": "2023-01-06T16:34:48+00:00" }, { "name": "league/fractal", @@ -3145,37 +3207,38 @@ }, { "name": "league/uri", - "version": "6.7.2", + "version": "6.8.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "d3b50812dd51f3fbf176344cc2981db03d10fe06" + "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/d3b50812dd51f3fbf176344cc2981db03d10fe06", - "reference": "d3b50812dd51f3fbf176344cc2981db03d10fe06", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/a700b4656e4c54371b799ac61e300ab25a2d1d39", + "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39", "shasum": "" }, "require": { "ext-json": "*", "league/uri-interfaces": "^2.3", - "php": "^7.4 || ^8.0", - "psr/http-message": "^1.0" + "php": "^8.1", + "psr/http-message": "^1.0.1" }, "conflict": { "league/uri-schemes": "^1.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^v3.3.2", - "nyholm/psr7": "^1.5", - "php-http/psr7-integration-tests": "^1.1", - "phpstan/phpstan": "^1.2.0", + "friendsofphp/php-cs-fixer": "^v3.9.5", + "nyholm/psr7": "^1.5.1", + "php-http/psr7-integration-tests": "^1.1.1", + "phpbench/phpbench": "^1.2.6", + "phpstan/phpstan": "^1.8.5", "phpstan/phpstan-deprecation-rules": "^1.0", - "phpstan/phpstan-phpunit": "^1.0.0", - "phpstan/phpstan-strict-rules": "^1.1.0", - "phpunit/phpunit": "^9.5.10", - "psr/http-factory": "^1.0" + "phpstan/phpstan-phpunit": "^1.1.1", + "phpstan/phpstan-strict-rules": "^1.4.3", + "phpunit/phpunit": "^9.5.24", + "psr/http-factory": "^1.0.1" }, "suggest": { "ext-fileinfo": "Needed to create Data URI from a filepath", @@ -3232,7 +3295,7 @@ "docs": "https://uri.thephpleague.com", "forum": "https://thephpleague.slack.com", "issues": "https://github.com/thephpleague/uri/issues", - "source": "https://github.com/thephpleague/uri/tree/6.7.2" + "source": "https://github.com/thephpleague/uri/tree/6.8.0" }, "funding": [ { @@ -3240,7 +3303,7 @@ "type": "github" } ], - "time": "2022-09-13T19:50:42+00:00" + "time": "2022-09-13T19:58:47+00:00" }, { "name": "league/uri-interfaces", @@ -3417,16 +3480,16 @@ }, { "name": "nesbot/carbon", - "version": "2.64.1", + "version": "2.65.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "f2e59963f4c4f4fdfb9fcfd752e8d2e2b79a4e2c" + "reference": "09acf64155c16dc6f580f36569ae89344e9734a3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/f2e59963f4c4f4fdfb9fcfd752e8d2e2b79a4e2c", - "reference": "f2e59963f4c4f4fdfb9fcfd752e8d2e2b79a4e2c", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/09acf64155c16dc6f580f36569ae89344e9734a3", + "reference": "09acf64155c16dc6f580f36569ae89344e9734a3", "shasum": "" }, "require": { @@ -3515,7 +3578,7 @@ "type": "tidelift" } ], - "time": "2023-01-01T23:17:36+00:00" + "time": "2023-01-06T15:55:01+00:00" }, { "name": "nette/schema", @@ -3666,16 +3729,16 @@ }, { "name": "nunomaduro/collision", - "version": "v6.3.2", + "version": "v6.4.0", "source": { "type": "git", "url": "https://github.com/nunomaduro/collision.git", - "reference": "83699b231e7f277bfa2e823788973bf4082f019a" + "reference": "f05978827b9343cba381ca05b8c7deee346b6015" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nunomaduro/collision/zipball/83699b231e7f277bfa2e823788973bf4082f019a", - "reference": "83699b231e7f277bfa2e823788973bf4082f019a", + "url": "https://api.github.com/repos/nunomaduro/collision/zipball/f05978827b9343cba381ca05b8c7deee346b6015", + "reference": "f05978827b9343cba381ca05b8c7deee346b6015", "shasum": "" }, "require": { @@ -3750,7 +3813,7 @@ "type": "patreon" } ], - "time": "2022-12-23T21:36:49+00:00" + "time": "2023-01-03T12:54:54+00:00" }, { "name": "nunomaduro/termwind", @@ -5030,21 +5093,20 @@ }, { "name": "ramsey/collection", - "version": "1.3.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/ramsey/collection.git", - "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4" + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/collection/zipball/ad7475d1c9e70b190ecffc58f2d989416af339b4", - "reference": "ad7475d1c9e70b190ecffc58f2d989416af339b4", + "url": "https://api.github.com/repos/ramsey/collection/zipball/a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", + "reference": "a4b48764bfbb8f3a6a4d1aeb1a35bb5e9ecac4a5", "shasum": "" }, "require": { - "php": "^7.4 || ^8.0", - "symfony/polyfill-php81": "^1.23" + "php": "^8.1" }, "require-dev": { "captainhook/plugin-composer": "^5.3", @@ -5104,7 +5166,7 @@ ], "support": { "issues": "https://github.com/ramsey/collection/issues", - "source": "https://github.com/ramsey/collection/tree/1.3.0" + "source": "https://github.com/ramsey/collection/tree/2.0.0" }, "funding": [ { @@ -5116,7 +5178,7 @@ "type": "tidelift" } ], - "time": "2022-12-27T19:12:24+00:00" + "time": "2022-12-31T21:50:55+00:00" }, { "name": "ramsey/uuid", @@ -5558,16 +5620,16 @@ }, { "name": "spatie/laravel-ignition", - "version": "1.6.3", + "version": "1.6.4", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "2db918babd96f87b73fc26e4195f5a19328dd123" + "reference": "1a2b4bd3d48c72526c0ba417687e5c56b5cf49bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/2db918babd96f87b73fc26e4195f5a19328dd123", - "reference": "2db918babd96f87b73fc26e4195f5a19328dd123", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/1a2b4bd3d48c72526c0ba417687e5c56b5cf49bc", + "reference": "1a2b4bd3d48c72526c0ba417687e5c56b5cf49bc", "shasum": "" }, "require": { @@ -5644,71 +5706,25 @@ "type": "github" } ], - "time": "2022-12-26T15:13:03+00:00" - }, - { - "name": "stella-maris/clock", - "version": "0.1.7", - "source": { - "type": "git", - "url": "https://github.com/stella-maris-solutions/clock.git", - "reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/stella-maris-solutions/clock/zipball/fa23ce16019289a18bb3446fdecd45befcdd94f8", - "reference": "fa23ce16019289a18bb3446fdecd45befcdd94f8", - "shasum": "" - }, - "require": { - "php": "^7.0|^8.0", - "psr/clock": "^1.0" - }, - "type": "library", - "autoload": { - "psr-4": { - "StellaMaris\\Clock\\": "src" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Andreas Heigl", - "role": "Maintainer" - } - ], - "description": "A pre-release of the proposed PSR-20 Clock-Interface", - "homepage": "https://gitlab.com/stella-maris/clock", - "keywords": [ - "clock", - "datetime", - "point in time", - "psr20" - ], - "support": { - "source": "https://github.com/stella-maris-solutions/clock/tree/0.1.7" - }, - "time": "2022-11-25T16:15:06+00:00" + "time": "2023-01-03T19:28:04+00:00" }, { "name": "symfony/console", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "2ab307342a7233b9a260edd5ef94087aaca57d18" + "reference": "0f579613e771dba2dbb8211c382342a641f5da06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/2ab307342a7233b9a260edd5ef94087aaca57d18", - "reference": "2ab307342a7233b9a260edd5ef94087aaca57d18", + "url": "https://api.github.com/repos/symfony/console/zipball/0f579613e771dba2dbb8211c382342a641f5da06", + "reference": "0f579613e771dba2dbb8211c382342a641f5da06", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^1.1|^2|^3", "symfony/string": "^5.4|^6.0" @@ -5770,7 +5786,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.17" + "source": "https://github.com/symfony/console/tree/v6.2.3" }, "funding": [ { @@ -5786,24 +5802,24 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:21:34+00:00" + "time": "2022-12-28T14:26:22+00:00" }, { "name": "symfony/css-selector", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "3e526b732295b5d4c16c38d557b74ba8498a92b4" + "reference": "ab1df4ba3ded7b724766ba3a6e0eca0418e74f80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/3e526b732295b5d4c16c38d557b74ba8498a92b4", - "reference": "3e526b732295b5d4c16c38d557b74ba8498a92b4", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/ab1df4ba3ded7b724766ba3a6e0eca0418e74f80", + "reference": "ab1df4ba3ded7b724766ba3a6e0eca0418e74f80", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -5835,7 +5851,7 @@ "description": "Converts CSS selectors to XPath expressions", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v6.0.17" + "source": "https://github.com/symfony/css-selector/tree/v6.2.3" }, "funding": [ { @@ -5851,29 +5867,29 @@ "type": "tidelift" } ], - "time": "2022-12-28T14:21:34+00:00" + "time": "2022-12-28T14:26:22+00:00" }, { "name": "symfony/deprecation-contracts", - "version": "v3.0.2", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c" + "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", - "reference": "26954b3d62a6c5fd0ea8a2a00c0353a14978d05c", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3", + "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -5902,7 +5918,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0" }, "funding": [ { @@ -5918,24 +5934,24 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/error-handler", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "1113c4bcf3bc77a9c79562543317479c90ba7b82" + "reference": "0926124c95d220499e2baf0fb465772af3a4eddb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/1113c4bcf3bc77a9c79562543317479c90ba7b82", - "reference": "1113c4bcf3bc77a9c79562543317479c90ba7b82", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/0926124c95d220499e2baf0fb465772af3a4eddb", + "reference": "0926124c95d220499e2baf0fb465772af3a4eddb", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", "symfony/var-dumper": "^5.4|^6.0" }, @@ -5973,7 +5989,7 @@ "description": "Provides tools to manage errors and ease debugging PHP code", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v6.0.17" + "source": "https://github.com/symfony/error-handler/tree/v6.2.3" }, "funding": [ { @@ -5989,24 +6005,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-19T14:33:49+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "42b3985aa07837c9df36013ec5b965e9f2d480bc" + "reference": "3ffeb31139b49bf6ef0bc09d1db95eac053388d1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/42b3985aa07837c9df36013ec5b965e9f2d480bc", - "reference": "42b3985aa07837c9df36013ec5b965e9f2d480bc", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/3ffeb31139b49bf6ef0bc09d1db95eac053388d1", + "reference": "3ffeb31139b49bf6ef0bc09d1db95eac053388d1", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/event-dispatcher-contracts": "^2|^3" }, "conflict": { @@ -6056,7 +6072,7 @@ "description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v6.0.17" + "source": "https://github.com/symfony/event-dispatcher/tree/v6.2.2" }, "funding": [ { @@ -6072,24 +6088,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/event-dispatcher-contracts", - "version": "v3.0.2", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051" + "reference": "0782b0b52a737a05b4383d0df35a474303cabdae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/7bc61cc2db649b4637d331240c5346dcc7708051", - "reference": "7bc61cc2db649b4637d331240c5346dcc7708051", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/0782b0b52a737a05b4383d0df35a474303cabdae", + "reference": "0782b0b52a737a05b4383d0df35a474303cabdae", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1" }, "suggest": { @@ -6098,7 +6114,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -6135,7 +6151,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.2.0" }, "funding": [ { @@ -6151,24 +6167,27 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:55:41+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/finder", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d467d625fc88f7cebf96f495e588a7196a669db1" + "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d467d625fc88f7cebf96f495e588a7196a669db1", - "reference": "d467d625fc88f7cebf96f495e588a7196a669db1", + "url": "https://api.github.com/repos/symfony/finder/zipball/81eefbddfde282ee33b437ba5e13d7753211ae8e", + "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" }, "type": "library", "autoload": { @@ -6196,7 +6215,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v6.0.17" + "source": "https://github.com/symfony/finder/tree/v6.2.3" }, "funding": [ { @@ -6212,25 +6231,26 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:53:58+00:00" + "time": "2022-12-22T17:55:15+00:00" }, { "name": "symfony/http-client", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "d104286d135d29a17ead777888087e7f0fd11771" + "reference": "7054ad466f836309aef511789b9c697bc986d8ce" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/d104286d135d29a17ead777888087e7f0fd11771", - "reference": "d104286d135d29a17ead777888087e7f0fd11771", + "url": "https://api.github.com/repos/symfony/http-client/zipball/7054ad466f836309aef511789b9c697bc986d8ce", + "reference": "7054ad466f836309aef511789b9c697bc986d8ce", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", + "symfony/deprecation-contracts": "^2.1|^3", "symfony/http-client-contracts": "^3", "symfony/service-contracts": "^1.0|^2|^3" }, @@ -6280,7 +6300,7 @@ "description": "Provides powerful methods to fetch HTTP resources synchronously or asynchronously", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-client/tree/v6.0.17" + "source": "https://github.com/symfony/http-client/tree/v6.2.2" }, "funding": [ { @@ -6296,24 +6316,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/http-client-contracts", - "version": "v3.0.2", + "version": "v3.1.1", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "4184b9b63af1edaf35b6a7974c6f1f9f33294129" + "reference": "fd038f08c623ab5d22b26e9ba35afe8c79071800" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/4184b9b63af1edaf35b6a7974c6f1f9f33294129", - "reference": "4184b9b63af1edaf35b6a7974c6f1f9f33294129", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/fd038f08c623ab5d22b26e9ba35afe8c79071800", + "reference": "fd038f08c623ab5d22b26e9ba35afe8c79071800", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "suggest": { "symfony/http-client-implementation": "" @@ -6321,7 +6341,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.1-dev" }, "thanks": { "name": "symfony/contracts", @@ -6331,7 +6351,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\HttpClient\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -6358,7 +6381,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.1.1" }, "funding": [ { @@ -6374,27 +6397,30 @@ "type": "tidelift" } ], - "time": "2022-04-12T16:11:42+00:00" + "time": "2022-04-22T07:30:54+00:00" }, { "name": "symfony/http-foundation", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "22fe17e40b0481d39212e7165e004eb26422085d" + "reference": "ddf4dd35de1623e7c02013523e6c2137b67b636f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/22fe17e40b0481d39212e7165e004eb26422085d", - "reference": "22fe17e40b0481d39212e7165e004eb26422085d", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/ddf4dd35de1623e7c02013523e6c2137b67b636f", + "reference": "ddf4dd35de1623e7c02013523e6c2137b67b636f", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/deprecation-contracts": "^2.1|^3", "symfony/polyfill-mbstring": "~1.1" }, + "conflict": { + "symfony/cache": "<6.2" + }, "require-dev": { "predis/predis": "~1.0", "symfony/cache": "^5.4|^6.0", @@ -6433,7 +6459,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v6.0.17" + "source": "https://github.com/symfony/http-foundation/tree/v6.2.2" }, "funding": [ { @@ -6449,26 +6475,27 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.0.18", + "version": "v6.2.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "71b52f9e5740b124894b454244fa0db48bb15814" + "reference": "74f2e638ec3fa0315443bd85fab7fc8066b77f83" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/71b52f9e5740b124894b454244fa0db48bb15814", - "reference": "71b52f9e5740b124894b454244fa0db48bb15814", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/74f2e638ec3fa0315443bd85fab7fc8066b77f83", + "reference": "74f2e638ec3fa0315443bd85fab7fc8066b77f83", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/log": "^1|^2|^3", - "symfony/error-handler": "^5.4|^6.0", + "symfony/deprecation-contracts": "^2.1|^3", + "symfony/error-handler": "^6.1", "symfony/event-dispatcher": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", "symfony/polyfill-ctype": "^1.8" @@ -6476,9 +6503,9 @@ "conflict": { "symfony/browser-kit": "<5.4", "symfony/cache": "<5.4", - "symfony/config": "<5.4", + "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<5.4", + "symfony/dependency-injection": "<6.2", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", @@ -6495,10 +6522,10 @@ "require-dev": { "psr/cache": "^1.0|^2.0|^3.0", "symfony/browser-kit": "^5.4|^6.0", - "symfony/config": "^5.4|^6.0", + "symfony/config": "^6.1", "symfony/console": "^5.4|^6.0", "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", + "symfony/dependency-injection": "^6.2", "symfony/dom-crawler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", @@ -6508,6 +6535,7 @@ "symfony/stopwatch": "^5.4|^6.0", "symfony/translation": "^5.4|^6.0", "symfony/translation-contracts": "^1.1|^2|^3", + "symfony/uid": "^5.4|^6.0", "twig/twig": "^2.13|^3.0.4" }, "suggest": { @@ -6542,7 +6570,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v6.0.18" + "source": "https://github.com/symfony/http-kernel/tree/v6.2.4" }, "funding": [ { @@ -6558,37 +6586,42 @@ "type": "tidelift" } ], - "time": "2022-12-29T18:58:12+00:00" + "time": "2022-12-29T19:05:08+00:00" }, { "name": "symfony/mailer", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/mailer.git", - "reference": "0d4562cd13f1e5b78b578120ae5cbd5527ec1534" + "reference": "b355ad81f1d2987c47dcd3b04d5dce669e1e62e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailer/zipball/0d4562cd13f1e5b78b578120ae5cbd5527ec1534", - "reference": "0d4562cd13f1e5b78b578120ae5cbd5527ec1534", + "url": "https://api.github.com/repos/symfony/mailer/zipball/b355ad81f1d2987c47dcd3b04d5dce669e1e62e6", + "reference": "b355ad81f1d2987c47dcd3b04d5dce669e1e62e6", "shasum": "" }, "require": { "egulias/email-validator": "^2.1.10|^3", - "php": ">=8.0.2", + "php": ">=8.1", "psr/event-dispatcher": "^1", "psr/log": "^1|^2|^3", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/mime": "^5.4|^6.0", + "symfony/mime": "^6.2", "symfony/service-contracts": "^1.1|^2|^3" }, "conflict": { - "symfony/http-kernel": "<5.4" + "symfony/http-kernel": "<5.4", + "symfony/messenger": "<6.2", + "symfony/mime": "<6.2", + "symfony/twig-bridge": "<6.2.1" }, "require-dev": { + "symfony/console": "^5.4|^6.0", "symfony/http-client-contracts": "^1.1|^2|^3", - "symfony/messenger": "^5.4|^6.0" + "symfony/messenger": "^6.2", + "symfony/twig-bridge": "^6.2" }, "type": "library", "autoload": { @@ -6616,7 +6649,7 @@ "description": "Helps sending emails", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailer/tree/v6.0.17" + "source": "https://github.com/symfony/mailer/tree/v6.2.2" }, "funding": [ { @@ -6632,24 +6665,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/mailgun-mailer", - "version": "v6.0.7", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/mailgun-mailer.git", - "reference": "f0d032c26683b26f4bc26864e09b1e08fa55226e" + "reference": "c5364fbcf5581ba9eae569db12b380b9255ce238" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/f0d032c26683b26f4bc26864e09b1e08fa55226e", - "reference": "f0d032c26683b26f4bc26864e09b1e08fa55226e", + "url": "https://api.github.com/repos/symfony/mailgun-mailer/zipball/c5364fbcf5581ba9eae569db12b380b9255ce238", + "reference": "c5364fbcf5581ba9eae569db12b380b9255ce238", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/mailer": "^5.4|^6.0" }, "require-dev": { @@ -6681,7 +6714,7 @@ "description": "Symfony Mailgun Mailer Bridge", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/mailgun-mailer/tree/v6.0.7" + "source": "https://github.com/symfony/mailgun-mailer/tree/v6.2.0" }, "funding": [ { @@ -6697,24 +6730,24 @@ "type": "tidelift" } ], - "time": "2022-03-24T17:11:42+00:00" + "time": "2022-10-09T08:55:40+00:00" }, { "name": "symfony/mime", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "3e6a7ba15997020778312ed576ad01ab60dc2336" + "reference": "8c98bf40406e791043890a163f6f6599b9cfa1ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/3e6a7ba15997020778312ed576ad01ab60dc2336", - "reference": "3e6a7ba15997020778312ed576ad01ab60dc2336", + "url": "https://api.github.com/repos/symfony/mime/zipball/8c98bf40406e791043890a163f6f6599b9cfa1ed", + "reference": "8c98bf40406e791043890a163f6f6599b9cfa1ed", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, @@ -6723,15 +6756,16 @@ "phpdocumentor/reflection-docblock": "<3.2.2", "phpdocumentor/type-resolver": "<1.4.0", "symfony/mailer": "<5.4", - "symfony/serializer": "<5.4.14|>=6.0,<6.0.14|>=6.1,<6.1.6" + "symfony/serializer": "<6.2" }, "require-dev": { "egulias/email-validator": "^2.1.10|^3.1", + "league/html-to-markdown": "^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "symfony/dependency-injection": "^5.4|^6.0", "symfony/property-access": "^5.4|^6.0", "symfony/property-info": "^5.4|^6.0", - "symfony/serializer": "^5.4.14|~6.0.14|^6.1.6" + "symfony/serializer": "^6.2" }, "type": "library", "autoload": { @@ -6763,7 +6797,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v6.0.17" + "source": "https://github.com/symfony/mime/tree/v6.2.2" }, "funding": [ { @@ -6779,7 +6813,7 @@ "type": "tidelift" } ], - "time": "2022-12-14T16:19:02+00:00" + "time": "2022-12-14T16:38:10+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7357,85 +7391,6 @@ ], "time": "2022-11-03T14:55:06+00:00" }, - { - "name": "symfony/polyfill-php81", - "version": "v1.27.0", - "source": { - "type": "git", - "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", - "shasum": "" - }, - "require": { - "php": ">=7.1" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "1.27-dev" - }, - "thanks": { - "name": "symfony/polyfill", - "url": "https://github.com/symfony/polyfill" - } - }, - "autoload": { - "files": [ - "bootstrap.php" - ], - "psr-4": { - "Symfony\\Polyfill\\Php81\\": "" - }, - "classmap": [ - "Resources/stubs" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ], - "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" - }, - "funding": [ - { - "url": "https://symfony.com/sponsor", - "type": "custom" - }, - { - "url": "https://github.com/fabpot", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", - "type": "tidelift" - } - ], - "time": "2022-11-03T14:55:06+00:00" - }, { "name": "symfony/polyfill-uuid", "version": "v1.27.0", @@ -7520,20 +7475,20 @@ }, { "name": "symfony/process", - "version": "v6.0.11", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "44270a08ccb664143dede554ff1c00aaa2247a43" + "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/44270a08ccb664143dede554ff1c00aaa2247a43", - "reference": "44270a08ccb664143dede554ff1c00aaa2247a43", + "url": "https://api.github.com/repos/symfony/process/zipball/ba6e55359f8f755fe996c58a81e00eaa67a35877", + "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "type": "library", "autoload": { @@ -7561,7 +7516,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.0.11" + "source": "https://github.com/symfony/process/tree/v6.2.0" }, "funding": [ { @@ -7577,7 +7532,7 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2022-11-02T09:08:04+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -7669,31 +7624,31 @@ }, { "name": "symfony/routing", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "61687a0aa80f6807c52e116ee64072f6ec53780c" + "reference": "35fec764f3e2c8c08fb340d275c84bc78ca7e0c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/61687a0aa80f6807c52e116ee64072f6ec53780c", - "reference": "61687a0aa80f6807c52e116ee64072f6ec53780c", + "url": "https://api.github.com/repos/symfony/routing/zipball/35fec764f3e2c8c08fb340d275c84bc78ca7e0c9", + "reference": "35fec764f3e2c8c08fb340d275c84bc78ca7e0c9", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "conflict": { "doctrine/annotations": "<1.12", - "symfony/config": "<5.4", + "symfony/config": "<6.2", "symfony/dependency-injection": "<5.4", "symfony/yaml": "<5.4" }, "require-dev": { "doctrine/annotations": "^1.12|^2", "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", + "symfony/config": "^6.2", "symfony/dependency-injection": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/http-foundation": "^5.4|^6.0", @@ -7737,7 +7692,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v6.0.17" + "source": "https://github.com/symfony/routing/tree/v6.2.3" }, "funding": [ { @@ -7753,24 +7708,24 @@ "type": "tidelift" } ], - "time": "2022-12-20T16:40:04+00:00" + "time": "2022-12-20T16:41:15+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.0.2", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" + "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/aac98028c69df04ee77eb69b96b86ee51fbf4b75", + "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "psr/container": "^2.0" }, "conflict": { @@ -7782,7 +7737,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -7792,7 +7747,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7819,7 +7777,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.2.0" }, "funding": [ { @@ -7835,24 +7793,24 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:58+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/string", - "version": "v6.0.17", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "3f57003dd8a67ed76870cc03092f8501db7788d9" + "reference": "863219fd713fa41cbcd285a79723f94672faff4d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/3f57003dd8a67ed76870cc03092f8501db7788d9", - "reference": "3f57003dd8a67ed76870cc03092f8501db7788d9", + "url": "https://api.github.com/repos/symfony/string/zipball/863219fd713fa41cbcd285a79723f94672faff4d", + "reference": "863219fd713fa41cbcd285a79723f94672faff4d", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", @@ -7864,6 +7822,7 @@ "require-dev": { "symfony/error-handler": "^5.4|^6.0", "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", "symfony/translation-contracts": "^2.0|^3.0", "symfony/var-exporter": "^5.4|^6.0" }, @@ -7904,7 +7863,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.17" + "source": "https://github.com/symfony/string/tree/v6.2.2" }, "funding": [ { @@ -7920,24 +7879,24 @@ "type": "tidelift" } ], - "time": "2022-12-14T15:52:41+00:00" + "time": "2022-12-14T16:11:27+00:00" }, { "name": "symfony/translation", - "version": "v6.0.14", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "6f99eb179aee4652c0a7cd7c11f2a870d904330c" + "reference": "a2a15404ef4c15d92c205718eb828b225a144379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/6f99eb179aee4652c0a7cd7c11f2a870d904330c", - "reference": "6f99eb179aee4652c0a7cd7c11f2a870d904330c", + "url": "https://api.github.com/repos/symfony/translation/zipball/a2a15404ef4c15d92c205718eb828b225a144379", + "reference": "a2a15404ef4c15d92c205718eb828b225a144379", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0", "symfony/translation-contracts": "^2.3|^3.0" }, @@ -7953,6 +7912,7 @@ "symfony/translation-implementation": "2.3|3.0" }, "require-dev": { + "nikic/php-parser": "^4.13", "psr/log": "^1|^2|^3", "symfony/config": "^5.4|^6.0", "symfony/console": "^5.4|^6.0", @@ -7962,10 +7922,12 @@ "symfony/http-kernel": "^5.4|^6.0", "symfony/intl": "^5.4|^6.0", "symfony/polyfill-intl-icu": "^1.21", + "symfony/routing": "^5.4|^6.0", "symfony/service-contracts": "^1.1.2|^2|^3", "symfony/yaml": "^5.4|^6.0" }, "suggest": { + "nikic/php-parser": "To use PhpAstExtractor", "psr/log-implementation": "To use logging capability in translator", "symfony/config": "", "symfony/yaml": "" @@ -7999,7 +7961,7 @@ "description": "Provides tools to internationalize your application", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v6.0.14" + "source": "https://github.com/symfony/translation/tree/v6.2.3" }, "funding": [ { @@ -8015,24 +7977,24 @@ "type": "tidelift" } ], - "time": "2022-10-07T08:02:12+00:00" + "time": "2022-12-23T14:11:11+00:00" }, { "name": "symfony/translation-contracts", - "version": "v3.0.2", + "version": "v3.2.0", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282" + "reference": "68cce71402305a015f8c1589bfada1280dc64fe7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/acbfbb274e730e5a0236f619b6168d9dedb3e282", - "reference": "acbfbb274e730e5a0236f619b6168d9dedb3e282", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/68cce71402305a015f8c1589bfada1280dc64fe7", + "reference": "68cce71402305a015f8c1589bfada1280dc64fe7", "shasum": "" }, "require": { - "php": ">=8.0.2" + "php": ">=8.1" }, "suggest": { "symfony/translation-implementation": "" @@ -8040,7 +8002,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.3-dev" }, "thanks": { "name": "symfony/contracts", @@ -8050,7 +8012,10 @@ "autoload": { "psr-4": { "Symfony\\Contracts\\Translation\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -8077,7 +8042,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/translation-contracts/tree/v3.2.0" }, "funding": [ { @@ -8093,24 +8058,24 @@ "type": "tidelift" } ], - "time": "2022-06-27T17:10:44+00:00" + "time": "2022-11-25T10:21:52+00:00" }, { "name": "symfony/uid", - "version": "v6.0.13", + "version": "v6.2.0", "source": { "type": "git", "url": "https://github.com/symfony/uid.git", - "reference": "db426b27173f5e2d8b960dd10fa8ce19ea9ca5f3" + "reference": "4f9f537e57261519808a7ce1d941490736522bbc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/uid/zipball/db426b27173f5e2d8b960dd10fa8ce19ea9ca5f3", - "reference": "db426b27173f5e2d8b960dd10fa8ce19ea9ca5f3", + "url": "https://api.github.com/repos/symfony/uid/zipball/4f9f537e57261519808a7ce1d941490736522bbc", + "reference": "4f9f537e57261519808a7ce1d941490736522bbc", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-uuid": "^1.15" }, "require-dev": { @@ -8151,7 +8116,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/uid/tree/v6.0.13" + "source": "https://github.com/symfony/uid/tree/v6.2.0" }, "funding": [ { @@ -8167,24 +8132,24 @@ "type": "tidelift" } ], - "time": "2022-09-09T09:33:56+00:00" + "time": "2022-10-09T08:55:40+00:00" }, { "name": "symfony/var-dumper", - "version": "v6.0.17", + "version": "v6.2.3", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "7d8e7c3c67c77790425ebe33691419dada154e65" + "reference": "fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/7d8e7c3c67c77790425ebe33691419dada154e65", - "reference": "7d8e7c3c67c77790425ebe33691419dada154e65", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0", + "reference": "fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { @@ -8239,7 +8204,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.0.17" + "source": "https://github.com/symfony/var-dumper/tree/v6.2.3" }, "funding": [ { @@ -8255,20 +8220,20 @@ "type": "tidelift" } ], - "time": "2022-12-22T17:53:58+00:00" + "time": "2022-12-22T17:55:15+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", - "version": "2.2.5", + "version": "2.2.6", "source": { "type": "git", "url": "https://github.com/tijsverkoyen/CssToInlineStyles.git", - "reference": "4348a3a06651827a27d989ad1d13efec6bb49b19" + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/4348a3a06651827a27d989ad1d13efec6bb49b19", - "reference": "4348a3a06651827a27d989ad1d13efec6bb49b19", + "url": "https://api.github.com/repos/tijsverkoyen/CssToInlineStyles/zipball/c42125b83a4fa63b187fdf29f9c93cb7733da30c", + "reference": "c42125b83a4fa63b187fdf29f9c93cb7733da30c", "shasum": "" }, "require": { @@ -8306,9 +8271,9 @@ "homepage": "https://github.com/tijsverkoyen/CssToInlineStyles", "support": { "issues": "https://github.com/tijsverkoyen/CssToInlineStyles/issues", - "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.5" + "source": "https://github.com/tijsverkoyen/CssToInlineStyles/tree/2.2.6" }, - "time": "2022-09-12T13:28:28+00:00" + "time": "2023-01-03T09:29:04+00:00" }, { "name": "twig/twig", @@ -8891,6 +8856,84 @@ ], "time": "2022-12-30T00:15:36+00:00" }, + { + "name": "ergebnis/phpstan-rules", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/ergebnis/phpstan-rules.git", + "reference": "ebeced30d7e50324a94a83c19a59d75816e8fbb4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/ebeced30d7e50324a94a83c19a59d75816e8fbb4", + "reference": "ebeced30d7e50324a94a83c19a59d75816e8fbb4", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "nikic/php-parser": "^4.2.3", + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.0.0" + }, + "require-dev": { + "doctrine/orm": "^2.10.2", + "ergebnis/composer-normalize": "^2.15.0", + "ergebnis/license": "^1.1.0", + "ergebnis/php-cs-fixer-config": "^2.14.0", + "ergebnis/test-util": "^1.5.0", + "infection/infection": "~0.15.3", + "nette/di": "^3.0.11", + "phpstan/phpstan-deprecation-rules": "^1.0.0", + "phpstan/phpstan-strict-rules": "^1.0.0", + "phpunit/phpunit": "^8.5.21", + "psalm/plugin-phpunit": "~0.16.1", + "psr/container": "^1.0.0", + "vimeo/psalm": "^4.12.0", + "zendframework/zend-servicemanager": "^2.0.0" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "Ergebnis\\PHPStan\\Rules\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andreas Möller", + "email": "am@localheinz.com" + } + ], + "description": "Provides additional rules for phpstan/phpstan.", + "homepage": "https://github.com/ergebnis/phpstan-rules", + "keywords": [ + "PHPStan", + "phpstan-extreme-rules", + "phpstan-rules" + ], + "support": { + "issues": "https://github.com/ergebnis/phpstan-rules/issues", + "source": "https://github.com/ergebnis/phpstan-rules" + }, + "funding": [ + { + "url": "https://github.com/localheinz", + "type": "github" + } + ], + "time": "2021-11-08T15:37:09+00:00" + }, { "name": "fakerphp/faker", "version": "v1.21.0", @@ -9197,6 +9240,103 @@ }, "time": "2022-11-12T15:38:23+00:00" }, + { + "name": "nunomaduro/larastan", + "version": "2.3.4", + "source": { + "type": "git", + "url": "https://github.com/nunomaduro/larastan.git", + "reference": "32ad25904dc8fbfdae4d4e431a27ba3bad2979cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nunomaduro/larastan/zipball/32ad25904dc8fbfdae4d4e431a27ba3bad2979cc", + "reference": "32ad25904dc8fbfdae4d4e431a27ba3bad2979cc", + "shasum": "" + }, + "require": { + "ext-json": "*", + "illuminate/console": "^9", + "illuminate/container": "^9", + "illuminate/contracts": "^9", + "illuminate/database": "^9", + "illuminate/http": "^9", + "illuminate/pipeline": "^9", + "illuminate/support": "^9", + "mockery/mockery": "^1.4.4", + "php": "^8.0.2", + "phpmyadmin/sql-parser": "^5.5", + "phpstan/phpstan": "^1.9.4" + }, + "require-dev": { + "nikic/php-parser": "^4.13.2", + "orchestra/testbench": "^7.0.0", + "phpunit/phpunit": "^9.5.11" + }, + "suggest": { + "orchestra/testbench": "Using Larastan for analysing a package needs Testbench" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "2.0-dev" + }, + "phpstan": { + "includes": [ + "extension.neon" + ] + } + }, + "autoload": { + "psr-4": { + "NunoMaduro\\Larastan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nuno Maduro", + "email": "enunomaduro@gmail.com" + } + ], + "description": "Larastan - Discover bugs in your code without running it. A phpstan/phpstan wrapper for Laravel", + "keywords": [ + "PHPStan", + "code analyse", + "code analysis", + "larastan", + "laravel", + "package", + "php", + "static analysis" + ], + "support": { + "issues": "https://github.com/nunomaduro/larastan/issues", + "source": "https://github.com/nunomaduro/larastan/tree/2.3.4" + }, + "funding": [ + { + "url": "https://www.paypal.com/paypalme/enunomaduro", + "type": "custom" + }, + { + "url": "https://github.com/canvural", + "type": "github" + }, + { + "url": "https://github.com/nunomaduro", + "type": "github" + }, + { + "url": "https://www.patreon.com/nunomaduro", + "type": "patreon" + } + ], + "time": "2023-01-02T12:13:26+00:00" + }, { "name": "phar-io/manifest", "version": "2.0.3", @@ -9416,6 +9556,247 @@ }, "time": "2022-10-14T12:47:21+00:00" }, + { + "name": "phpmyadmin/sql-parser", + "version": "5.6.0", + "source": { + "type": "git", + "url": "https://github.com/phpmyadmin/sql-parser.git", + "reference": "63f2f77847586864a661ef009ae687dbdda0a9f1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmyadmin/sql-parser/zipball/63f2f77847586864a661ef009ae687dbdda0a9f1", + "reference": "63f2f77847586864a661ef009ae687dbdda0a9f1", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php80": "^1.16" + }, + "conflict": { + "phpmyadmin/motranslator": "<3.0" + }, + "require-dev": { + "phpmyadmin/coding-standard": "^3.0", + "phpmyadmin/motranslator": "^4.0 || ^5.0", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.2", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/php-code-coverage": "*", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "^0.16.1", + "vimeo/psalm": "^4.11", + "zumba/json-serializer": "^3.0" + }, + "suggest": { + "ext-mbstring": "For best performance", + "phpmyadmin/motranslator": "Translate messages to your favorite locale" + }, + "bin": [ + "bin/highlight-query", + "bin/lint-query", + "bin/tokenize-query" + ], + "type": "library", + "autoload": { + "psr-4": { + "PhpMyAdmin\\SqlParser\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-or-later" + ], + "authors": [ + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "description": "A validating SQL lexer and parser with a focus on MySQL dialect.", + "homepage": "https://github.com/phpmyadmin/sql-parser", + "keywords": [ + "analysis", + "lexer", + "parser", + "query linter", + "sql", + "sql lexer", + "sql linter", + "sql parser", + "sql syntax highlighter", + "sql tokenizer" + ], + "support": { + "issues": "https://github.com/phpmyadmin/sql-parser/issues", + "source": "https://github.com/phpmyadmin/sql-parser" + }, + "funding": [ + { + "url": "https://www.phpmyadmin.net/donate/", + "type": "other" + } + ], + "time": "2023-01-02T05:36:07+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "1.9.7", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "0501435cd342eac7664bd62155b1ef907fc60b6f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/0501435cd342eac7664bd62155b1ef907fc60b6f", + "reference": "0501435cd342eac7664bd62155b1ef907fc60b6f", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.9.7" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2023-01-04T21:59:57+00:00" + }, + { + "name": "phpstan/phpstan-deprecation-rules", + "version": "1.1.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-deprecation-rules.git", + "reference": "2c6792eda026d9c474c14aa018aed312686714db" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/2c6792eda026d9c474c14aa018aed312686714db", + "reference": "2c6792eda026d9c474c14aa018aed312686714db", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.9.3" + }, + "require-dev": { + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-php-parser": "^1.1", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.", + "support": { + "issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues", + "source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/1.1.1" + }, + "time": "2022-12-13T14:26:20+00:00" + }, + { + "name": "phpstan/phpstan-strict-rules", + "version": "1.4.4", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan-strict-rules.git", + "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", + "reference": "23e5f377ee6395a1a04842d3d6ed4bd25e7b44a6", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0", + "phpstan/phpstan": "^1.8.6" + }, + "require-dev": { + "nikic/php-parser": "^4.13.0", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^9.5" + }, + "type": "phpstan-extension", + "extra": { + "phpstan": { + "includes": [ + "rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Extra strict and opinionated rules for PHPStan", + "support": { + "issues": "https://github.com/phpstan/phpstan-strict-rules/issues", + "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.4.4" + }, + "time": "2022-09-21T11:38:17+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.23", @@ -10800,6 +11181,61 @@ ], "time": "2020-09-28T06:39:44+00:00" }, + { + "name": "thecodingmachine/phpstan-strict-rules", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/thecodingmachine/phpstan-strict-rules.git", + "reference": "2ba8fa8b328c45f3b149c05def5bf96793c594b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thecodingmachine/phpstan-strict-rules/zipball/2ba8fa8b328c45f3b149c05def5bf96793c594b6", + "reference": "2ba8fa8b328c45f3b149c05def5bf96793c594b6", + "shasum": "" + }, + "require": { + "php": "^7.1|^8.0", + "phpstan/phpstan": "^1.0" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^7.1" + }, + "type": "phpstan-extension", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + }, + "phpstan": { + "includes": [ + "phpstan-strict-rules.neon" + ] + } + }, + "autoload": { + "psr-4": { + "TheCodingMachine\\PHPStan\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "David NĂ©grier", + "email": "d.negrier@thecodingmachine.com" + } + ], + "description": "A set of additional rules for PHPStan based on best practices followed at TheCodingMachine", + "support": { + "issues": "https://github.com/thecodingmachine/phpstan-strict-rules/issues", + "source": "https://github.com/thecodingmachine/phpstan-strict-rules/tree/v1.0.0" + }, + "time": "2021-11-08T09:10:49+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.1", @@ -10857,7 +11293,7 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": ">=8", + "php": ">=8.2", "ext-bcmath": "*", "ext-curl": "*", "ext-fileinfo": "*", @@ -10876,7 +11312,7 @@ }, "platform-dev": [], "platform-overrides": { - "php": "8.0.19" + "php": "8.2" }, "plugin-api-version": "2.3.0" } diff --git a/config/auth.php b/config/auth.php index 92fad546f9..c645307e39 100644 --- a/config/auth.php +++ b/config/auth.php @@ -21,7 +21,7 @@ declare(strict_types=1); -if ('ldap' === strtolower((string) env('AUTHENTICATION_GUARD'))) { +if ('ldap' === strtolower((string)env('AUTHENTICATION_GUARD'))) { die('LDAP is no longer supported by Firefly III v5.7+. Sorry about that. You will have to switch to "remote_user_guard", and use tools like Authelia or Keycloak to use LDAP together with Firefly III.'); } diff --git a/config/cache.php b/config/cache.php index 69ed690ca4..d28d9d6882 100644 --- a/config/cache.php +++ b/config/cache.php @@ -83,7 +83,7 @@ return [ 'servers' => [ [ 'host' => env('MEMCACHED_HOST', '127.0.0.1'), - 'port' => (int) env('MEMCACHED_PORT', 11211), + 'port' => (int)env('MEMCACHED_PORT', 11211), 'weight' => 100, ], ], diff --git a/config/cer.php b/config/cer.php new file mode 100644 index 0000000000..aff3718313 --- /dev/null +++ b/config/cer.php @@ -0,0 +1,73 @@ +. + */ + +declare(strict_types=1); + +return [ + + 'url' => 'https://ff3exchangerates.z6.web.core.windows.net', + 'enabled' => env('ENABLE_EXTERNAL_RATES', false), + // if currencies are added, default rates must be added as well! + // last exchange rate update: 6-6-2022 + // source: https://www.xe.com/currencyconverter/ + 'date' => '2022-06-06', + 'rates' => [ + // europa + ['EUR', 'HUF', 387.9629], + ['EUR', 'GBP', 0.85420754], + ['EUR', 'UAH', 31.659752], + ['EUR', 'PLN', 4.581788], + ['EUR', 'TRY', 17.801397], + ['EUR', 'DKK', 7.4389753], + + // Americas + ['EUR', 'USD', 1.0722281], + ['EUR', 'BRL', 5.0973173], + ['EUR', 'CAD', 1.3459969], + ['EUR', 'MXN', 20.899824], + + // Oceania currencies + ['EUR', 'IDR', 15466.299], + ['EUR', 'AUD', 1.4838549], + ['EUR', 'NZD', 1.6425829], + + // africa + ['EUR', 'EGP', 19.99735], + ['EUR', 'MAD', 10.573307], + ['EUR', 'ZAR', 16.413167], + + // asia + ['EUR', 'JPY', 140.15257], + ['EUR', 'RMB', 7.1194265], + ['EUR', 'RUB', 66.000895], + ['EUR', 'INR', 83.220481], + + // int + ['EUR', 'XBT', 0, 00003417], + ['EUR', 'BCH', 0.00573987], + ['EUR', 'ETH', 0, 00056204], + + ['EUR', 'ILS', 3.5712508], + ['EUR', 'CHF', 1.0323891], + ['EUR', 'HRK', 7.5220845], + ], +]; diff --git a/config/database.php b/config/database.php index da13fb0564..0ea963ea83 100644 --- a/config/database.php +++ b/config/database.php @@ -142,7 +142,7 @@ return [ 'client' => env('REDIS_CLIENT', 'predis'), 'options' => [ 'cluster' => env('REDIS_CLUSTER', 'predis'), - 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_') . '_database_'), + 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), ], 'default' => [ 'scheme' => envNonEmpty('REDIS_SCHEME', 'tcp'), diff --git a/config/filesystems.php b/config/filesystems.php index 8deff7ba8f..1af22469ae 100644 --- a/config/filesystems.php +++ b/config/filesystems.php @@ -88,7 +88,7 @@ return [ 'public' => [ 'driver' => 'local', 'root' => storage_path('app/public'), - 'url' => env('APP_URL') . '/storage', + 'url' => env('APP_URL').'/storage', 'visibility' => 'public', ], diff --git a/config/firefly.php b/config/firefly.php index d38be2908d..e02260a5f6 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -22,6 +22,7 @@ declare(strict_types=1); +use FireflyIII\Enums\TransactionTypeEnum; use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Attachment; @@ -60,7 +61,9 @@ use FireflyIII\Support\Binder\TagList; use FireflyIII\Support\Binder\TagOrId; use FireflyIII\TransactionRules\Actions\AddTag; use FireflyIII\TransactionRules\Actions\AppendDescription; +use FireflyIII\TransactionRules\Actions\AppendDescriptionToNotes; use FireflyIII\TransactionRules\Actions\AppendNotes; +use FireflyIII\TransactionRules\Actions\AppendNotesToDescription; use FireflyIII\TransactionRules\Actions\ClearBudget; use FireflyIII\TransactionRules\Actions\ClearCategory; use FireflyIII\TransactionRules\Actions\ClearNotes; @@ -69,6 +72,8 @@ use FireflyIII\TransactionRules\Actions\ConvertToTransfer; use FireflyIII\TransactionRules\Actions\ConvertToWithdrawal; use FireflyIII\TransactionRules\Actions\DeleteTransaction; use FireflyIII\TransactionRules\Actions\LinkToBill; +use FireflyIII\TransactionRules\Actions\MoveDescriptionToNotes; +use FireflyIII\TransactionRules\Actions\MoveNotesToDescription; use FireflyIII\TransactionRules\Actions\PrependDescription; use FireflyIII\TransactionRules\Actions\PrependNotes; use FireflyIII\TransactionRules\Actions\RemoveAllTags; @@ -98,12 +103,12 @@ return [ 'feature_flags' => [ 'export' => true, 'telemetry' => false, - 'webhooks' => false, + 'webhooks' => true, 'handle_debts' => true, ], - 'version' => '5.7.18', - 'api_version' => '1.5.6', - 'db_version' => 18, + 'version' => '5.8.0-alpha.1', + 'api_version' => '2.0.0-alpha.1', + 'db_version' => 19, // generic settings 'maxUploadSize' => 1073741824, // 1 GB @@ -142,11 +147,15 @@ return [ 'update_endpoint' => 'https://version.firefly-iii.org/index.json', 'update_minimum_age' => 7, + // notifications + 'available_notifications' => ['bill_reminder', 'new_access_token', 'transaction_creation', 'user_login'], + 'admin_notifications' => ['admin_new_reg', 'user_new_reg', 'new_version', 'invite_created', 'invite_redeemed'], + // enabled languages 'languages' => [ // currently enabled languages 'bg_BG' => ['name_locale' => 'БългарсĐșĐž', 'name_english' => 'Bulgarian'], -// 'ca_ES' => ['name_locale' => 'Catalan', 'name_english' => 'Catalan'], + // 'ca_ES' => ['name_locale' => 'Catalan', 'name_english' => 'Catalan'], 'cs_CZ' => ['name_locale' => 'Czech', 'name_english' => 'Czech'], 'da_DK' => ['name_locale' => 'Danish', 'name_english' => 'Danish'], 'de_DE' => ['name_locale' => 'Deutsch', 'name_english' => 'German'], @@ -154,17 +163,17 @@ return [ 'en_GB' => ['name_locale' => 'English (GB)', 'name_english' => 'English (GB)'], 'en_US' => ['name_locale' => 'English (US)', 'name_english' => 'English (US)'], 'es_ES' => ['name_locale' => 'Español', 'name_english' => 'Spanish'], -// 'et_EE' => ['name_locale' => 'Estonian', 'name_english' => 'Estonian'], -// 'fa_IR' => ['name_locale' => 'ÙŰ§Ű±ŰłÛŒ', 'name_english' => 'Persian'], + // 'et_EE' => ['name_locale' => 'Estonian', 'name_english' => 'Estonian'], + // 'fa_IR' => ['name_locale' => 'ÙŰ§Ű±ŰłÛŒ', 'name_english' => 'Persian'], 'fi_FI' => ['name_locale' => 'Suomi', 'name_english' => 'Finnish'], 'fr_FR' => ['name_locale' => 'Français', 'name_english' => 'French'], -// 'he_IL' => ['name_locale' => 'Hebrew', 'name_english' => 'Hebrew'], + // 'he_IL' => ['name_locale' => 'Hebrew', 'name_english' => 'Hebrew'], 'hu_HU' => ['name_locale' => 'Hungarian', 'name_english' => 'Hungarian'], 'id_ID' => ['name_locale' => 'Bahasa Indonesia', 'name_english' => 'Indonesian'], -// 'is_IS' => ['name_locale' => 'Icelandic', 'name_english' => 'Icelandic'], + // 'is_IS' => ['name_locale' => 'Icelandic', 'name_english' => 'Icelandic'], 'it_IT' => ['name_locale' => 'Italiano', 'name_english' => 'Italian'], 'ja_JP' => ['name_locale' => 'Japanese', 'name_english' => 'Japanese'], -// 'lt_LT' => ['name_locale' => 'LietuviĆł', 'name_english' => 'Lithuanian'], + // 'lt_LT' => ['name_locale' => 'LietuviĆł', 'name_english' => 'Lithuanian'], 'nb_NO' => ['name_locale' => 'Norsk', 'name_english' => 'Norwegian'], 'nl_NL' => ['name_locale' => 'Nederlands', 'name_english' => 'Dutch'], 'pl_PL' => ['name_locale' => 'Polski', 'name_english' => 'Polish'], @@ -172,12 +181,12 @@ return [ 'pt_PT' => ['name_locale' => 'PortuguĂȘs', 'name_english' => 'Portuguese'], 'ro_RO' => ['name_locale' => 'RomĂąnă', 'name_english' => 'Romanian'], 'ru_RU' => ['name_locale' => 'РуссĐșĐžĐč', 'name_english' => 'Russian'], -// 'si_LK' => ['name_locale' => 'සිංහග', 'name_english' => 'Sinhala (Sri Lanka)'], + // 'si_LK' => ['name_locale' => 'සිංහග', 'name_english' => 'Sinhala (Sri Lanka)'], 'sk_SK' => ['name_locale' => 'Slovenčina', 'name_english' => 'Slovak'], 'sl_SI' => ['name_locale' => 'Slovenian', 'name_english' => 'Slovenian'], -//// 'sr_CS' => ['name_locale' => 'Serbian (Latin)', 'name_english' => 'Serbian (Latin)'], + //// 'sr_CS' => ['name_locale' => 'Serbian (Latin)', 'name_english' => 'Serbian (Latin)'], 'sv_SE' => ['name_locale' => 'Svenska', 'name_english' => 'Swedish'], -// // 'tlh_AA' => ['name_locale' => 'tlhIngan Hol', 'name_english' => 'Klingon'], + // // 'tlh_AA' => ['name_locale' => 'tlhIngan Hol', 'name_english' => 'Klingon'], 'tr_TR' => ['name_locale' => 'TĂŒrkçe', 'name_english' => 'Turkish'], 'uk_UA' => ['name_locale' => 'Ukranian', 'name_english' => 'Ukranian'], 'vi_VN' => ['name_locale' => 'Tiáșżng Việt', 'name_english' => 'Vietnamese'], @@ -211,9 +220,14 @@ return [ // account types that may have or set a currency 'valid_currency_account_types' => [ - AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE, - AccountType::CASH, AccountType::INITIAL_BALANCE, AccountType::LIABILITY_CREDIT, - AccountType::RECONCILIATION + AccountType::ASSET, + AccountType::LOAN, + AccountType::DEBT, + AccountType::MORTGAGE, + AccountType::CASH, + AccountType::INITIAL_BALANCE, + AccountType::LIABILITY_CREDIT, + AccountType::RECONCILIATION, ], // "value must be in this list" values @@ -482,6 +496,10 @@ return [ 'convert_transfer' => ConvertToTransfer::class, 'update_piggy' => UpdatePiggybank::class, 'delete_transaction' => DeleteTransaction::class, + 'append_descr_to_notes' => AppendDescriptionToNotes::class, + 'append_notes_to_descr' => AppendNotesToDescription::class, + 'move_descr_to_notes' => MoveDescriptionToNotes::class, + 'move_notes_to_descr' => MoveNotesToDescription::class, ], 'context-rule-actions' => [ 'set_category', @@ -512,10 +530,15 @@ return [ 'expected_source_types' => [ 'source' => [ TransactionTypeModel::WITHDRAWAL => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], - TransactionTypeModel::DEPOSIT => [AccountType::REVENUE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + TransactionTypeEnum::DEPOSIT->value => [AccountType::REVENUE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], TransactionTypeModel::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], - TransactionTypeModel::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, - AccountType::MORTGAGE,], + TransactionTypeModel::OPENING_BALANCE => [ + AccountType::INITIAL_BALANCE, + AccountType::ASSET, + AccountType::LOAN, + AccountType::DEBT, + AccountType::MORTGAGE, + ], TransactionTypeModel::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET], TransactionTypeModel::LIABILITY_CREDIT => [AccountType::LIABILITY_CREDIT, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], // in case no transaction type is known yet, it could be anything. @@ -529,46 +552,111 @@ return [ ], ], 'destination' => [ - TransactionTypeModel::WITHDRAWAL => [AccountType::EXPENSE, AccountType::CASH, AccountType::LOAN, AccountType::DEBT, - AccountType::MORTGAGE,], - TransactionTypeModel::DEPOSIT => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], + TransactionTypeModel::WITHDRAWAL => [ + AccountType::EXPENSE, + AccountType::CASH, + AccountType::LOAN, + AccountType::DEBT, + AccountType::MORTGAGE, + ], + TransactionTypeEnum::DEPOSIT->value => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], TransactionTypeModel::TRANSFER => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], - TransactionTypeModel::OPENING_BALANCE => [AccountType::INITIAL_BALANCE, AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, - AccountType::MORTGAGE,], + TransactionTypeModel::OPENING_BALANCE => [ + AccountType::INITIAL_BALANCE, + AccountType::ASSET, + AccountType::LOAN, + AccountType::DEBT, + AccountType::MORTGAGE, + ], TransactionTypeModel::RECONCILIATION => [AccountType::RECONCILIATION, AccountType::ASSET], TransactionTypeModel::LIABILITY_CREDIT => [AccountType::LIABILITY_CREDIT, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], ], ], 'allowed_opposing_types' => [ 'source' => [ - AccountType::ASSET => [AccountType::ASSET, AccountType::CASH, AccountType::DEBT, AccountType::EXPENSE, AccountType::INITIAL_BALANCE, - AccountType::LOAN, AccountType::RECONCILIATION, AccountType::MORTGAGE], + AccountType::ASSET => [ + AccountType::ASSET, + AccountType::CASH, + AccountType::DEBT, + AccountType::EXPENSE, + AccountType::INITIAL_BALANCE, + AccountType::LOAN, + AccountType::RECONCILIATION, + AccountType::MORTGAGE, + ], AccountType::CASH => [AccountType::ASSET], - AccountType::DEBT => [AccountType::ASSET, AccountType::DEBT, AccountType::EXPENSE, AccountType::INITIAL_BALANCE, AccountType::LOAN, - AccountType::MORTGAGE, AccountType::LIABILITY_CREDIT], + AccountType::DEBT => [ + AccountType::ASSET, + AccountType::DEBT, + AccountType::EXPENSE, + AccountType::INITIAL_BALANCE, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::LIABILITY_CREDIT, + ], AccountType::EXPENSE => [], // is not allowed as a source. AccountType::INITIAL_BALANCE => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], - AccountType::LOAN => [AccountType::ASSET, AccountType::DEBT, AccountType::EXPENSE, AccountType::INITIAL_BALANCE, AccountType::LOAN, - AccountType::MORTGAGE, AccountType::LIABILITY_CREDIT], - AccountType::MORTGAGE => [AccountType::ASSET, AccountType::DEBT, AccountType::EXPENSE, AccountType::INITIAL_BALANCE, AccountType::LOAN, - AccountType::MORTGAGE, AccountType::LIABILITY_CREDIT], + AccountType::LOAN => [ + AccountType::ASSET, + AccountType::DEBT, + AccountType::EXPENSE, + AccountType::INITIAL_BALANCE, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::LIABILITY_CREDIT, + ], + AccountType::MORTGAGE => [ + AccountType::ASSET, + AccountType::DEBT, + AccountType::EXPENSE, + AccountType::INITIAL_BALANCE, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::LIABILITY_CREDIT, + ], AccountType::RECONCILIATION => [AccountType::ASSET], AccountType::REVENUE => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], AccountType::LIABILITY_CREDIT => [AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], ], 'destination' => [ - AccountType::ASSET => [AccountType::ASSET, AccountType::CASH, AccountType::DEBT, AccountType::INITIAL_BALANCE, AccountType::LOAN, - AccountType::MORTGAGE, AccountType::RECONCILIATION, AccountType::REVENUE,], + AccountType::ASSET => [ + AccountType::ASSET, + AccountType::CASH, + AccountType::DEBT, + AccountType::INITIAL_BALANCE, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::RECONCILIATION, + AccountType::REVENUE, + ], AccountType::CASH => [AccountType::ASSET], - AccountType::DEBT => [AccountType::ASSET, AccountType::DEBT, AccountType::INITIAL_BALANCE, AccountType::LOAN, AccountType::MORTGAGE, - AccountType::REVENUE,], + AccountType::DEBT => [ + AccountType::ASSET, + AccountType::DEBT, + AccountType::INITIAL_BALANCE, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::REVENUE, + ], AccountType::EXPENSE => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], AccountType::INITIAL_BALANCE => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE], - AccountType::LOAN => [AccountType::ASSET, AccountType::DEBT, AccountType::INITIAL_BALANCE, AccountType::LOAN, AccountType::MORTGAGE, - AccountType::REVENUE,], - AccountType::MORTGAGE => [AccountType::ASSET, AccountType::DEBT, AccountType::INITIAL_BALANCE, AccountType::LOAN, AccountType::MORTGAGE, - AccountType::REVENUE,], + AccountType::LOAN => [ + AccountType::ASSET, + AccountType::DEBT, + AccountType::INITIAL_BALANCE, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::REVENUE, + ], + AccountType::MORTGAGE => [ + AccountType::ASSET, + AccountType::DEBT, + AccountType::INITIAL_BALANCE, + AccountType::LOAN, + AccountType::MORTGAGE, + AccountType::REVENUE, + ], AccountType::RECONCILIATION => [AccountType::ASSET], AccountType::REVENUE => [], // is not allowed as a destination AccountType::LIABILITY_CREDIT => [],// is not allowed as a destination @@ -577,31 +665,66 @@ return [ // depending on the account type, return the allowed transaction types: 'allowed_transaction_types' => [ 'source' => [ - AccountType::ASSET => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::TRANSFER, TransactionTypeModel::OPENING_BALANCE, - TransactionTypeModel::RECONCILIATION,], + AccountType::ASSET => [ + TransactionTypeModel::WITHDRAWAL, + TransactionTypeModel::TRANSFER, + TransactionTypeModel::OPENING_BALANCE, + TransactionTypeModel::RECONCILIATION, + ], AccountType::EXPENSE => [], // is not allowed as a source. - AccountType::REVENUE => [TransactionTypeModel::DEPOSIT], - AccountType::LOAN => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER, - TransactionTypeModel::OPENING_BALANCE, TransactionTypeModel::LIABILITY_CREDIT], - AccountType::DEBT => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER, - TransactionTypeModel::OPENING_BALANCE, TransactionTypeModel::LIABILITY_CREDIT], - AccountType::MORTGAGE => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER, - TransactionTypeModel::OPENING_BALANCE, TransactionTypeModel::LIABILITY_CREDIT], + AccountType::REVENUE => [TransactionTypeEnum::DEPOSIT->value], + AccountType::LOAN => [ + TransactionTypeModel::WITHDRAWAL, + TransactionTypeEnum::DEPOSIT->value, + TransactionTypeModel::TRANSFER, + TransactionTypeModel::OPENING_BALANCE, + TransactionTypeModel::LIABILITY_CREDIT, + ], + AccountType::DEBT => [ + TransactionTypeModel::WITHDRAWAL, + TransactionTypeEnum::DEPOSIT->value, + TransactionTypeModel::TRANSFER, + TransactionTypeModel::OPENING_BALANCE, + TransactionTypeModel::LIABILITY_CREDIT, + ], + AccountType::MORTGAGE => [ + TransactionTypeModel::WITHDRAWAL, + TransactionTypeEnum::DEPOSIT->value, + TransactionTypeModel::TRANSFER, + TransactionTypeModel::OPENING_BALANCE, + TransactionTypeModel::LIABILITY_CREDIT, + ], AccountType::INITIAL_BALANCE => [TransactionTypeModel::OPENING_BALANCE], AccountType::RECONCILIATION => [TransactionTypeModel::RECONCILIATION], AccountType::LIABILITY_CREDIT => [TransactionTypeModel::LIABILITY_CREDIT], ], 'destination' => [ - AccountType::ASSET => [TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER, TransactionTypeModel::OPENING_BALANCE, - TransactionTypeModel::RECONCILIATION,], + AccountType::ASSET => [ + TransactionTypeEnum::DEPOSIT->value, + TransactionTypeModel::TRANSFER, + TransactionTypeModel::OPENING_BALANCE, + TransactionTypeModel::RECONCILIATION, + ], AccountType::EXPENSE => [TransactionTypeModel::WITHDRAWAL], AccountType::REVENUE => [], // is not allowed as destination. - AccountType::LOAN => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER, - TransactionTypeModel::OPENING_BALANCE,], - AccountType::DEBT => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER, - TransactionTypeModel::OPENING_BALANCE,], - AccountType::MORTGAGE => [TransactionTypeModel::WITHDRAWAL, TransactionTypeModel::DEPOSIT, TransactionTypeModel::TRANSFER, - TransactionTypeModel::OPENING_BALANCE,], + AccountType::LOAN => [ + TransactionTypeModel::WITHDRAWAL, + TransactionTypeEnum::DEPOSIT->value, + TransactionTypeModel::TRANSFER, + TransactionTypeModel::OPENING_BALANCE, + ], + AccountType::DEBT => [ + TransactionTypeModel::WITHDRAWAL, + TransactionTypeEnum::DEPOSIT->value, + TransactionTypeModel::TRANSFER, + TransactionTypeModel::OPENING_BALANCE, + ], + AccountType::MORTGAGE => [ + TransactionTypeModel::WITHDRAWAL, + TransactionTypeEnum::DEPOSIT->value, + TransactionTypeModel::TRANSFER, + TransactionTypeModel::OPENING_BALANCE, + ], AccountType::INITIAL_BALANCE => [TransactionTypeModel::OPENING_BALANCE], AccountType::RECONCILIATION => [TransactionTypeModel::RECONCILIATION], AccountType::LIABILITY_CREDIT => [], // is not allowed as a destination @@ -628,7 +751,7 @@ return [ AccountType::MORTGAGE => TransactionTypeModel::DEPOSIT, ], AccountType::DEBT => [ - AccountType::ASSET => TransactionTypeModel::DEPOSIT, + AccountType::ASSET => TransactionTypeEnum::DEPOSIT->value, AccountType::DEBT => TransactionTypeModel::TRANSFER, AccountType::EXPENSE => TransactionTypeModel::WITHDRAWAL, AccountType::INITIAL_BALANCE => TransactionTypeModel::OPENING_BALANCE, @@ -642,7 +765,7 @@ return [ AccountType::MORTGAGE => TransactionTypeModel::OPENING_BALANCE, ], AccountType::LOAN => [ - AccountType::ASSET => TransactionTypeModel::DEPOSIT, + AccountType::ASSET => TransactionTypeEnum::DEPOSIT->value, AccountType::DEBT => TransactionTypeModel::TRANSFER, AccountType::EXPENSE => TransactionTypeModel::WITHDRAWAL, AccountType::INITIAL_BALANCE => TransactionTypeModel::OPENING_BALANCE, @@ -650,7 +773,7 @@ return [ AccountType::MORTGAGE => TransactionTypeModel::TRANSFER, ], AccountType::MORTGAGE => [ - AccountType::ASSET => TransactionTypeModel::DEPOSIT, + AccountType::ASSET => TransactionTypeEnum::DEPOSIT->value, AccountType::DEBT => TransactionTypeModel::TRANSFER, AccountType::EXPENSE => TransactionTypeModel::WITHDRAWAL, AccountType::INITIAL_BALANCE => TransactionTypeModel::OPENING_BALANCE, @@ -661,10 +784,10 @@ return [ AccountType::ASSET => TransactionTypeModel::RECONCILIATION, ], AccountType::REVENUE => [ - AccountType::ASSET => TransactionTypeModel::DEPOSIT, - AccountType::DEBT => TransactionTypeModel::DEPOSIT, - AccountType::LOAN => TransactionTypeModel::DEPOSIT, - AccountType::MORTGAGE => TransactionTypeModel::DEPOSIT, + AccountType::ASSET => TransactionTypeEnum::DEPOSIT->value, + AccountType::DEBT => TransactionTypeEnum::DEPOSIT->value, + AccountType::LOAN => TransactionTypeEnum::DEPOSIT->value, + AccountType::MORTGAGE => TransactionTypeEnum::DEPOSIT->value, ], AccountType::LIABILITY_CREDIT => [ AccountType::DEBT => TransactionTypeModel::LIABILITY_CREDIT, @@ -682,7 +805,7 @@ return [ AccountType::DEBT => [AccountType::EXPENSE, AccountType::CASH], AccountType::MORTGAGE => [AccountType::EXPENSE, AccountType::CASH], ], - TransactionTypeModel::DEPOSIT => [ + TransactionTypeEnum::DEPOSIT->value => [ AccountType::REVENUE => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], AccountType::CASH => [AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], AccountType::LOAN => [AccountType::ASSET], @@ -713,42 +836,46 @@ return [ AccountType::LIABILITY_CREDIT => [AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], ], ], - // if you add fields to this array, dont forget to update the export routine (ExportDataGenerator). + // if you add fields to this array, don't forget to update the export routine (ExportDataGenerator). 'journal_meta_fields' => [ // sepa - 'sepa_cc', 'sepa_ct_op', 'sepa_ct_id', - 'sepa_db', 'sepa_country', 'sepa_ep', - 'sepa_ci', 'sepa_batch_id', 'external_url', + 'sepa_cc', + 'sepa_ct_op', + 'sepa_ct_id', + 'sepa_db', + 'sepa_country', + 'sepa_ep', + 'sepa_ci', + 'sepa_batch_id', + 'external_url', // dates - 'interest_date', 'book_date', 'process_date', - 'due_date', 'payment_date', 'invoice_date', + 'interest_date', + 'book_date', + 'process_date', + 'due_date', + 'payment_date', + 'invoice_date', // others - 'recurrence_id', 'internal_reference', 'bunq_payment_id', - 'import_hash', 'import_hash_v2', 'external_id', 'original_source', + 'recurrence_id', + 'internal_reference', + 'bunq_payment_id', + 'import_hash', + 'import_hash_v2', + 'external_id', + 'original_source', // recurring transactions - 'recurrence_total', 'recurrence_count', + 'recurrence_total', + 'recurrence_count', + 'recurrence_date', ], 'webhooks' => [ 'max_attempts' => env('WEBHOOK_MAX_ATTEMPTS', 3), - 'triggers' => [ - Webhook::TRIGGER_STORE_TRANSACTION => 'TRIGGER_STORE_TRANSACTION', - Webhook::TRIGGER_UPDATE_TRANSACTION => 'TRIGGER_UPDATE_TRANSACTION', - Webhook::TRIGGER_DESTROY_TRANSACTION => 'TRIGGER_DESTROY_TRANSACTION', - ], - 'responses' => [ - Webhook::RESPONSE_TRANSACTIONS => 'RESPONSE_TRANSACTIONS', - Webhook::RESPONSE_ACCOUNTS => 'RESPONSE_ACCOUNTS', - Webhook::RESPONSE_NONE => 'RESPONSE_NONE', - ], - 'deliveries' => [ - Webhook::DELIVERY_JSON => 'DELIVERY_JSON', - ], ], 'can_have_virtual_amounts' => [AccountType::ASSET], - 'can_have_opening_balance' => [AccountType::ASSET, AccountType::DEBT, AccountType::LOAN, AccountType::MORTGAGE, AccountType::CREDITCARD], + 'can_have_opening_balance' => [AccountType::ASSET], 'valid_asset_fields' => ['account_role', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], 'valid_cc_fields' => ['account_role', 'cc_monthly_payment_date', 'cc_type', 'account_number', 'currency_id', 'BIC', 'include_net_worth'], 'valid_account_fields' => ['account_number', 'currency_id', 'BIC', 'interest', 'interest_period', 'include_net_worth', 'liability_direction'], diff --git a/config/ide-helper.php b/config/ide-helper.php index 95598ccdcf..f39619f398 100644 --- a/config/ide-helper.php +++ b/config/ide-helper.php @@ -86,7 +86,7 @@ return [ 'include_helpers' => false, 'helper_files' => [ - base_path() . '/vendor/laravel/framework/src/Illuminate/Support/helpers.php', + base_path().'/vendor/laravel/framework/src/Illuminate/Support/helpers.php', ], /* diff --git a/config/logging.php b/config/logging.php index 228f6c1de1..4b1369bcd8 100644 --- a/config/logging.php +++ b/config/logging.php @@ -62,10 +62,6 @@ return [ 'driver' => 'stack', 'channels' => ['audit_daily', 'audit_stdout'], ], - 'scoped' => [ - 'driver' => 'custom', - 'via' => FireflyIII\Logging\CreateCustomLogger::class, - ], 'papertrail' => [ 'driver' => 'monolog', 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), @@ -93,7 +89,7 @@ return [ // daily, used in stack 'stack' by default: 'daily' => [ 'driver' => 'daily', - 'path' => storage_path('logs/ff3-' . PHP_SAPI . '.log'), + 'path' => storage_path('logs/ff3-'.PHP_SAPI.'.log'), 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), 'days' => 7, ], diff --git a/config/mail.php b/config/mail.php index f1de983819..37861ebd56 100644 --- a/config/mail.php +++ b/config/mail.php @@ -37,14 +37,14 @@ return [ 'mailers' => [ 'smtp' => [ - 'transport' => 'smtp', - 'host' => env('MAIL_HOST', 'smtp.mailtrap.io'), - 'port' => (int) env('MAIL_PORT', 2525), - 'encryption' => env('MAIL_ENCRYPTION', 'tls'), - 'username' => env('MAIL_USERNAME'), - 'password' => env('MAIL_PASSWORD'), - 'timeout' => null, - 'verify_peer' => null !== env('MAIL_ENCRYPTION') + 'transport' => 'smtp', + 'host' => env('MAIL_HOST', 'smtp.mailtrap.io'), + 'port' => (int)env('MAIL_PORT', 2525), + 'encryption' => env('MAIL_ENCRYPTION', 'tls'), + 'username' => env('MAIL_USERNAME'), + 'password' => env('MAIL_PASSWORD'), + 'timeout' => null, + 'verify_peer' => null !== env('MAIL_ENCRYPTION'), ], 'ses' => [ diff --git a/config/search.php b/config/search.php index 45c9a8991c..6e065e4f07 100644 --- a/config/search.php +++ b/config/search.php @@ -26,6 +26,7 @@ return [ 'operators' => [ 'user_action' => ['alias' => false, 'needs_context' => true,], 'account_id' => ['alias' => false, 'needs_context' => true,], + 'reconciled' => ['alias' => false, 'needs_context' => false,], 'source_account_id' => ['alias' => false, 'needs_context' => true,], 'destination_account_id' => ['alias' => false, 'needs_context' => true,], 'transaction_type' => ['alias' => false, 'needs_context' => true,], @@ -229,6 +230,10 @@ return [ 'attachment_notes_start' => ['alias' => true, 'alias_for' => 'attachment_notes_starts', 'needs_context' => true], 'attachment_notes_ends' => ['alias' => false, 'needs_context' => true], 'attachment_notes_end' => ['alias' => true, 'alias_for' => 'attachment_notes_ends', 'needs_context' => true], + 'exists' => ['alias' => false, 'needs_context' => false,], 'sepa_ct_is' => ['alias' => false, 'needs_context' => true], + 'no_external_id' => ['alias' => false, 'needs_context' => false], + 'any_external_id' => ['alias' => false, 'needs_context' => false], + ], ]; diff --git a/config/twigbridge.php b/config/twigbridge.php index a56206bb83..d70ce0c3a4 100644 --- a/config/twigbridge.php +++ b/config/twigbridge.php @@ -174,19 +174,42 @@ return [ 'Form' => ['is_safe' => ['input', 'select', 'checkbox', 'model', 'open', 'radio', 'textarea', 'file']], 'ExpandedForm' => [ 'is_safe' => [ - 'date', 'text', 'select', 'balance', 'optionsList', 'checkbox', 'amount', 'tags', 'integer', 'textarea', 'location', 'file', 'staticText', - 'password', 'nonSelectableAmount', 'number', 'amountNoCurrency', 'percentage', 'objectGroup', + 'date', + 'text', + 'select', + 'balance', + 'optionsList', + 'checkbox', + 'amount', + 'tags', + 'integer', + 'textarea', + 'location', + 'file', + 'staticText', + 'password', + 'nonSelectableAmount', + 'number', + 'amountNoCurrency', + 'percentage', + 'objectGroup', ], ], 'AccountForm' => [ 'is_safe' => [ - 'activeWithdrawalDestinations', 'activeDepositDestinations', 'assetAccountCheckList', 'assetAccountList', 'longAccountList', + 'activeWithdrawalDestinations', + 'activeDepositDestinations', + 'assetAccountCheckList', + 'assetAccountList', + 'longAccountList', ], ], 'CurrencyForm' => [ 'is_safe' => [ - 'currencyList', 'currencyListEmpty', 'balanceAll', + 'currencyList', + 'currencyListEmpty', + 'balanceAll', ], ], 'PiggyBankForm' => [ @@ -196,7 +219,8 @@ return [ ], 'RuleForm' => [ 'is_safe' => [ - 'ruleGroupList', 'ruleGroupListWithEmpty', + 'ruleGroupList', + 'ruleGroupListWithEmpty', ], ], ], diff --git a/database/migrations/2016_06_16_000000_create_support_tables.php b/database/migrations/2016_06_16_000000_create_support_tables.php index fc2c2e8779..65925899dc 100644 --- a/database/migrations/2016_06_16_000000_create_support_tables.php +++ b/database/migrations/2016_06_16_000000_create_support_tables.php @@ -1,4 +1,5 @@ string('id', 100)->primary(); - $table->integer('user_id'); - $table->integer('client_id'); - $table->text('scopes')->nullable(); - $table->boolean('revoked'); - $table->dateTime('expires_at')->nullable(); - } + 'oauth_auth_codes', + static function (Blueprint $table) { + $table->string('id', 100)->primary(); + $table->integer('user_id'); + $table->integer('client_id'); + $table->text('scopes')->nullable(); + $table->boolean('revoked'); + $table->dateTime('expires_at')->nullable(); + } ); } } diff --git a/database/migrations/2018_01_01_000002_create_oauth_access_tokens_table.php b/database/migrations/2018_01_01_000002_create_oauth_access_tokens_table.php index e8e95975f2..883955a3e7 100644 --- a/database/migrations/2018_01_01_000002_create_oauth_access_tokens_table.php +++ b/database/migrations/2018_01_01_000002_create_oauth_access_tokens_table.php @@ -48,16 +48,17 @@ class CreateOauthAccessTokensTable extends Migration public function up(): void { Schema::create( - 'oauth_access_tokens', static function (Blueprint $table) { - $table->string('id', 100)->primary(); - $table->integer('user_id')->index()->nullable(); - $table->integer('client_id'); - $table->string('name')->nullable(); - $table->text('scopes')->nullable(); - $table->boolean('revoked'); - $table->timestamps(); - $table->dateTime('expires_at')->nullable(); - } + 'oauth_access_tokens', + static function (Blueprint $table) { + $table->string('id', 100)->primary(); + $table->integer('user_id')->index()->nullable(); + $table->integer('client_id'); + $table->string('name')->nullable(); + $table->text('scopes')->nullable(); + $table->boolean('revoked'); + $table->timestamps(); + $table->dateTime('expires_at')->nullable(); + } ); } } diff --git a/database/migrations/2018_01_01_000003_create_oauth_refresh_tokens_table.php b/database/migrations/2018_01_01_000003_create_oauth_refresh_tokens_table.php index 513e34b852..44a7aecdcb 100644 --- a/database/migrations/2018_01_01_000003_create_oauth_refresh_tokens_table.php +++ b/database/migrations/2018_01_01_000003_create_oauth_refresh_tokens_table.php @@ -48,12 +48,13 @@ class CreateOauthRefreshTokensTable extends Migration public function up(): void { Schema::create( - 'oauth_refresh_tokens', static function (Blueprint $table) { - $table->string('id', 100)->primary(); - $table->string('access_token_id', 100)->index(); - $table->boolean('revoked'); - $table->dateTime('expires_at')->nullable(); - } + 'oauth_refresh_tokens', + static function (Blueprint $table) { + $table->string('id', 100)->primary(); + $table->string('access_token_id', 100)->index(); + $table->boolean('revoked'); + $table->dateTime('expires_at')->nullable(); + } ); } } diff --git a/database/migrations/2018_01_01_000004_create_oauth_clients_table.php b/database/migrations/2018_01_01_000004_create_oauth_clients_table.php index c06869e26d..2fc046a840 100644 --- a/database/migrations/2018_01_01_000004_create_oauth_clients_table.php +++ b/database/migrations/2018_01_01_000004_create_oauth_clients_table.php @@ -48,17 +48,18 @@ class CreateOauthClientsTable extends Migration public function up(): void { Schema::create( - 'oauth_clients', static function (Blueprint $table) { - $table->increments('id'); - $table->integer('user_id')->index()->nullable(); - $table->string('name'); - $table->string('secret', 100); - $table->text('redirect'); - $table->boolean('personal_access_client'); - $table->boolean('password_client'); - $table->boolean('revoked'); - $table->timestamps(); - } + 'oauth_clients', + static function (Blueprint $table) { + $table->increments('id'); + $table->integer('user_id')->index()->nullable(); + $table->string('name'); + $table->string('secret', 100); + $table->text('redirect'); + $table->boolean('personal_access_client'); + $table->boolean('password_client'); + $table->boolean('revoked'); + $table->timestamps(); + } ); } } diff --git a/database/migrations/2018_01_01_000005_create_oauth_personal_access_clients_table.php b/database/migrations/2018_01_01_000005_create_oauth_personal_access_clients_table.php index 228fcf05fd..35236cff40 100644 --- a/database/migrations/2018_01_01_000005_create_oauth_personal_access_clients_table.php +++ b/database/migrations/2018_01_01_000005_create_oauth_personal_access_clients_table.php @@ -48,11 +48,12 @@ class CreateOauthPersonalAccessClientsTable extends Migration public function up(): void { Schema::create( - 'oauth_personal_access_clients', static function (Blueprint $table) { - $table->increments('id'); - $table->integer('client_id')->index(); - $table->timestamps(); - } + 'oauth_personal_access_clients', + static function (Blueprint $table) { + $table->increments('id'); + $table->integer('client_id')->index(); + $table->timestamps(); + } ); } } diff --git a/database/migrations/2018_04_07_210913_changes_for_v473.php b/database/migrations/2018_04_07_210913_changes_for_v473.php index d659877176..33e93911f8 100644 --- a/database/migrations/2018_04_07_210913_changes_for_v473.php +++ b/database/migrations/2018_04_07_210913_changes_for_v473.php @@ -43,7 +43,6 @@ class ChangesForV473 extends Migration Schema::table( 'bills', static function (Blueprint $table) { - // cannot drop foreign keys in SQLite: if ('sqlite' !== config('database.default')) { $table->dropForeign('bills_transaction_currency_id_foreign'); diff --git a/database/migrations/2018_04_29_174524_changes_for_v474.php b/database/migrations/2018_04_29_174524_changes_for_v474.php index b1e9088b78..132b86dc47 100644 --- a/database/migrations/2018_04_29_174524_changes_for_v474.php +++ b/database/migrations/2018_04_29_174524_changes_for_v474.php @@ -44,7 +44,6 @@ class ChangesForV474 extends Migration Schema::table( 'import_jobs', static function (Blueprint $table) { - // cannot drop foreign keys in SQLite: if ('sqlite' !== config('database.default')) { $table->dropForeign('import_jobs_tag_id_foreign'); diff --git a/database/migrations/2018_06_08_200526_changes_for_v475.php b/database/migrations/2018_06_08_200526_changes_for_v475.php index bab7ef6846..6e7053056e 100644 --- a/database/migrations/2018_06_08_200526_changes_for_v475.php +++ b/database/migrations/2018_06_08_200526_changes_for_v475.php @@ -56,93 +56,98 @@ class ChangesForV475 extends Migration public function up(): void { Schema::create( - 'recurrences', static function (Blueprint $table) { - $table->increments('id'); - $table->timestamps(); - $table->softDeletes(); - $table->integer('user_id', false, true); - $table->integer('transaction_type_id', false, true); + 'recurrences', + static function (Blueprint $table) { + $table->increments('id'); + $table->timestamps(); + $table->softDeletes(); + $table->integer('user_id', false, true); + $table->integer('transaction_type_id', false, true); - $table->string('title', 1024); - $table->text('description'); + $table->string('title', 1024); + $table->text('description'); - $table->date('first_date'); - $table->date('repeat_until')->nullable(); - $table->date('latest_date')->nullable(); - $table->smallInteger('repetitions', false, true); + $table->date('first_date'); + $table->date('repeat_until')->nullable(); + $table->date('latest_date')->nullable(); + $table->smallInteger('repetitions', false, true); - $table->boolean('apply_rules')->default(true); - $table->boolean('active')->default(true); + $table->boolean('apply_rules')->default(true); + $table->boolean('active')->default(true); - $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); - $table->foreign('transaction_type_id')->references('id')->on('transaction_types')->onDelete('cascade'); - } + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + $table->foreign('transaction_type_id')->references('id')->on('transaction_types')->onDelete('cascade'); + } ); Schema::create( - 'recurrences_transactions', static function (Blueprint $table) { - $table->increments('id'); - $table->timestamps(); - $table->softDeletes(); - $table->integer('recurrence_id', false, true); - $table->integer('transaction_currency_id', false, true); - $table->integer('foreign_currency_id', false, true)->nullable(); - $table->integer('source_id', false, true); - $table->integer('destination_id', false, true); + 'recurrences_transactions', + static function (Blueprint $table) { + $table->increments('id'); + $table->timestamps(); + $table->softDeletes(); + $table->integer('recurrence_id', false, true); + $table->integer('transaction_currency_id', false, true); + $table->integer('foreign_currency_id', false, true)->nullable(); + $table->integer('source_id', false, true); + $table->integer('destination_id', false, true); - $table->decimal('amount', 36, 24); - $table->decimal('foreign_amount', 36, 24)->nullable(); - $table->string('description', 1024); + $table->decimal('amount', 36, 24); + $table->decimal('foreign_amount', 36, 24)->nullable(); + $table->string('description', 1024); - $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); - $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade'); - $table->foreign('foreign_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); - $table->foreign('source_id')->references('id')->on('accounts')->onDelete('cascade'); - $table->foreign('destination_id')->references('id')->on('accounts')->onDelete('cascade'); - } + $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); + $table->foreign('transaction_currency_id')->references('id')->on('transaction_currencies')->onDelete('cascade'); + $table->foreign('foreign_currency_id')->references('id')->on('transaction_currencies')->onDelete('set null'); + $table->foreign('source_id')->references('id')->on('accounts')->onDelete('cascade'); + $table->foreign('destination_id')->references('id')->on('accounts')->onDelete('cascade'); + } ); Schema::create( - 'recurrences_repetitions', static function (Blueprint $table) { - $table->increments('id'); - $table->timestamps(); - $table->softDeletes(); - $table->integer('recurrence_id', false, true); - $table->string('repetition_type', 50); - $table->string('repetition_moment', 50); - $table->smallInteger('repetition_skip', false, true); - $table->smallInteger('weekend', false, true); + 'recurrences_repetitions', + static function (Blueprint $table) { + $table->increments('id'); + $table->timestamps(); + $table->softDeletes(); + $table->integer('recurrence_id', false, true); + $table->string('repetition_type', 50); + $table->string('repetition_moment', 50); + $table->smallInteger('repetition_skip', false, true); + $table->smallInteger('weekend', false, true); - $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); - } + $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); + } ); Schema::create( - 'recurrences_meta', static function (Blueprint $table) { - $table->increments('id'); - $table->timestamps(); - $table->softDeletes(); - $table->integer('recurrence_id', false, true); + 'recurrences_meta', + static function (Blueprint $table) { + $table->increments('id'); + $table->timestamps(); + $table->softDeletes(); + $table->integer('recurrence_id', false, true); - $table->string('name', 50); - $table->text('value'); + $table->string('name', 50); + $table->text('value'); - $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); - } + $table->foreign('recurrence_id')->references('id')->on('recurrences')->onDelete('cascade'); + } ); Schema::create( - 'rt_meta', static function (Blueprint $table) { - $table->increments('id'); - $table->timestamps(); - $table->softDeletes(); - $table->integer('rt_id', false, true); + 'rt_meta', + static function (Blueprint $table) { + $table->increments('id'); + $table->timestamps(); + $table->softDeletes(); + $table->integer('rt_id', false, true); - $table->string('name', 50); - $table->text('value'); + $table->string('name', 50); + $table->text('value'); - $table->foreign('rt_id')->references('id')->on('recurrences_transactions')->onDelete('cascade'); - } + $table->foreign('rt_id')->references('id')->on('recurrences_transactions')->onDelete('cascade'); + } ); } } diff --git a/database/migrations/2018_09_05_195147_changes_for_v477.php b/database/migrations/2018_09_05_195147_changes_for_v477.php index d9f9678942..3db1986b8f 100644 --- a/database/migrations/2018_09_05_195147_changes_for_v477.php +++ b/database/migrations/2018_09_05_195147_changes_for_v477.php @@ -40,15 +40,15 @@ class ChangesForV477 extends Migration public function down(): void { Schema::table( - 'budget_limits', static function (Blueprint $table) { + 'budget_limits', + static function (Blueprint $table) { + // cannot drop foreign keys in SQLite: + if ('sqlite' !== config('database.default')) { + $table->dropForeign('budget_limits_transaction_currency_id_foreign'); + } - // cannot drop foreign keys in SQLite: - if ('sqlite' !== config('database.default')) { - $table->dropForeign('budget_limits_transaction_currency_id_foreign'); + $table->dropColumn(['transaction_currency_id']); } - - $table->dropColumn(['transaction_currency_id']); - } ); } diff --git a/database/migrations/2018_11_06_172532_changes_for_v479.php b/database/migrations/2018_11_06_172532_changes_for_v479.php index 3001eea2d3..9cc0093cbf 100644 --- a/database/migrations/2018_11_06_172532_changes_for_v479.php +++ b/database/migrations/2018_11_06_172532_changes_for_v479.php @@ -40,9 +40,10 @@ class ChangesForV479 extends Migration public function down() { Schema::table( - 'transaction_currencies', static function (Blueprint $table) { - $table->dropColumn(['enabled']); - } + 'transaction_currencies', + static function (Blueprint $table) { + $table->dropColumn(['enabled']); + } ); } diff --git a/database/migrations/2019_01_28_193833_changes_for_v4710.php b/database/migrations/2019_01_28_193833_changes_for_v4710.php index dfda36398d..0e07b4286f 100644 --- a/database/migrations/2019_01_28_193833_changes_for_v4710.php +++ b/database/migrations/2019_01_28_193833_changes_for_v4710.php @@ -54,15 +54,16 @@ class ChangesForV4710 extends Migration { if (!Schema::hasTable('transaction_groups')) { Schema::create( - 'transaction_groups', static function (Blueprint $table) { - $table->increments('id'); - $table->timestamps(); - $table->softDeletes(); - $table->integer('user_id', false, true); - $table->string('title', 1024)->nullable(); + 'transaction_groups', + static function (Blueprint $table) { + $table->increments('id'); + $table->timestamps(); + $table->softDeletes(); + $table->integer('user_id', false, true); + $table->string('title', 1024)->nullable(); - $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); - } + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + } ); } diff --git a/database/migrations/2019_02_05_055516_changes_for_v4711.php b/database/migrations/2019_02_05_055516_changes_for_v4711.php index 1829ede413..430f23f0e9 100644 --- a/database/migrations/2019_02_05_055516_changes_for_v4711.php +++ b/database/migrations/2019_02_05_055516_changes_for_v4711.php @@ -60,15 +60,17 @@ class ChangesForV4711 extends Migration * nice. */ Schema::table( - 'transaction_journals', static function (Blueprint $table) { - $table->dateTime('date')->change(); - } + 'transaction_journals', + static function (Blueprint $table) { + $table->dateTime('date')->change(); + } ); Schema::table( - 'preferences', static function (Blueprint $table) { - $table->text('data')->nullable()->change(); - } + 'preferences', + static function (Blueprint $table) { + $table->text('data')->nullable()->change(); + } ); } } diff --git a/database/migrations/2019_02_11_170529_changes_for_v4712.php b/database/migrations/2019_02_11_170529_changes_for_v4712.php index 8d235a6b4e..09c3bb4910 100644 --- a/database/migrations/2019_02_11_170529_changes_for_v4712.php +++ b/database/migrations/2019_02_11_170529_changes_for_v4712.php @@ -59,9 +59,10 @@ class ChangesForV4712 extends Migration * nice. */ Schema::table( - 'transaction_journals', static function (Blueprint $table) { - $table->dateTime('date')->change(); - } + 'transaction_journals', + static function (Blueprint $table) { + $table->dateTime('date')->change(); + } ); } } diff --git a/database/migrations/2019_03_11_223700_fix_ldap_configuration.php b/database/migrations/2019_03_11_223700_fix_ldap_configuration.php index 9f16faaa27..bbf7a89207 100644 --- a/database/migrations/2019_03_11_223700_fix_ldap_configuration.php +++ b/database/migrations/2019_03_11_223700_fix_ldap_configuration.php @@ -40,9 +40,10 @@ class FixLdapConfiguration extends Migration public function down(): void { Schema::table( - 'users', static function (Blueprint $table) { - $table->dropColumn(['objectguid']); - } + 'users', + static function (Blueprint $table) { + $table->dropColumn(['objectguid']); + } ); } @@ -59,9 +60,10 @@ class FixLdapConfiguration extends Migration * now. To support this, we add the column. */ Schema::table( - 'users', static function (Blueprint $table) { - $table->uuid('objectguid')->nullable()->after('id'); - } + 'users', + static function (Blueprint $table) { + $table->uuid('objectguid')->nullable()->after('id'); + } ); } } diff --git a/database/migrations/2019_03_22_183214_changes_for_v480.php b/database/migrations/2019_03_22_183214_changes_for_v480.php index d68a2fbffe..825cfbecb6 100644 --- a/database/migrations/2019_03_22_183214_changes_for_v480.php +++ b/database/migrations/2019_03_22_183214_changes_for_v480.php @@ -50,15 +50,17 @@ class ChangesForV480 extends Migration } ); Schema::table( - 'rule_groups', static function (Blueprint $table) { - $table->dropColumn('stop_processing'); - } + 'rule_groups', + static function (Blueprint $table) { + $table->dropColumn('stop_processing'); + } ); Schema::table( - 'users', static function (Blueprint $table) { - $table->dropColumn('mfa_secret'); - } + 'users', + static function (Blueprint $table) { + $table->dropColumn('mfa_secret'); + } ); } @@ -84,14 +86,16 @@ class ChangesForV480 extends Migration } ); Schema::table( - 'rule_groups', static function (Blueprint $table) { - $table->boolean('stop_processing')->default(false); - } + 'rule_groups', + static function (Blueprint $table) { + $table->boolean('stop_processing')->default(false); + } ); Schema::table( - 'users', static function (Blueprint $table) { - $table->string('mfa_secret', 50)->nullable(); - } + 'users', + static function (Blueprint $table) { + $table->string('mfa_secret', 50)->nullable(); + } ); } } diff --git a/database/migrations/2019_12_28_191351_make_locations_table.php b/database/migrations/2019_12_28_191351_make_locations_table.php index b2435c8430..65c6dc91b0 100644 --- a/database/migrations/2019_12_28_191351_make_locations_table.php +++ b/database/migrations/2019_12_28_191351_make_locations_table.php @@ -51,18 +51,19 @@ class MakeLocationsTable extends Migration public function up() { Schema::create( - 'locations', static function (Blueprint $table) { - $table->bigIncrements('id'); - $table->timestamps(); - $table->softDeletes(); + 'locations', + static function (Blueprint $table) { + $table->bigIncrements('id'); + $table->timestamps(); + $table->softDeletes(); - $table->integer('locatable_id', false, true); - $table->string('locatable_type', 255); + $table->integer('locatable_id', false, true); + $table->string('locatable_type', 255); - $table->decimal('latitude', 36, 24)->nullable(); - $table->decimal('longitude', 36, 24)->nullable(); - $table->smallInteger('zoom_level', false, true)->nullable(); - } + $table->decimal('latitude', 36, 24)->nullable(); + $table->decimal('longitude', 36, 24)->nullable(); + $table->smallInteger('zoom_level', false, true)->nullable(); + } ); } } diff --git a/database/migrations/2020_06_07_063612_changes_for_v530.php b/database/migrations/2020_06_07_063612_changes_for_v530.php index 6f5eb8204a..0441731aa6 100644 --- a/database/migrations/2020_06_07_063612_changes_for_v530.php +++ b/database/migrations/2020_06_07_063612_changes_for_v530.php @@ -52,24 +52,26 @@ class ChangesForV530 extends Migration { if (!Schema::hasTable('object_groups')) { Schema::create( - 'object_groups', static function (Blueprint $table) { - $table->increments('id'); - $table->integer('user_id', false, true); - $table->timestamps(); - $table->softDeletes(); - $table->string('title', 255); - $table->mediumInteger('order', false, true)->default(0); - $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); - } + 'object_groups', + static function (Blueprint $table) { + $table->increments('id'); + $table->integer('user_id', false, true); + $table->timestamps(); + $table->softDeletes(); + $table->string('title', 255); + $table->mediumInteger('order', false, true)->default(0); + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + } ); } if (!Schema::hasTable('object_groupables')) { Schema::create( - 'object_groupables', static function (Blueprint $table) { - $table->integer('object_group_id'); - $table->integer('object_groupable_id', false, true); - $table->string('object_groupable_type', 255); - } + 'object_groupables', + static function (Blueprint $table) { + $table->integer('object_group_id'); + $table->integer('object_groupable_id', false, true); + $table->string('object_groupable_type', 255); + } ); } } diff --git a/database/migrations/2020_06_30_202620_changes_for_v530a.php b/database/migrations/2020_06_30_202620_changes_for_v530a.php index b5412de5d4..b54a7144cc 100644 --- a/database/migrations/2020_06_30_202620_changes_for_v530a.php +++ b/database/migrations/2020_06_30_202620_changes_for_v530a.php @@ -41,9 +41,10 @@ class ChangesForV530a extends Migration public function down(): void { Schema::table( - 'bills', static function (Blueprint $table) { - $table->dropColumn('order'); - } + 'bills', + static function (Blueprint $table) { + $table->dropColumn('order'); + } ); } @@ -55,9 +56,10 @@ class ChangesForV530a extends Migration public function up(): void { Schema::table( - 'bills', static function (Blueprint $table) { - $table->integer('order', false, true)->default(0); - } + 'bills', + static function (Blueprint $table) { + $table->integer('order', false, true)->default(0); + } ); } } diff --git a/database/migrations/2020_07_24_162820_changes_for_v540.php b/database/migrations/2020_07_24_162820_changes_for_v540.php index 3e1f951768..38401fba0a 100644 --- a/database/migrations/2020_07_24_162820_changes_for_v540.php +++ b/database/migrations/2020_07_24_162820_changes_for_v540.php @@ -41,22 +41,25 @@ class ChangesForV540 extends Migration public function down(): void { Schema::table( - 'oauth_clients', static function (Blueprint $table) { - $table->dropColumn('provider'); - } + 'oauth_clients', + static function (Blueprint $table) { + $table->dropColumn('provider'); + } ); Schema::table( - 'accounts', static function (Blueprint $table) { - $table->dropColumn('order'); - } + 'accounts', + static function (Blueprint $table) { + $table->dropColumn('order'); + } ); Schema::table( - 'bills', static function (Blueprint $table) { - $table->dropColumn('end_date'); - $table->dropColumn('extension_date'); - } + 'bills', + static function (Blueprint $table) { + $table->dropColumn('end_date'); + $table->dropColumn('extension_date'); + } ); } @@ -68,26 +71,30 @@ class ChangesForV540 extends Migration public function up(): void { Schema::table( - 'accounts', static function (Blueprint $table) { - $table->integer('order', false, true)->default(0); - } + 'accounts', + static function (Blueprint $table) { + $table->integer('order', false, true)->default(0); + } ); Schema::table( - 'oauth_clients', static function (Blueprint $table) { - $table->string('provider')->nullable(); - } + 'oauth_clients', + static function (Blueprint $table) { + $table->string('provider')->nullable(); + } ); Schema::table( - 'bills', static function (Blueprint $table) { - $table->date('end_date')->nullable()->after('date'); - $table->date('extension_date')->nullable()->after('end_date'); - } + 'bills', + static function (Blueprint $table) { + $table->date('end_date')->nullable()->after('date'); + $table->date('extension_date')->nullable()->after('end_date'); + } ); // make column nullable: Schema::table( - 'oauth_clients', function (Blueprint $table) { - $table->string('secret', 100)->nullable()->change(); - } + 'oauth_clients', + function (Blueprint $table) { + $table->string('secret', 100)->nullable()->change(); + } ); } } diff --git a/database/migrations/2020_11_12_070604_changes_for_v550.php b/database/migrations/2020_11_12_070604_changes_for_v550.php index 9cec0a1dcf..9c73f036a5 100644 --- a/database/migrations/2020_11_12_070604_changes_for_v550.php +++ b/database/migrations/2020_11_12_070604_changes_for_v550.php @@ -58,10 +58,11 @@ class ChangesForV550 extends Migration // expand budget / transaction journal table. Schema::table( - 'budget_transaction_journal', function (Blueprint $table) { - $table->dropForeign('budget_id_foreign'); - $table->dropColumn('budget_limit_id'); - } + 'budget_transaction_journal', + function (Blueprint $table) { + $table->dropForeign('budget_id_foreign'); + $table->dropColumn('budget_limit_id'); + } ); // drop failed jobs table. @@ -91,40 +92,43 @@ class ChangesForV550 extends Migration Schema::dropIfExists('jobs'); // this is the NEW table Schema::create( - 'jobs', function (Blueprint $table) { - $table->bigIncrements('id'); - $table->string('queue')->index(); - $table->longText('payload'); - $table->unsignedTinyInteger('attempts'); - $table->unsignedInteger('reserved_at')->nullable(); - $table->unsignedInteger('available_at'); - $table->unsignedInteger('created_at'); - } + 'jobs', + function (Blueprint $table) { + $table->bigIncrements('id'); + $table->string('queue')->index(); + $table->longText('payload'); + $table->unsignedTinyInteger('attempts'); + $table->unsignedInteger('reserved_at')->nullable(); + $table->unsignedInteger('available_at'); + $table->unsignedInteger('created_at'); + } ); // drop failed jobs table. Schema::dropIfExists('failed_jobs'); // create new failed_jobs table. Schema::create( - 'failed_jobs', function (Blueprint $table) { - $table->bigIncrements('id'); - $table->string('uuid')->unique(); - $table->text('connection'); - $table->text('queue'); - $table->longText('payload'); - $table->longText('exception'); - $table->timestamp('failed_at')->useCurrent(); - } + 'failed_jobs', + function (Blueprint $table) { + $table->bigIncrements('id'); + $table->string('uuid')->unique(); + $table->text('connection'); + $table->text('queue'); + $table->longText('payload'); + $table->longText('exception'); + $table->timestamp('failed_at')->useCurrent(); + } ); // update budget / transaction journal table. Schema::table( - 'budget_transaction_journal', function (Blueprint $table) { - if (!Schema::hasColumn('budget_transaction_journal', 'budget_limit_id')) { - $table->integer('budget_limit_id', false, true)->nullable()->default(null)->after('budget_id'); - $table->foreign('budget_limit_id', 'budget_id_foreign')->references('id')->on('budget_limits')->onDelete('set null'); + 'budget_transaction_journal', + function (Blueprint $table) { + if (!Schema::hasColumn('budget_transaction_journal', 'budget_limit_id')) { + $table->integer('budget_limit_id', false, true)->nullable()->default(null)->after('budget_id'); + $table->foreign('budget_limit_id', 'budget_id_foreign')->references('id')->on('budget_limits')->onDelete('set null'); + } } - } ); // append budget limits table. diff --git a/database/migrations/2021_03_12_061213_changes_for_v550b2.php b/database/migrations/2021_03_12_061213_changes_for_v550b2.php index a894a00324..4b3a97a1b2 100644 --- a/database/migrations/2021_03_12_061213_changes_for_v550b2.php +++ b/database/migrations/2021_03_12_061213_changes_for_v550b2.php @@ -39,14 +39,13 @@ class ChangesForV550b2 extends Migration public function down(): void { Schema::table( - 'recurrences_transactions', function (Blueprint $table) { - - $table->dropForeign('type_foreign'); - if (Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) { - $table->dropColumn('transaction_type_id'); + 'recurrences_transactions', + function (Blueprint $table) { + $table->dropForeign('type_foreign'); + if (Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) { + $table->dropColumn('transaction_type_id'); + } } - - } ); } @@ -59,12 +58,13 @@ class ChangesForV550b2 extends Migration { // expand recurrence transaction table Schema::table( - 'recurrences_transactions', function (Blueprint $table) { - if (!Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) { - $table->integer('transaction_type_id', false, true)->nullable()->after('transaction_currency_id'); - $table->foreign('transaction_type_id', 'type_foreign')->references('id')->on('transaction_types')->onDelete('set null'); + 'recurrences_transactions', + function (Blueprint $table) { + if (!Schema::hasColumn('recurrences_transactions', 'transaction_type_id')) { + $table->integer('transaction_type_id', false, true)->nullable()->after('transaction_currency_id'); + $table->foreign('transaction_type_id', 'type_foreign')->references('id')->on('transaction_types')->onDelete('set null'); + } } - } ); } } diff --git a/database/migrations/2021_05_09_064644_add_ldap_columns_to_users_table.php b/database/migrations/2021_05_09_064644_add_ldap_columns_to_users_table.php index 17d54fa8bd..5a0ad59217 100644 --- a/database/migrations/2021_05_09_064644_add_ldap_columns_to_users_table.php +++ b/database/migrations/2021_05_09_064644_add_ldap_columns_to_users_table.php @@ -34,9 +34,10 @@ class AddLdapColumnsToUsersTable extends Migration public function down() { Schema::table( - 'users', function (Blueprint $table) { - $table->dropColumn(['domain']); - } + 'users', + function (Blueprint $table) { + $table->dropColumn(['domain']); + } ); } @@ -46,9 +47,10 @@ class AddLdapColumnsToUsersTable extends Migration public function up() { Schema::table( - 'users', function (Blueprint $table) { - $table->string('domain')->nullable(); - } + 'users', + function (Blueprint $table) { + $table->string('domain')->nullable(); + } ); } } diff --git a/database/migrations/2021_05_13_053836_extend_currency_info.php b/database/migrations/2021_05_13_053836_extend_currency_info.php index 1eeea51fa5..cc572ac058 100644 --- a/database/migrations/2021_05_13_053836_extend_currency_info.php +++ b/database/migrations/2021_05_13_053836_extend_currency_info.php @@ -49,10 +49,11 @@ class ExtendCurrencyInfo extends Migration public function up() { Schema::table( - 'transaction_currencies', function (Blueprint $table) { - $table->string('code', 51)->change(); - $table->string('symbol', 51)->change(); - } + 'transaction_currencies', + function (Blueprint $table) { + $table->string('code', 51)->change(); + $table->string('symbol', 51)->change(); + } ); } } diff --git a/database/migrations/2021_08_28_073733_user_groups.php b/database/migrations/2021_08_28_073733_user_groups.php index 70afc7d990..fcc2f8242f 100644 --- a/database/migrations/2021_08_28_073733_user_groups.php +++ b/database/migrations/2021_08_28_073733_user_groups.php @@ -32,8 +32,21 @@ use Illuminate\Support\Facades\Schema; class UserGroups extends Migration { private array $tables - = ['accounts', 'attachments', 'available_budgets', 'bills', 'budgets', 'categories', 'recurrences', 'rule_groups', 'rules', 'tags', - 'transaction_groups', 'transaction_journals', 'webhooks']; + = [ + 'accounts', + 'attachments', + 'available_budgets', + 'bills', + 'budgets', + 'categories', + 'recurrences', + 'rule_groups', + 'rules', + 'tags', + 'transaction_groups', + 'transaction_journals', + 'webhooks', + ]; /** * Reverse the migrations. @@ -46,25 +59,24 @@ class UserGroups extends Migration /** @var string $tableName */ foreach ($this->tables as $tableName) { Schema::table( - $tableName, function (Blueprint $table) use ($tableName) { - - $table->dropForeign(sprintf('%s_to_ugi', $tableName)); - if (Schema::hasColumn($tableName, 'user_group_id')) { - $table->dropColumn('user_group_id'); + $tableName, + function (Blueprint $table) use ($tableName) { + $table->dropForeign(sprintf('%s_to_ugi', $tableName)); + if (Schema::hasColumn($tableName, 'user_group_id')) { + $table->dropColumn('user_group_id'); + } } - } ); } Schema::table( - 'users', function (Blueprint $table) { - - $table->dropForeign('type_user_group_id'); - if (Schema::hasColumn('users', 'user_group_id')) { - $table->dropColumn('user_group_id'); + 'users', + function (Blueprint $table) { + $table->dropForeign('type_user_group_id'); + if (Schema::hasColumn('users', 'user_group_id')) { + $table->dropColumn('user_group_id'); + } } - - } ); Schema::dropIfExists('group_memberships'); @@ -84,25 +96,27 @@ class UserGroups extends Migration * may have multiple roles in a group */ Schema::create( - 'user_groups', static function (Blueprint $table) { - $table->bigIncrements('id'); - $table->timestamps(); - $table->softDeletes(); + 'user_groups', + static function (Blueprint $table) { + $table->bigIncrements('id'); + $table->timestamps(); + $table->softDeletes(); - $table->string('title', 255); - $table->unique('title'); - } + $table->string('title', 255); + $table->unique('title'); + } ); Schema::create( - 'user_roles', static function (Blueprint $table) { - $table->bigIncrements('id'); - $table->timestamps(); - $table->softDeletes(); + 'user_roles', + static function (Blueprint $table) { + $table->bigIncrements('id'); + $table->timestamps(); + $table->softDeletes(); - $table->string('title', 255); - $table->unique('title'); - } + $table->string('title', 255); + $table->unique('title'); + } ); Schema::create( @@ -122,27 +136,29 @@ class UserGroups extends Migration } ); Schema::table( - 'users', function (Blueprint $table) { - if (!Schema::hasColumn('users', 'user_group_id')) { - $table->bigInteger('user_group_id', false, true)->nullable(); - $table->foreign('user_group_id', 'type_user_group_id')->references('id')->on('user_groups')->onDelete('set null')->onUpdate('cascade'); + 'users', + function (Blueprint $table) { + if (!Schema::hasColumn('users', 'user_group_id')) { + $table->bigInteger('user_group_id', false, true)->nullable(); + $table->foreign('user_group_id', 'type_user_group_id')->references('id')->on('user_groups')->onDelete('set null')->onUpdate('cascade'); + } } - } ); // ADD columns from tables /** @var string $tableName */ foreach ($this->tables as $tableName) { Schema::table( - $tableName, function (Blueprint $table) use ($tableName) { - - if (!Schema::hasColumn($tableName, 'user_group_id')) { - $table->bigInteger('user_group_id', false, true)->nullable()->after('user_id'); - $table->foreign('user_group_id', sprintf('%s_to_ugi', $tableName))->references('id')->on('user_groups')->onDelete('set null')->onUpdate('cascade'); + $tableName, + function (Blueprint $table) use ($tableName) { + if (!Schema::hasColumn($tableName, 'user_group_id')) { + $table->bigInteger('user_group_id', false, true)->nullable()->after('user_id'); + $table->foreign('user_group_id', sprintf('%s_to_ugi', $tableName))->references('id')->on('user_groups')->onDelete('set null')->onUpdate( + 'cascade' + ); + } } - } ); } - } } diff --git a/database/migrations/2022_08_21_104626_add_user_groups.php b/database/migrations/2022_08_21_104626_add_user_groups.php new file mode 100644 index 0000000000..4a8ea74758 --- /dev/null +++ b/database/migrations/2022_08_21_104626_add_user_groups.php @@ -0,0 +1,68 @@ +. + */ + +declare(strict_types=1); + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +/** + * + */ +return new class () extends Migration { + /** + * Run the migrations. + * + * @return void + */ + public function up(): void + { + Schema::table( + 'currency_exchange_rates', + function (Blueprint $table) { + if (!Schema::hasColumn('currency_exchange_rates', 'user_group_id')) { + $table->bigInteger('user_group_id', false, true)->nullable()->after('user_id'); + $table->foreign('user_group_id', 'cer_to_ugi')->references('id')->on('user_groups')->onDelete('set null')->onUpdate('cascade'); + } + } + ); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down(): void + { + Schema::table( + 'currency_exchange_rates', + function (Blueprint $table) { + $table->dropForeign('cer_to_ugi'); + if (Schema::hasColumn('currency_exchange_rates', 'user_group_id')) { + $table->dropColumn('user_group_id'); + } + } + ); + } +}; diff --git a/database/migrations/2022_09_18_123911_create_notifications_table.php b/database/migrations/2022_09_18_123911_create_notifications_table.php new file mode 100644 index 0000000000..cafb647bf0 --- /dev/null +++ b/database/migrations/2022_09_18_123911_create_notifications_table.php @@ -0,0 +1,56 @@ +. + */ + +declare(strict_types=1); + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class () extends Migration { + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('notifications', function (Blueprint $table) { + $table->uuid('id')->primary(); + $table->string('type'); + $table->morphs('notifiable'); + $table->text('data'); + $table->timestamp('read_at')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('notifications'); + } +}; diff --git a/database/migrations/2022_10_01_074908_invited_users.php b/database/migrations/2022_10_01_074908_invited_users.php new file mode 100644 index 0000000000..d91ccb6508 --- /dev/null +++ b/database/migrations/2022_10_01_074908_invited_users.php @@ -0,0 +1,58 @@ +. + */ + +declare(strict_types=1); + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class () extends Migration { + /** + * Run the migrations. + * + * @return void + */ + public function up(): void + { + Schema::create('invited_users', function (Blueprint $table) { + $table->id(); + $table->timestamps(); + $table->integer('user_id', false, true); + $table->string('email', 255); + $table->string('invite_code', 64); + $table->dateTime('expires'); + $table->boolean('redeemed'); + $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down(): void + { + Schema::dropIfExists('invited_users'); + } +}; diff --git a/database/migrations/2022_10_01_210238_audit_log_entries.php b/database/migrations/2022_10_01_210238_audit_log_entries.php new file mode 100644 index 0000000000..5b6d2d1ae9 --- /dev/null +++ b/database/migrations/2022_10_01_210238_audit_log_entries.php @@ -0,0 +1,63 @@ +. + */ + +declare(strict_types=1); + +use Illuminate\Database\Migrations\Migration; +use Illuminate\Database\Schema\Blueprint; +use Illuminate\Support\Facades\Schema; + +return new class () extends Migration { + /** + * Run the migrations. + * + * @return void + */ + public function up() + { + Schema::create('audit_log_entries', function (Blueprint $table) { + $table->id(); + $table->timestamps(); + $table->softDeletes(); + + $table->integer('auditable_id', false, true); + $table->string('auditable_type'); + + $table->integer('changer_id', false, true); + $table->string('changer_type'); + + $table->string('action', 255); + $table->text('before')->nullable(); + $table->text('after')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::dropIfExists('audit_log_entries'); + } +}; diff --git a/database/seeders/AccountTypeSeeder.php b/database/seeders/AccountTypeSeeder.php index e917f3ba94..5d0eac7ee7 100644 --- a/database/seeders/AccountTypeSeeder.php +++ b/database/seeders/AccountTypeSeeder.php @@ -1,4 +1,5 @@ data = $version; $entry->save(); diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index 839742aa3c..8c18621566 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -1,4 +1,5 @@ call(LinkTypeSeeder::class); $this->call(ConfigSeeder::class); $this->call(UserRoleSeeder::class); + $this->call(ExchangeRateSeeder::class); } } diff --git a/database/seeders/ExchangeRateSeeder.php b/database/seeders/ExchangeRateSeeder.php new file mode 100644 index 0000000000..390b70d36a --- /dev/null +++ b/database/seeders/ExchangeRateSeeder.php @@ -0,0 +1,120 @@ +. + */ + +declare(strict_types=1); + +namespace Database\Seeders; + +use FireflyIII\Models\CurrencyExchangeRate; +use FireflyIII\Models\TransactionCurrency; +use FireflyIII\User; +use Illuminate\Database\Seeder; +use Illuminate\Support\Collection; +use Log; + +/** + * Class ExchangeRateSeeder + */ +class ExchangeRateSeeder extends Seeder +{ + private Collection $users; + + /** + * @return void + */ + public function run(): void + { + $count = User::count(); + if (0 === $count) { + Log::debug('Will not seed exchange rates yet.'); + return; + } + $users = User::get(); + $date = config('cer.date'); + $rates = config('cer.rates'); + $usable = []; + foreach ($rates as $rate) { + $from = $this->getCurrency($rate[0]); + $to = $this->getCurrency($rate[1]); + if (null !== $from && null !== $to) { + $usable[] = [$from, $to, $rate[2]]; + } + } + unset($rates, $from, $to, $rate); + + /** @var User $user */ + foreach ($users as $user) { + foreach ($usable as $rate) { + if (!$this->hasRate($user, $rate[0], $rate[1], $date)) { + $this->addRate($user, $rate[0], $rate[1], $date, $rate[2]); + } + } + } + } + + /** + * @param string $code + * @return TransactionCurrency|null + */ + private function getCurrency(string $code): ?TransactionCurrency + { + return TransactionCurrency::whereNull('deleted_at')->where('code', $code)->first(); + } + + /** + * @param User $user + * @param TransactionCurrency $from + * @param TransactionCurrency $to + * @param string $date + * @return bool + */ + private function hasRate(User $user, TransactionCurrency $from, TransactionCurrency $to, string $date): bool + { + return $user->currencyExchangeRates() + ->where('from_currency_id', $from->id) + ->where('to_currency_id', $to->id) + ->where('date', $date) + ->count() > 0; + } + + /** + * @param User $user + * @param TransactionCurrency $from + * @param TransactionCurrency $to + * @param string $date + * @param float $rate + * @return void + */ + private function addRate(User $user, TransactionCurrency $from, TransactionCurrency $to, string $date, float $rate): void + { + /** @var User $user */ + CurrencyExchangeRate::create( + [ + 'user_id' => $user->id, + 'from_currency_id' => $from->id, + 'to_currency_id' => $to->id, + 'date' => $date, + 'rate' => $rate, + ] + ); + } +} diff --git a/database/seeders/LinkTypeSeeder.php b/database/seeders/LinkTypeSeeder.php index 00ee9fee54..79731451dd 100644 --- a/database/seeders/LinkTypeSeeder.php +++ b/database/seeders/LinkTypeSeeder.php @@ -1,4 +1,5 @@ 'JPY', 'name' => 'Japanese yen', 'symbol' => '„', 'decimal_places' => 0]; - $currencies[] = ['code' => 'RMB', 'name' => 'Chinese yuan', 'symbol' => '„', 'decimal_places' => 2]; + $currencies[] = ['code' => 'CNY', 'name' => 'Chinese yuan', 'symbol' => '„', 'decimal_places' => 2]; $currencies[] = ['code' => 'RUB', 'name' => 'Russian ruble', 'symbol' => 'ₜ', 'decimal_places' => 2]; $currencies[] = ['code' => 'INR', 'name' => 'Indian rupee', 'symbol' => 'â‚č', 'decimal_places' => 2]; diff --git a/database/seeders/TransactionTypeSeeder.php b/database/seeders/TransactionTypeSeeder.php index d3dd66be5d..661968afa0 100644 --- a/database/seeders/TransactionTypeSeeder.php +++ b/database/seeders/TransactionTypeSeeder.php @@ -1,4 +1,5 @@ import {defineComponent} from 'vue'; import Preferences from "./api/preferences"; +import Prefs from "./api/v2/preferences"; import Currencies from "./api/currencies"; -import {setDatesFromViewRange} from "./store/fireflyiii/actions"; +import {useFireflyIIIStore} from 'stores/fireflyiii' + export default defineComponent( { name: 'App', preFetch({store}) { + const ffStore = useFireflyIIIStore(store); - store.dispatch('fireflyiii/refreshCacheKey'); + ffStore.refreshCacheKey(); - const getViewRange = function() { + const getViewRange = function () { let pref = new Preferences(); - return pref.getByName('viewRange').then(data => { + return pref.getByName('viewRange').then(data => { const viewRange = data.data.data.attributes.data; - store.commit('fireflyiii/updateViewRange', viewRange); - store.dispatch('fireflyiii/setDatesFromViewRange'); + ffStore.updateViewRange(viewRange); + ffStore.setDatesFromViewRange(); }).catch((err) => { console.error('Could not load view range.') console.log(err); }); }; - const getListPageSize = function() { + const getListPageSize = function () { let pref = new Preferences(); - return pref.getByName('listPageSize').then(data => { + return pref.getByName('listPageSize').then(data => { const listPageSize = data.data.data.attributes.data; - store.commit('fireflyiii/updateListPageSize', listPageSize); + ffStore.updateListPageSize(listPageSize); }).catch((err) => { console.error('Could not load listPageSize.') console.log(err); }); }; - const getDefaultCurrency = function() { + const getDefaultCurrency = function () { let curr = new Currencies(); - return curr.default().then(data => { + return curr.default().then(data => { let currencyId = parseInt(data.data.data.id); let currencyCode = data.data.data.attributes.code; - store.commit('fireflyiii/setCurrencyId', currencyId); - store.commit('fireflyiii/setCurrencyCode', currencyCode); + ffStore.setCurrencyId(currencyId); + ffStore.setCurrencyCode(currencyCode); }).catch((err) => { console.error('Could not load preferences.'); console.log(err); }); }; + const getLocale = function () { + return (new Prefs).get('locale').then(data => { + const locale = data.data.data.attributes.data.replace('_', '-'); + + ffStore.setLocale(locale); + }).catch((err) => { + console.error('Could not load locale.') + console.log(err); + }); + }; + getDefaultCurrency().then(() => { getViewRange(); getListPageSize(); + getLocale(); }); } }) diff --git a/frontend/src/api/accounts/get.js b/frontend/src/api/accounts/get.js index e6cf5163fd..8270b4ecdb 100644 --- a/frontend/src/api/accounts/get.js +++ b/frontend/src/api/accounts/get.js @@ -33,7 +33,7 @@ export default class Get extends Api { */ get(identifier, date) { let params = {date: date}; - if(!date) { + if (!date) { return this.apiGet(identifier); } return this.apiGet(identifier, params); diff --git a/frontend/src/api/accounts/list.js b/frontend/src/api/accounts/list.js index 72b5f4e20b..28b7d5b41a 100644 --- a/frontend/src/api/accounts/list.js +++ b/frontend/src/api/accounts/list.js @@ -21,7 +21,7 @@ import {api} from "boot/axios"; import Api from "src/api/root/api"; -export default class List extends Api{ +export default class List extends Api { constructor() { super('accounts'); } diff --git a/frontend/src/api/authenticate/index.js b/frontend/src/api/authenticate/index.js index 43d5fb32ea..2335516928 100644 --- a/frontend/src/api/authenticate/index.js +++ b/frontend/src/api/authenticate/index.js @@ -20,7 +20,7 @@ import {api} from "boot/axios"; - export default class Authenticate { +export default class Authenticate { async authenticate() { return await api.get('/sanctum/csrf-cookie'); } diff --git a/frontend/src/api/categories/get.js b/frontend/src/api/categories/get.js index 765aec746f..a3fc6f2891 100644 --- a/frontend/src/api/categories/get.js +++ b/frontend/src/api/categories/get.js @@ -23,12 +23,14 @@ import {api} from "boot/axios"; export default class Get { get(identifier) { let url = '/api/v1/categories/' + identifier; - return api.get(url); + return api.get(url); } + transactions(identifier, page, cacheKey) { let url = '/api/v1/categories/' + identifier + '/transactions'; return api.get(url, {params: {page: page, cache: cacheKey}}); } + transactionsWithoutCategory(page, cacheKey) { let url = '/api/v1/categories/transactions-without-category'; return api.get(url, {params: {page: page, cache: cacheKey}}); diff --git a/frontend/src/api/currencies/get.js b/frontend/src/api/currencies/get.js index 107144b51d..ebce1424c6 100644 --- a/frontend/src/api/currencies/get.js +++ b/frontend/src/api/currencies/get.js @@ -23,8 +23,9 @@ import {api} from "boot/axios"; export default class Get { get(identifier) { let url = '/api/v1/currencies/' + identifier; - return api.get(url); + return api.get(url); } + transactions(identifier, page, cacheKey) { let url = '/api/v1/currencies/' + identifier + '/transactions'; return api.get(url, {params: {page: page, cache: cacheKey}}); diff --git a/frontend/src/api/currencies/index.js b/frontend/src/api/currencies/index.js index bcc528de2b..86c8c916e9 100644 --- a/frontend/src/api/currencies/index.js +++ b/frontend/src/api/currencies/index.js @@ -20,9 +20,12 @@ import {api} from "boot/axios"; import Authenticate from '../authenticate/index'; + export default class Currencies { default() { let auth = new Authenticate(); - return auth.authenticate().then(() => {return api.get('/api/v1/currencies/default')}); + return auth.authenticate().then(() => { + return api.get('/api/v1/currencies/default') + }); } } diff --git a/frontend/src/api/currencies/post.js b/frontend/src/api/currencies/post.js index 689d72c571..063e99c502 100644 --- a/frontend/src/api/currencies/post.js +++ b/frontend/src/api/currencies/post.js @@ -25,6 +25,7 @@ export default class Post { let url = '/api/v1/currencies'; return api.post(url, submission); } + makeDefault(currency) { let url = '/api/v1/currencies/' + currency + '/default'; return api.post(url); diff --git a/frontend/src/api/piggy-banks/get.js b/frontend/src/api/piggy-banks/get.js index d12c88609f..fa3271f5d6 100644 --- a/frontend/src/api/piggy-banks/get.js +++ b/frontend/src/api/piggy-banks/get.js @@ -23,8 +23,9 @@ import {api} from "boot/axios"; export default class Get { get(identifier) { let url = '/api/v1/piggy_banks/' + identifier; - return api.get(url); + return api.get(url); } + transactions(identifier, page, cacheKey) { let url = '/api/v1/piggy_banks/' + identifier + '/transactions'; return api.get(url, {params: {page: page, cache: cacheKey}}); diff --git a/frontend/src/api/preferences/index.js b/frontend/src/api/preferences/index.js index 4121d77636..fac50967d5 100644 --- a/frontend/src/api/preferences/index.js +++ b/frontend/src/api/preferences/index.js @@ -24,6 +24,7 @@ export default class Preferences { getByName(name) { return api.get('/api/v1/preferences/' + name); } + postByName(name, value) { return api.post('/api/v1/preferences', {name: name, data: value}); } diff --git a/frontend/src/api/recurring/get.js b/frontend/src/api/recurring/get.js index f1a05daf97..d08f98d99b 100644 --- a/frontend/src/api/recurring/get.js +++ b/frontend/src/api/recurring/get.js @@ -23,6 +23,6 @@ import {api} from "boot/axios"; export default class Get { get(identifier) { let url = '/api/v1/recurrences/' + identifier; - return api.get(url); + return api.get(url); } } diff --git a/frontend/src/api/rule-groups/get.js b/frontend/src/api/rule-groups/get.js index 7fe8793f9e..b63ba19027 100644 --- a/frontend/src/api/rule-groups/get.js +++ b/frontend/src/api/rule-groups/get.js @@ -23,11 +23,12 @@ import {api} from "boot/axios"; export default class Get { get(identifier, date) { let url = '/api/v1/rule_groups/' + identifier; - if(!date) { + if (!date) { return api.get(url); } return api.get(url, {params: {date: date}}); } + rules(identifier, page, cacheKey) { let url = '/api/v1/rule_groups/' + identifier + '/rules'; return api.get(url, {params: {page: page, cache: cacheKey}}); diff --git a/frontend/src/api/rules/get.js b/frontend/src/api/rules/get.js index 29e80b2474..98f6bc77b6 100644 --- a/frontend/src/api/rules/get.js +++ b/frontend/src/api/rules/get.js @@ -23,7 +23,7 @@ import {api} from "boot/axios"; export default class Get { get(identifier, date) { let url = '/api/v1/rules/' + identifier; - if(!date) { + if (!date) { return api.get(url); } return api.get(url, {params: {date: date}}); diff --git a/frontend/src/api/subscriptions/get.js b/frontend/src/api/subscriptions/get.js index 2d0ef000cf..66759dd199 100644 --- a/frontend/src/api/subscriptions/get.js +++ b/frontend/src/api/subscriptions/get.js @@ -25,6 +25,7 @@ export default class Get { let url = '/api/v1/bills/' + identifier; return api.get(url); } + transactions(identifier, page, cacheKey) { let url = '/api/v1/bills/' + identifier + '/transactions'; return api.get(url, {params: {page: page, cache: cacheKey}}); diff --git a/frontend/src/api/system/about.js b/frontend/src/api/system/about.js index e895bf64bf..3f8d10ce74 100644 --- a/frontend/src/api/system/about.js +++ b/frontend/src/api/system/about.js @@ -22,7 +22,7 @@ import {api} from "boot/axios"; //import createAuthRefreshInterceptor from 'axios-auth-refresh'; export default class About { - list() { - return api.get('/api/v1/about'); - } + list() { + return api.get('/api/v1/about'); + } } diff --git a/frontend/src/api/system/configuration.js b/frontend/src/api/system/configuration.js index e57913ea55..4161f0294c 100644 --- a/frontend/src/api/system/configuration.js +++ b/frontend/src/api/system/configuration.js @@ -1,4 +1,3 @@ - /* * configuration.js * Copyright (c) 2022 james@firefly-iii.org @@ -22,11 +21,11 @@ import {api} from "boot/axios"; export default class Configuration { - get (identifier) { + get(identifier) { return api.get('/api/v1/configuration/' + identifier); } - put (identifier, value) { + put(identifier, value) { return api.put('/api/v1/configuration/' + identifier, value); } } diff --git a/frontend/src/api/tags/get.js b/frontend/src/api/tags/get.js index 1825f1aec3..90939638e2 100644 --- a/frontend/src/api/tags/get.js +++ b/frontend/src/api/tags/get.js @@ -25,6 +25,7 @@ export default class Get { let url = '/api/v1/tags/' + identifier; return api.get(url); } + transactions(identifier, page, cacheKey) { let url = '/api/v1/tags/' + identifier + '/transactions'; return api.get(url, {params: {page: page, cache: cacheKey}}); diff --git a/frontend/src/api/v2/accounts/get.js b/frontend/src/api/v2/accounts/get.js new file mode 100644 index 0000000000..16d4cecfed --- /dev/null +++ b/frontend/src/api/v2/accounts/get.js @@ -0,0 +1,48 @@ +/* + * get.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import Api from "src/api/v2/root/api"; + +export default class Get extends Api { + constructor() { + super('accounts'); // call the super class constructor and pass in the name parameter + } + + /** + * + * @param identifier + * @param date + * @returns {Promise>} + */ + get(identifier, date) { + let params = {date: date}; + if (!date) { + return this.apiGet(identifier); + } + return this.apiGet(identifier, params); + } + + transactions(identifier, params) { + if (!params) { + return this.apiGetTransactions(identifier); + } + return this.apiGetTransactions(identifier, params); + } +} diff --git a/frontend/src/api/v2/bills/sum.js b/frontend/src/api/v2/bills/sum.js new file mode 100644 index 0000000000..ad0171424e --- /dev/null +++ b/frontend/src/api/v2/bills/sum.js @@ -0,0 +1,38 @@ +/* + * list.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; +import {format} from "date-fns"; + +export default class Sum { + unpaid(start, end) { + let url = 'api/v2/bills/sum/unpaid'; + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get(url, {params: {start: startStr, end: endStr}}); + } + + paid(start, end) { + let url = 'api/v2/bills/sum/paid'; + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get(url, {params: {start: startStr, end: endStr}}); + } +} diff --git a/frontend/src/api/v2/budget-limits/list.js b/frontend/src/api/v2/budget-limits/list.js new file mode 100644 index 0000000000..ebfd951302 --- /dev/null +++ b/frontend/src/api/v2/budget-limits/list.js @@ -0,0 +1,31 @@ +/* + * list.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; +import {format} from "date-fns"; + +export default class List { + list(budget, start, end, page) { + let url = '/api/v2/budgets/' + budget + '/limits'; + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get(url, {params: {page: page, start: startStr, end: endStr}}); + } +} diff --git a/frontend/src/api/v2/budgets/list.js b/frontend/src/api/v2/budgets/list.js new file mode 100644 index 0000000000..122c817e98 --- /dev/null +++ b/frontend/src/api/v2/budgets/list.js @@ -0,0 +1,28 @@ +/* + * list.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; + +export default class List { + list(page) { + let url = '/api/v2/budgets'; + return api.get(url, {params: {page: page}}); + } +} diff --git a/frontend/src/api/v2/budgets/sum.js b/frontend/src/api/v2/budgets/sum.js new file mode 100644 index 0000000000..926004bf5c --- /dev/null +++ b/frontend/src/api/v2/budgets/sum.js @@ -0,0 +1,38 @@ +/* + * list.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; +import {format} from "date-fns"; + +export default class Sum { + budgeted(start, end) { + let url = 'api/v2/budgets/sum/budgeted'; + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get(url, {params: {start: startStr, end: endStr}}); + } + + spent(start, end) { + let url = 'api/v2/budgets/sum/spent'; + let startStr = format(start, 'y-MM-dd'); + let endStr = format(end, 'y-MM-dd'); + return api.get(url, {params: {start: startStr, end: endStr}}); + } +} diff --git a/frontend/src/api/v2/chart/account/dashboard.js b/frontend/src/api/v2/chart/account/dashboard.js new file mode 100644 index 0000000000..c131ff2ae9 --- /dev/null +++ b/frontend/src/api/v2/chart/account/dashboard.js @@ -0,0 +1,30 @@ +/* + * overview.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; +import {format} from "date-fns"; + +export default class Dashboard { + overview(range, cacheKey) { + let startStr = format(range.start, 'y-MM-dd'); + let endStr = format(range.end, 'y-MM-dd'); + return api.get('/api/v2/chart/account/dashboard', {params: {start: startStr, end: endStr, cache: cacheKey}}); + } +} diff --git a/frontend/src/api/v2/net-worth/index.js b/frontend/src/api/v2/net-worth/index.js new file mode 100644 index 0000000000..6037ee45a2 --- /dev/null +++ b/frontend/src/api/v2/net-worth/index.js @@ -0,0 +1,29 @@ +/* + * basic.js + * Copyright (c) 2021 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; +import {format} from "date-fns"; + +export default class NetWorth { + get(date) { + let dateStr = format(date, 'y-MM-dd'); + return api.get('/api/v2/net-worth', {params: {date: dateStr}}); + } +} diff --git a/frontend/src/api/v2/preferences/index.js b/frontend/src/api/v2/preferences/index.js new file mode 100644 index 0000000000..4e5e9e5951 --- /dev/null +++ b/frontend/src/api/v2/preferences/index.js @@ -0,0 +1,31 @@ +/* + * basic.js + * Copyright (c) 2021 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; + +export default class Preferences { + get(name) { + return api.get('/api/v2/preferences/' + name); + } + + // postByName(name, value) { + // return api.post('/api/v1/preferences', {name: name, data: value}); + // } +} diff --git a/frontend/src/api/v2/root/api.js b/frontend/src/api/v2/root/api.js new file mode 100644 index 0000000000..1ab35799e3 --- /dev/null +++ b/frontend/src/api/v2/root/api.js @@ -0,0 +1,69 @@ +/* + * api.js + * Copyright (c) 2022 james@firefly-iii.org + * + * This file is part of Firefly III (https://github.com/firefly-iii). + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import {api} from "boot/axios"; + +/** + * + */ +export default class Api { + root = '/api/v2/'; + path = ''; + + constructor(path) { + this.path = path; + } + + apiPath() { + return this.root + this.path; + } + + apiPathWithObject(object) { + return this.root + this.path + '/' + object; + } + + /** + * + * @param object + * @param params + * @returns {Promise>} + */ + apiGet(object, params) { + let url = this.apiPathWithObject(object); + if (params) { + return api.get(url, {params: params}); + } + return api.get(url); + } + + /** + * + * @param object + * @param params + * @returns {Promise>} + */ + apiGetTransactions(object, params) { + let url = this.apiPathWithObject(object) + '/transactions'; + if (params) { + return api.get(url, {params: params}); + } + return api.get(url); + } +} diff --git a/frontend/src/boot/axios.js b/frontend/src/boot/axios.js index 37e2ffc6be..6cc571832e 100644 --- a/frontend/src/boot/axios.js +++ b/frontend/src/boot/axios.js @@ -23,9 +23,9 @@ import axios from 'axios' import {setupCache} from 'axios-cache-adapter' const cache = setupCache({ - maxAge: 15 * 60 * 1000, - exclude: { query: false } - }) + maxAge: 15 * 60 * 1000, + exclude: {query: false} +}) // Be careful when using SSR for cross-request state pollution // due to creating a Singleton instance here; diff --git a/frontend/src/boot/i18n.js b/frontend/src/boot/i18n.js index 9d105e14bd..d28f99d44b 100644 --- a/frontend/src/boot/i18n.js +++ b/frontend/src/boot/i18n.js @@ -18,11 +18,11 @@ * along with this program. If not, see . */ -import { boot } from 'quasar/wrappers' -import { createI18n } from 'vue-i18n' +import {boot} from 'quasar/wrappers' +import {createI18n} from 'vue-i18n' import messages from 'src/i18n' -export default boot(({ app }) => { +export default boot(({app}) => { const i18n = createI18n({ locale: 'en-US', messages diff --git a/frontend/src/components/Alert.vue b/frontend/src/components/Alert.vue index 970e43794b..8523990715 100644 --- a/frontend/src/components/Alert.vue +++ b/frontend/src/components/Alert.vue @@ -19,14 +19,14 @@ --> diff --git a/frontend/src/components/DateRange.vue b/frontend/src/components/DateRange.vue index d963a048f5..86fd499585 100644 --- a/frontend/src/components/DateRange.vue +++ b/frontend/src/components/DateRange.vue @@ -22,14 +22,15 @@
- +
- - + + - + {{ $t('firefly.pref_' + choice.value) }} @@ -40,60 +41,17 @@ + + diff --git a/frontend/src/components/dashboard/BillInsightBox.vue b/frontend/src/components/dashboard/BillInsightBox.vue new file mode 100644 index 0000000000..f1fe7b7c48 --- /dev/null +++ b/frontend/src/components/dashboard/BillInsightBox.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/frontend/src/components/dashboard/BudgetBox.vue b/frontend/src/components/dashboard/BudgetBox.vue new file mode 100644 index 0000000000..9be3af1705 --- /dev/null +++ b/frontend/src/components/dashboard/BudgetBox.vue @@ -0,0 +1,174 @@ + + + + + + + diff --git a/frontend/src/components/dashboard/NetWorthInsightBox.vue b/frontend/src/components/dashboard/NetWorthInsightBox.vue new file mode 100644 index 0000000000..5cbf393251 --- /dev/null +++ b/frontend/src/components/dashboard/NetWorthInsightBox.vue @@ -0,0 +1,136 @@ + + + + + + + diff --git a/frontend/src/components/dashboard/NewUser.vue b/frontend/src/components/dashboard/NewUser.vue index 7dd1283e2c..c3cde7a446 100644 --- a/frontend/src/components/dashboard/NewUser.vue +++ b/frontend/src/components/dashboard/NewUser.vue @@ -21,7 +21,7 @@