diff --git a/.ci/php-cs-fixer/composer.lock b/.ci/php-cs-fixer/composer.lock index 0ad960ff0b..8706691e71 100644 --- a/.ci/php-cs-fixer/composer.lock +++ b/.ci/php-cs-fixer/composer.lock @@ -79,16 +79,16 @@ }, { "name": "composer/semver", - "version": "3.3.2", + "version": "3.4.0", "source": { "type": "git", "url": "https://github.com/composer/semver.git", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9" + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/semver/zipball/3953f23262f2bff1919fc82183ad9acb13ff62c9", - "reference": "3953f23262f2bff1919fc82183ad9acb13ff62c9", + "url": "https://api.github.com/repos/composer/semver/zipball/35e8d0af4486141bc745f23a29cc2091eb624a32", + "reference": "35e8d0af4486141bc745f23a29cc2091eb624a32", "shasum": "" }, "require": { @@ -138,9 +138,9 @@ "versioning" ], "support": { - "irc": "irc://irc.freenode.org/composer", + "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/semver/issues", - "source": "https://github.com/composer/semver/tree/3.3.2" + "source": "https://github.com/composer/semver/tree/3.4.0" }, "funding": [ { @@ -156,7 +156,7 @@ "type": "tidelift" } ], - "time": "2022-04-01T19:23:25+00:00" + "time": "2023-08-31T09:50:34+00:00" }, { "name": "composer/xdebug-handler", @@ -224,178 +224,23 @@ ], "time": "2022-02-25T21:32:43+00:00" }, - { - "name": "doctrine/annotations", - "version": "2.0.1", - "source": { - "type": "git", - "url": "https://github.com/doctrine/annotations.git", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/annotations/zipball/e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "reference": "e157ef3f3124bbf6fe7ce0ffd109e8a8ef284e7f", - "shasum": "" - }, - "require": { - "doctrine/lexer": "^2 || ^3", - "ext-tokenizer": "*", - "php": "^7.2 || ^8.0", - "psr/cache": "^1 || ^2 || ^3" - }, - "require-dev": { - "doctrine/cache": "^2.0", - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.8.0", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "symfony/cache": "^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/2.0.1" - }, - "time": "2023-02-02T22:02:53+00:00" - }, - { - "name": "doctrine/lexer", - "version": "3.0.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/lexer.git", - "reference": "84a527db05647743d50373e0ec53a152f2cde568" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/lexer/zipball/84a527db05647743d50373e0ec53a152f2cde568", - "reference": "84a527db05647743d50373e0ec53a152f2cde568", - "shasum": "" - }, - "require": { - "php": "^8.1" - }, - "require-dev": { - "doctrine/coding-standard": "^10", - "phpstan/phpstan": "^1.9", - "phpunit/phpunit": "^9.5", - "psalm/plugin-phpunit": "^0.18.3", - "vimeo/psalm": "^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/3.0.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-15T16:57:16+00:00" - }, { "name": "friendsofphp/php-cs-fixer", - "version": "v3.22.0", + "version": "v3.25.0", "source": { "type": "git", "url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git", - "reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3" + "reference": "9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/92b019f6c8d79aa26349d0db7671d37440dc0ff3", - "reference": "92b019f6c8d79aa26349d0db7671d37440dc0ff3", + "url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d", + "reference": "9025b7d2b6e1d90a63d0ac0905018ce5d03ec88d", "shasum": "" }, "require": { "composer/semver": "^3.3", "composer/xdebug-handler": "^3.0.3", - "doctrine/annotations": "^2", - "doctrine/lexer": "^2 || ^3", "ext-json": "*", "ext-tokenizer": "*", "php": "^7.4 || ^8.0", @@ -464,7 +309,7 @@ ], "support": { "issues": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/issues", - "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.22.0" + "source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.25.0" }, "funding": [ { @@ -472,56 +317,7 @@ "type": "github" } ], - "time": "2023-07-16T23:08:06+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" + "time": "2023-08-31T21:27:18+00:00" }, { "name": "psr/container", @@ -745,16 +541,16 @@ }, { "name": "symfony/console", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898" + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/aa5d64ad3f63f2e48964fc81ee45cb318a723898", - "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898", + "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", "shasum": "" }, "require": { @@ -815,7 +611,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.2" + "source": "https://github.com/symfony/console/tree/v6.3.4" }, "funding": [ { @@ -831,7 +627,7 @@ "type": "tidelift" } ], - "time": "2023-07-19T20:17:28+00:00" + "time": "2023-08-16T10:10:12+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1252,16 +1048,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { @@ -1276,7 +1072,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1314,7 +1110,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, "funding": [ { @@ -1330,20 +1126,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + "reference": "875e90aeea2777b6f135677f618529449334a612" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", "shasum": "" }, "require": { @@ -1355,7 +1151,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1395,7 +1191,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" }, "funding": [ { @@ -1411,20 +1207,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { @@ -1436,7 +1232,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1479,7 +1275,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" }, "funding": [ { @@ -1495,20 +1291,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { @@ -1523,7 +1319,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1562,7 +1358,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -1578,20 +1374,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "shasum": "" }, "require": { @@ -1600,7 +1396,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1645,7 +1441,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" }, "funding": [ { @@ -1661,20 +1457,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php81", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php81.git", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a" + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a", - "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a", + "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/7581cd600fa9fd681b797d00b02f068e2f13263b", + "reference": "7581cd600fa9fd681b797d00b02f068e2f13263b", "shasum": "" }, "require": { @@ -1683,7 +1479,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -1724,7 +1520,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php81/tree/v1.28.0" }, "funding": [ { @@ -1740,20 +1536,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/process", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d" + "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d", - "reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d", + "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", + "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", "shasum": "" }, "require": { @@ -1785,7 +1581,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.3.2" + "source": "https://github.com/symfony/process/tree/v6.3.4" }, "funding": [ { @@ -1801,7 +1597,7 @@ "type": "tidelift" } ], - "time": "2023-07-12T16:00:22+00:00" + "time": "2023-08-07T10:39:22+00:00" }, { "name": "symfony/service-contracts", diff --git a/.env.example b/.env.example index 246385673d..ec2b4a8762 100644 --- a/.env.example +++ b/.env.example @@ -45,12 +45,6 @@ TRUSTED_PROXIES= # Default setting 'stack' will log to 'daily' and to 'stdout' at the same time. LOG_CHANNEL=stack -# -# Used when logging to papertrail: -# -PAPERTRAIL_HOST= -PAPERTRAIL_PORT= - # Log level. You can set this from least severe to most severe: # debug, info, notice, warning, error, critical, alert, emergency # If you set it to debug your logs will grow large, and fast. If you set it to emergency probably @@ -58,8 +52,30 @@ PAPERTRAIL_PORT= APP_LOG_LEVEL=notice # Audit log level. -# Set this to "emergency" if you dont want to store audit logs, leave on info otherwise. -AUDIT_LOG_LEVEL=info +# The audit log is used to log notable Firefly III events on a separate channel. +# These log entries may contain sensitive financial information. +# The audit log is disabled by default. +# +# To enable it, set AUDIT_LOG_LEVEL to "info" +# To disable it, set AUDIT_LOG_LEVEL to "emergency" +AUDIT_LOG_LEVEL=emergency + +# +# If you want, you can redirect the audit logs to another channel. +# Set 'audit_stdout', 'audit_syslog', 'audit_errorlog' to log to the system itself. +# Use audit_daily to log to a rotating file. +# Use audit_papertrail to log to papertrail. +# +# If you do this, the audit logs may be mixed with normal logs because the settings for these channels +# are often the same as the settings for the normal logs. +AUDIT_LOG_CHANNEL= + +# +# Used when logging to papertrail: +# Also used when audit logs log to papertrail: +# +PAPERTRAIL_HOST= +PAPERTRAIL_PORT= # Database credentials. Make sure the database exists. I recommend a dedicated user for Firefly III # For other database types, please see the FAQ: https://docs.firefly-iii.org/firefly-iii/faq/self-hosted/#i-want-to-use-sqlite diff --git a/app/Api/V1/Controllers/Controller.php b/app/Api/V1/Controllers/Controller.php index e3cb350469..8740fb7c08 100644 --- a/app/Api/V1/Controllers/Controller.php +++ b/app/Api/V1/Controllers/Controller.php @@ -102,6 +102,7 @@ abstract class Controller extends BaseController } catch (BadRequestException $e) { Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field)); Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); $value = null; } $obj = null; @@ -130,6 +131,7 @@ abstract class Controller extends BaseController } catch (BadRequestException $e) { Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $integer)); Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); $value = null; } if (null !== $value) { @@ -154,6 +156,7 @@ abstract class Controller extends BaseController } catch (BadRequestException $e) { Log::error('Request field "sort" contains a non-scalar value. Value set to NULL.'); Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); $param = ''; } if ('' === $param) { diff --git a/app/Api/V2/Controllers/Controller.php b/app/Api/V2/Controllers/Controller.php index 72c7975473..1843ea2d9a 100644 --- a/app/Api/V2/Controllers/Controller.php +++ b/app/Api/V2/Controllers/Controller.php @@ -99,6 +99,7 @@ class Controller extends BaseController } catch (BadRequestException $e) { Log::error(sprintf('Request field "%s" contains a non-scalar value. Value set to NULL.', $field)); Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); } if (null !== $date) { try { diff --git a/app/Api/V2/Controllers/Model/Transaction/StoreController.php b/app/Api/V2/Controllers/Model/Transaction/StoreController.php new file mode 100644 index 0000000000..2b0982ff2e --- /dev/null +++ b/app/Api/V2/Controllers/Model/Transaction/StoreController.php @@ -0,0 +1,45 @@ +. + */ + +namespace FireflyIII\Api\V2\Controllers\Model\Transaction; + +use FireflyIII\Api\V2\Controllers\Controller; +use Illuminate\Http\JsonResponse; + +/** + * Class StoreController + */ +class StoreController extends Controller +{ + /** + * @return JsonResponse + */ + public function post(): JsonResponse + { + + return response()->json([]); + + } + + +} diff --git a/app/Api/V2/Controllers/Summary/BasicController.php b/app/Api/V2/Controllers/Summary/BasicController.php index 1a90507289..35b82e13fa 100644 --- a/app/Api/V2/Controllers/Summary/BasicController.php +++ b/app/Api/V2/Controllers/Summary/BasicController.php @@ -105,10 +105,6 @@ class BasicController extends Controller $end = $this->parameters->get('end'); // balance information: - $balanceData = []; - $billData = []; - $spentData = []; - $netWorthData = []; $balanceData = $this->getBalanceInformation($start, $end); $billData = $this->getBillInformation($start, $end); $spentData = $this->getLeftToSpendInfo($start, $end); @@ -127,9 +123,15 @@ class BasicController extends Controller private function getBalanceInformation(Carbon $start, Carbon $end): array { // prep some arrays: - $incomes = []; - $expenses = []; - $sums = []; + $incomes = [ + 'native' => '0', + ]; + $expenses = [ + 'native' => '0', + ]; + $sums = [ + 'native' => '0', + ]; $return = []; $currencies = []; $converter = new ExchangeRateConverter(); @@ -354,6 +356,7 @@ class BasicController extends Controller */ private function getLeftToSpendInfo(Carbon $start, Carbon $end): array { + app('log')->debug('Now in getLeftToSpendInfo'); $return = []; $today = today(config('app.timezone')); $available = $this->abRepository->getAvailableBudgetWithCurrency($start, $end); @@ -367,7 +370,7 @@ class BasicController extends Controller $nativeLeft = [ 'key' => 'left-to-spend-in-native', 'value' => '0', - 'currency_id' => (int)$default->id, + 'currency_id' => (string)$default->id, 'currency_code' => $default->code, 'currency_symbol' => $default->symbol, 'currency_decimal_places' => (int)$default->decimal_places, @@ -375,7 +378,7 @@ class BasicController extends Controller $nativePerDay = [ 'key' => 'left-per-day-to-spend-in-native', 'value' => '0', - 'currency_id' => (int)$default->id, + 'currency_id' => (string)$default->id, 'currency_code' => $default->code, 'currency_symbol' => $default->symbol, 'currency_decimal_places' => (int)$default->decimal_places, @@ -386,17 +389,20 @@ class BasicController extends Controller * @var array $row */ foreach ($spent as $currencyId => $row) { + app('log')->debug(sprintf('Processing spent array in currency #%d', $currencyId)); + $currencyId = (int)$currencyId; $spent = '0'; $spentNative = '0'; // get the sum from the array of transactions (double loop but who cares) /** @var array $budget */ foreach ($row['budgets'] as $budget) { + app('log')->debug(sprintf('Processing expenses in budget "%s".', $budget['name'])); /** @var array $journal */ foreach ($budget['transaction_journals'] as $journal) { $journalCurrencyId = $journal['currency_id']; $currency = $currencies[$journalCurrencyId] ?? $this->currencyRepos->find($journalCurrencyId); $currencies[$currencyId] = $currency; - $amount = bcmul($journal['amount'], '-1'); + $amount = app('steam')->negative($journal['amount']); $amountNative = $converter->convert($default, $currency, $start, $amount); if ((int)$journal['foreign_currency_id'] === (int)$default->id) { $amountNative = $journal['foreign_amount']; @@ -404,15 +410,18 @@ class BasicController extends Controller $spent = bcadd($spent, $amount); $spentNative = bcadd($spentNative, $amountNative); } + app('log')->debug(sprintf('Total spent in budget "%s" is %s', $budget['name'], $spent)); } // either an amount was budgeted or 0 is available. $currency = $currencies[$currencyId] ?? $this->currencyRepos->find($currencyId); $currencies[$currencyId] = $currency; $amount = $available[$currencyId]['amount'] ?? '0'; - $amountNative = $converter->convert($default, $currency, $start, $amount); + $amountNative = $available[$currencyId]['native_amount'] ?? '0'; $left = bcadd($amount, $spent); $leftNative = bcadd($amountNative, $spentNative); + app('log')->debug(sprintf('Available amount is %s', $amount)); + app('log')->debug(sprintf('Amount left is %s', $left)); // how much left per day? $days = $today->diffInDays($end) + 1; @@ -429,10 +438,10 @@ class BasicController extends Controller $return[] = [ 'key' => sprintf('left-to-spend-in-%s', $row['currency_code']), 'value' => $left, - 'currency_id' => $row['currency_id'], + 'currency_id' => (string)$row['currency_id'], 'currency_code' => $row['currency_code'], 'currency_symbol' => $row['currency_symbol'], - 'currency_decimal_places' => $row['currency_decimal_places'], + 'currency_decimal_places' => (int)$row['currency_decimal_places'], ]; // left (native) $nativeLeft['value'] = $leftNative; @@ -441,10 +450,10 @@ class BasicController extends Controller $return[] = [ 'key' => sprintf('left-per-day-to-spend-in-%s', $row['currency_code']), 'value' => $perDay, - 'currency_id' => $row['currency_id'], + 'currency_id' => (string)$row['currency_id'], 'currency_code' => $row['currency_code'], 'currency_symbol' => $row['currency_symbol'], - 'currency_decimal_places' => $row['currency_decimal_places'], + 'currency_decimal_places' => (int)$row['currency_decimal_places'], ]; // left per day (native) diff --git a/app/Api/V2/Request/Chart/BalanceChartRequest.php b/app/Api/V2/Request/Chart/BalanceChartRequest.php index f7003d967e..c9c0087f06 100644 --- a/app/Api/V2/Request/Chart/BalanceChartRequest.php +++ b/app/Api/V2/Request/Chart/BalanceChartRequest.php @@ -42,7 +42,7 @@ class BalanceChartRequest extends FormRequest { return [ 'accounts' => $this->getAccountList(), - 'period' => $this->string('period'), + 'period' => $this->convertString('period'), ]; } diff --git a/app/Console/Commands/Correction/CorrectAmounts.php b/app/Console/Commands/Correction/CorrectAmounts.php index c2d53cd097..a35b941aaa 100644 --- a/app/Console/Commands/Correction/CorrectAmounts.php +++ b/app/Console/Commands/Correction/CorrectAmounts.php @@ -34,6 +34,7 @@ use FireflyIII\Models\PiggyBankRepetition; use FireflyIII\Models\RecurrenceTransaction; use FireflyIII\Models\RuleTrigger; use Illuminate\Console\Command; +use ValueError; /** * Class ReportSkeleton @@ -247,7 +248,16 @@ class CorrectAmounts extends Command /** @var RuleTrigger $item */ foreach ($set as $item) { // basic check: - if (-1 === bccomp((string)$item->trigger_value, '0')) { + $check = 0; + try { + $check = bccomp((string)$item->trigger_value, '0'); + } catch (ValueError $e) { + $this->friendlyError(sprintf('Rule #%d contained invalid %s-trigger "%s". The trigger has been removed, and the rule is disabled.', $item->rule_id, $item->trigger_type, $item->trigger_value)); + $item->rule->active = false; + $item->rule->save(); + $item->forceDelete(); + } + if (-1 === $check) { $fixed++; $item->trigger_value = app('steam')->positive((string)$item->trigger_value); $item->save(); diff --git a/app/Console/Commands/Correction/DeleteEmptyJournals.php b/app/Console/Commands/Correction/DeleteEmptyJournals.php index 887533667a..3ed726205c 100644 --- a/app/Console/Commands/Correction/DeleteEmptyJournals.php +++ b/app/Console/Commands/Correction/DeleteEmptyJournals.php @@ -82,6 +82,7 @@ class DeleteEmptyJournals extends Command TransactionJournal::find((int)$row->transaction_journal_id)->delete(); } catch (QueryException $e) { Log::info(sprintf('Could not delete journal: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); } @@ -113,6 +114,7 @@ class DeleteEmptyJournals extends Command TransactionJournal::find($entry->id)->delete(); } catch (QueryException $e) { Log::info(sprintf('Could not delete entry: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); } diff --git a/app/Events/Model/Rule/RuleActionFailedOnArray.php b/app/Events/Model/Rule/RuleActionFailedOnArray.php new file mode 100644 index 0000000000..dc7cc0cb55 --- /dev/null +++ b/app/Events/Model/Rule/RuleActionFailedOnArray.php @@ -0,0 +1,52 @@ +. + */ + +namespace FireflyIII\Events\Model\Rule; + +use FireflyIII\Models\RuleAction; +use Illuminate\Queue\SerializesModels; + +/** + * Class RuleActionFailedOnArray + */ +class RuleActionFailedOnArray +{ + use SerializesModels; + + public string $error; + public array $journal; + public RuleAction $ruleAction; + + /** + * @param RuleAction $ruleAction + * @param array $journal + * @param string $error + */ + public function __construct(RuleAction $ruleAction, array $journal, string $error) + { + app('log')->debug('Created new RuleActionFailedOnArray'); + $this->ruleAction = $ruleAction; + $this->journal = $journal; + $this->error = $error; + } +} diff --git a/app/Events/Model/Rule/RuleActionFailedOnObject.php b/app/Events/Model/Rule/RuleActionFailedOnObject.php new file mode 100644 index 0000000000..ffb8d45da9 --- /dev/null +++ b/app/Events/Model/Rule/RuleActionFailedOnObject.php @@ -0,0 +1,53 @@ +. + */ + +namespace FireflyIII\Events\Model\Rule; + +use FireflyIII\Models\RuleAction; +use FireflyIII\Models\TransactionJournal; +use Illuminate\Queue\SerializesModels; + +/** + * Class RuleActionFailedOnObject + */ +class RuleActionFailedOnObject +{ + use SerializesModels; + + public string $error; + public TransactionJournal $journal; + public RuleAction $ruleAction; + + /** + * @param RuleAction $ruleAction + * @param TransactionJournal $journal + * @param string $error + */ + public function __construct(RuleAction $ruleAction, TransactionJournal $journal, string $error) + { + app('log')->debug('Created new RuleActionFailedOnObject'); + $this->ruleAction = $ruleAction; + $this->journal = $journal; + $this->error = $error; + } +} diff --git a/app/Factory/AccountFactory.php b/app/Factory/AccountFactory.php index 82519e0eff..080da2d31b 100644 --- a/app/Factory/AccountFactory.php +++ b/app/Factory/AccountFactory.php @@ -218,6 +218,7 @@ class AccountFactory } // create account! $account = Account::create($databaseData); + Log::channel('audit')->info(sprintf('Account #%d ("%s") has been created.', $account->id, $account->name)); // update meta data: $data = $this->cleanMetaDataArray($account, $data); @@ -228,6 +229,7 @@ class AccountFactory $this->storeOpeningBalance($account, $data); } catch (FireflyException $e) { Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); } // create credit liability data (only liabilities) @@ -235,6 +237,7 @@ class AccountFactory $this->storeCreditLiability($account, $data); } catch (FireflyException $e) { Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); } // create notes diff --git a/app/Factory/AccountMetaFactory.php b/app/Factory/AccountMetaFactory.php index 46f1d013b1..e92b88a6cc 100644 --- a/app/Factory/AccountMetaFactory.php +++ b/app/Factory/AccountMetaFactory.php @@ -26,6 +26,7 @@ namespace FireflyIII\Factory; use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; +use Illuminate\Support\Facades\Log; /** * Class AccountMetaFactory diff --git a/app/Factory/CategoryFactory.php b/app/Factory/CategoryFactory.php index affe1abf52..e94ad3f50e 100644 --- a/app/Factory/CategoryFactory.php +++ b/app/Factory/CategoryFactory.php @@ -77,6 +77,7 @@ class CategoryFactory ); } catch (QueryException $e) { Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException('400003: Could not store new category.', 0, $e); } } diff --git a/app/Factory/RecurrenceFactory.php b/app/Factory/RecurrenceFactory.php index 6c5be3c1d3..a826b06a66 100644 --- a/app/Factory/RecurrenceFactory.php +++ b/app/Factory/RecurrenceFactory.php @@ -130,6 +130,7 @@ class RecurrenceFactory $this->createTransactions($recurrence, $data['transactions'] ?? []); } catch (FireflyException $e) { Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); $recurrence->forceDelete(); $message = sprintf('Could not create recurring transaction: %s', $e->getMessage()); $this->errors->add('store', $message); diff --git a/app/Factory/TransactionCurrencyFactory.php b/app/Factory/TransactionCurrencyFactory.php index 7d056ab1aa..f1d61b7e20 100644 --- a/app/Factory/TransactionCurrencyFactory.php +++ b/app/Factory/TransactionCurrencyFactory.php @@ -69,6 +69,7 @@ class TransactionCurrencyFactory } catch (QueryException $e) { $result = null; Log::error(sprintf('Could not create new currency: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); throw new FireflyException('400004: Could not store new currency.', 0, $e); } diff --git a/app/Factory/TransactionFactory.php b/app/Factory/TransactionFactory.php index 2a364528f9..cc63aa1fc0 100644 --- a/app/Factory/TransactionFactory.php +++ b/app/Factory/TransactionFactory.php @@ -110,7 +110,7 @@ class TransactionFactory Log::error(sprintf('Could not create transaction: %s', $e->getMessage()), $data); Log::error($e->getMessage()); Log::error($e->getTraceAsString()); - throw new FireflyException('Query exception when creating transaction.', 0, $e); + throw new FireflyException(sprintf('Query exception when creating transaction: %s', $e->getMessage()), 0, $e); } if (null === $result) { throw new FireflyException('Transaction is NULL.'); diff --git a/app/Generator/Report/Budget/MonthReportGenerator.php b/app/Generator/Report/Budget/MonthReportGenerator.php index 50ba4e8694..477c2e1f68 100644 --- a/app/Generator/Report/Budget/MonthReportGenerator.php +++ b/app/Generator/Report/Budget/MonthReportGenerator.php @@ -75,6 +75,7 @@ class MonthReportGenerator implements ReportGeneratorInterface ->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); } diff --git a/app/Generator/Report/Category/MonthReportGenerator.php b/app/Generator/Report/Category/MonthReportGenerator.php index eae5ee812b..b7ed3cd4e5 100644 --- a/app/Generator/Report/Category/MonthReportGenerator.php +++ b/app/Generator/Report/Category/MonthReportGenerator.php @@ -77,6 +77,7 @@ class MonthReportGenerator implements ReportGeneratorInterface ->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.category.month: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); } diff --git a/app/Generator/Report/Standard/MonthReportGenerator.php b/app/Generator/Report/Standard/MonthReportGenerator.php index 0161787a0c..a79956d9b1 100644 --- a/app/Generator/Report/Standard/MonthReportGenerator.php +++ b/app/Generator/Report/Standard/MonthReportGenerator.php @@ -59,6 +59,7 @@ class MonthReportGenerator implements ReportGeneratorInterface return view('reports.default.month', compact('accountIds', 'reportType'))->with('start', $this->start)->with('end', $this->end)->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.default.month: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render report view.'; throw new FireflyException($result, 0, $e); } diff --git a/app/Generator/Report/Standard/MultiYearReportGenerator.php b/app/Generator/Report/Standard/MultiYearReportGenerator.php index 177a578038..9647dfd555 100644 --- a/app/Generator/Report/Standard/MultiYearReportGenerator.php +++ b/app/Generator/Report/Standard/MultiYearReportGenerator.php @@ -63,6 +63,7 @@ class MultiYearReportGenerator implements ReportGeneratorInterface )->with('start', $this->start)->with('end', $this->end)->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.default.multi-year: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); } diff --git a/app/Generator/Report/Standard/YearReportGenerator.php b/app/Generator/Report/Standard/YearReportGenerator.php index 1d64e3b889..8cd9c768eb 100644 --- a/app/Generator/Report/Standard/YearReportGenerator.php +++ b/app/Generator/Report/Standard/YearReportGenerator.php @@ -63,6 +63,7 @@ class YearReportGenerator implements ReportGeneratorInterface )->with('start', $this->start)->with('end', $this->end)->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.account.report: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render report view.'; throw new FireflyException($result, 0, $e); } diff --git a/app/Generator/Report/Tag/MonthReportGenerator.php b/app/Generator/Report/Tag/MonthReportGenerator.php index 1ed38a8702..29ffb4ce91 100644 --- a/app/Generator/Report/Tag/MonthReportGenerator.php +++ b/app/Generator/Report/Tag/MonthReportGenerator.php @@ -71,6 +71,7 @@ class MonthReportGenerator implements ReportGeneratorInterface )->with('start', $this->start)->with('end', $this->end)->with('tags', $this->tags)->with('accounts', $this->accounts)->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render reports.tag.month: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = sprintf('Could not render report view: %s', $e->getMessage()); throw new FireflyException($result, 0, $e); } diff --git a/app/Generator/Webhook/StandardMessageGenerator.php b/app/Generator/Webhook/StandardMessageGenerator.php index a99192d310..f71c0a8ecb 100644 --- a/app/Generator/Webhook/StandardMessageGenerator.php +++ b/app/Generator/Webhook/StandardMessageGenerator.php @@ -174,6 +174,7 @@ class StandardMessageGenerator implements MessageGeneratorInterface Log::error( sprintf('The transformer could not include the requested transaction group for webhook #%d: %s', $webhook->id, $e->getMessage()) ); + Log::error($e->getTraceAsString()); return; } diff --git a/app/Handlers/Events/Model/BudgetLimitHandler.php b/app/Handlers/Events/Model/BudgetLimitHandler.php index e03058c385..d0e872dcb1 100644 --- a/app/Handlers/Events/Model/BudgetLimitHandler.php +++ b/app/Handlers/Events/Model/BudgetLimitHandler.php @@ -166,7 +166,7 @@ class BudgetLimitHandler $availableBudget->end_date->format('Y-m-d') ) ); - // have to recalc everything just in case. + // have to recalculate everything just in case. $set = $repository->getAllBudgetLimitsByCurrency($availableBudget->transactionCurrency, $availableBudget->start_date, $availableBudget->end_date); Log::debug(sprintf('Found %d interesting budget limit(s).', $set->count())); /** @var BudgetLimit $budgetLimit */ @@ -186,15 +186,18 @@ class BudgetLimitHandler precision : Precision::DAY(), boundaries: Boundaries::EXCLUDE_NONE() ); - // if both equal eachother, amount from this BL must be added to the AB + // if both equal each other, amount from this BL must be added to the AB if ($limitPeriod->equals($abPeriod)) { + app('log')->debug('This budget limit is equal to the available budget period.'); $newAmount = bcadd($newAmount, $budgetLimit->amount); } - // if budget limit period inside AB period, can be added in full. + // if budget limit period is inside AB period, it can be added in full. if (!$limitPeriod->equals($abPeriod) && $abPeriod->contains($limitPeriod)) { + app('log')->debug('This budget limit is smaller than the available budget period.'); $newAmount = bcadd($newAmount, $budgetLimit->amount); } - if (!$limitPeriod->equals($abPeriod) && $abPeriod->overlapsWith($limitPeriod)) { + if (!$limitPeriod->equals($abPeriod) && !$abPeriod->contains($limitPeriod) && $abPeriod->overlapsWith($limitPeriod)) { + app('log')->debug('This budget limit is something else entirely!'); $overlap = $abPeriod->overlap($limitPeriod); if (null !== $overlap) { $length = $overlap->length(); @@ -209,7 +212,7 @@ class BudgetLimitHandler return; } Log::debug(sprintf('Concluded new amount for this AB must be %s', $newAmount)); - $availableBudget->amount = $newAmount; + $availableBudget->amount = app('steam')->bcround($newAmount, $availableBudget->transactionCurrency->decimal_places); $availableBudget->save(); } diff --git a/app/Handlers/Events/Model/RuleHandler.php b/app/Handlers/Events/Model/RuleHandler.php new file mode 100644 index 0000000000..933c08b0eb --- /dev/null +++ b/app/Handlers/Events/Model/RuleHandler.php @@ -0,0 +1,95 @@ +. + */ + +namespace FireflyIII\Handlers\Events\Model; + +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject; +use FireflyIII\Notifications\User\RuleActionFailed; +use FireflyIII\Support\Facades\Preferences; +use Illuminate\Support\Facades\Notification; + +/** + * Class RuleHandler + */ +class RuleHandler +{ + /** + * @param RuleActionFailedOnArray $event + * + * @return void + */ + public function ruleActionFailedOnArray(RuleActionFailedOnArray $event): void + { + $ruleAction = $event->ruleAction; + $rule = $ruleAction->rule; + $preference = Preferences::getForUser($rule->user, 'notification_rule_action_failures', true)->data; + if (false === $preference) { + return; + } + app('log')->debug('Now in ruleActionFailedOnArray'); + $journal = $event->journal; + $error = $event->error; + $user = $ruleAction->rule->user; + + $mainMessage = trans('rules.main_message', ['rule' => $rule->title, 'action' => $ruleAction->action_type, 'group' => $journal['transaction_group_id'], 'error' => $error]); + $groupTitle = $journal['description'] ?? ''; + $groupLink = route('transactions.show', [$journal['transaction_group_id']]); + $ruleTitle = $rule->title; + $ruleLink = route('rules.edit', [$rule->id]); + $params = [$mainMessage, $groupTitle, $groupLink, $ruleTitle, $ruleLink]; + + + Notification::send($user, new RuleActionFailed($params)); + } + + /** + * @param RuleActionFailedOnObject $event + * + * @return void + */ + public function ruleActionFailedOnObject(RuleActionFailedOnObject $event): void + { + $ruleAction = $event->ruleAction; + $rule = $ruleAction->rule; + $preference = Preferences::getForUser($rule->user, 'notification_rule_action_failures', true)->data; + if (false === $preference) { + return; + } + app('log')->debug('Now in ruleActionFailedOnObject'); + $journal = $event->journal; + $error = $event->error; + $user = $ruleAction->rule->user; + + $mainMessage = trans('rules.main_message', ['rule' => $rule->title, 'action' => $ruleAction->action_type, 'group' => $journal->transaction_group_id, 'error' => $error]); + $groupTitle = $journal->description ?? ''; + $groupLink = route('transactions.show', [$journal->transaction_group_id]); + $ruleTitle = $rule->title; + $ruleLink = route('rules.edit', [$rule->id]); + $params = [$mainMessage, $groupTitle, $groupLink, $ruleTitle, $ruleLink]; + + + Notification::send($user, new RuleActionFailed($params)); + } + +} diff --git a/app/Handlers/Events/UserEventHandler.php b/app/Handlers/Events/UserEventHandler.php index 75b14a4736..79e8d50c07 100644 --- a/app/Handlers/Events/UserEventHandler.php +++ b/app/Handlers/Events/UserEventHandler.php @@ -275,6 +275,7 @@ class UserEventHandler Mail::to($newEmail)->send(new ConfirmEmailChangeMail($newEmail, $oldEmail, $url)); } catch (Exception $e) { // intentional generic exception Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException($e->getMessage(), 0, $e); } } @@ -299,6 +300,7 @@ class UserEventHandler Mail::to($oldEmail)->send(new UndoEmailChangeMail($newEmail, $oldEmail, $url)); } catch (Exception $e) { // intentional generic exception Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException($e->getMessage(), 0, $e); } } @@ -342,6 +344,7 @@ class UserEventHandler Mail::to($invitee)->send(new InvitationMail($invitee, $admin, $url)); } catch (Exception $e) { // intentional generic exception Log::error($e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException($e->getMessage(), 0, $e); } } diff --git a/app/Handlers/Events/VersionCheckEventHandler.php b/app/Handlers/Events/VersionCheckEventHandler.php index 1e380d3f31..5b39792b23 100644 --- a/app/Handlers/Events/VersionCheckEventHandler.php +++ b/app/Handlers/Events/VersionCheckEventHandler.php @@ -57,7 +57,7 @@ class VersionCheckEventHandler $permission = app('fireflyconfig')->get('permission_update_check', -1); $value = (int)$permission->data; if (1 !== $value) { - Log::info('Update check is not enabled.'); + Log::debug('Update check is not enabled.'); $this->warnToCheckForUpdates($event); return; diff --git a/app/Helpers/Collector/GroupCollector.php b/app/Helpers/Collector/GroupCollector.php index 8ad641805b..eee489d612 100644 --- a/app/Helpers/Collector/GroupCollector.php +++ b/app/Helpers/Collector/GroupCollector.php @@ -871,7 +871,7 @@ class GroupCollector implements GroupCollectorInterface public function setLimit(int $limit): GroupCollectorInterface { $this->limit = $limit; - app('log')->debug(sprintf('GroupCollector: The limit is now %d', $limit)); + //app('log')->debug(sprintf('GroupCollector: The limit is now %d', $limit)); return $this; } @@ -976,7 +976,7 @@ class GroupCollector implements GroupCollectorInterface { $page = 0 === $page ? 1 : $page; $this->page = $page; - app('log')->debug(sprintf('GroupCollector: page is now %d', $page)); + //app('log')->debug(sprintf('GroupCollector: page is now %d', $page)); return $this; } diff --git a/app/Http/Controllers/Admin/HomeController.php b/app/Http/Controllers/Admin/HomeController.php index ca9292021a..38c5799cc6 100644 --- a/app/Http/Controllers/Admin/HomeController.php +++ b/app/Http/Controllers/Admin/HomeController.php @@ -27,6 +27,7 @@ use FireflyIII\Events\AdminRequestedTestMessage; use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Support\Facades\FireflyConfig; +use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; @@ -99,7 +100,7 @@ class HomeController extends Controller if ('' === $url) { FireflyConfig::delete('slack_webhook_url'); } - if (str_starts_with($url, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($url)) { FireflyConfig::set('slack_webhook_url', $url); } diff --git a/app/Http/Controllers/Bill/IndexController.php b/app/Http/Controllers/Bill/IndexController.php index b9a81bece5..9c82002fc0 100644 --- a/app/Http/Controllers/Bill/IndexController.php +++ b/app/Http/Controllers/Bill/IndexController.php @@ -146,7 +146,7 @@ class IndexController extends Controller private function getSums(array $bills): array { $sums = []; - $range = app('navigation')->getViewRange(false); + $range = app('navigation')->getViewRange(true); /** @var array $group */ foreach ($bills as $groupOrder => $group) { @@ -177,7 +177,6 @@ class IndexController extends Controller $sums[$groupOrder][$currencyId]['per_period'] = bcadd($sums[$groupOrder][$currencyId]['per_period'], $this->amountPerPeriod($bill, $range)); } } - return $sums; } diff --git a/app/Http/Controllers/Budget/IndexController.php b/app/Http/Controllers/Budget/IndexController.php index 8d541550b7..46f3a09c71 100644 --- a/app/Http/Controllers/Budget/IndexController.php +++ b/app/Http/Controllers/Budget/IndexController.php @@ -101,6 +101,7 @@ class IndexController extends Controller */ public function index(Request $request, Carbon $start = null, Carbon $end = null) { + $this->abRepository->cleanup(); Log::debug(sprintf('Start of IndexController::index("%s", "%s")', $start?->format('Y-m-d'), $end?->format('Y-m-d'))); // collect some basic vars: @@ -337,6 +338,7 @@ class IndexController extends Controller */ public function reorder(Request $request, BudgetRepositoryInterface $repository): JsonResponse { + $this->abRepository->cleanup(); $budgetIds = $request->get('budgetIds'); foreach ($budgetIds as $index => $budgetId) { diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 34af46d70f..90e27d3c18 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -138,6 +138,9 @@ class HomeController extends Controller $accounts = $repository->getAccountsById($frontPage->data); $today = today(config('app.timezone')); + // sort frontpage accounts by order + $accounts = $accounts->sortBy('order'); + Log::debug('Frontpage accounts are ', $frontPage->data); /** @var BillRepositoryInterface $billRepository */ diff --git a/app/Http/Controllers/Json/BoxController.php b/app/Http/Controllers/Json/BoxController.php index 1bd0a3788e..c47451fa71 100644 --- a/app/Http/Controllers/Json/BoxController.php +++ b/app/Http/Controllers/Json/BoxController.php @@ -55,10 +55,12 @@ class BoxController extends Controller */ public function available(): JsonResponse { + app('log')->debug('Now in available()'); /** @var OperationsRepositoryInterface $opsRepository */ $opsRepository = app(OperationsRepositoryInterface::class); /** @var AvailableBudgetRepositoryInterface $abRepository */ $abRepository = app(AvailableBudgetRepositoryInterface::class); + $abRepository->cleanup(); /** @var Carbon $start */ $start = session('start', today(config('app.timezone'))->startOfMonth()); /** @var Carbon $end */ @@ -73,40 +75,57 @@ class BoxController extends Controller $cache->addProperty($today); $cache->addProperty('box-available'); if ($cache->has()) { - return response()->json($cache->get()); + //return response()->json($cache->get()); } $leftPerDayAmount = '0'; $leftToSpendAmount = '0'; - $currency = app('amount')->getDefaultCurrency(); - $availableBudgets = $abRepository->getAvailableBudgetsByDate($start, $end); + $currency = app('amount')->getDefaultCurrency(); + app('log')->debug(sprintf('Default currency is %s', $currency->code)); + $availableBudgets = $abRepository->getAvailableBudgetsByExactDate($start, $end); + app('log')->debug(sprintf('Found %d available budget(s)', $availableBudgets->count())); $availableBudgets = $availableBudgets->filter( static function (AvailableBudget $availableBudget) use ($currency) { if ($availableBudget->transaction_currency_id === $currency->id) { + app('log')->debug(sprintf( + 'Will include AB #%d: from %s-%s amount %s', + $availableBudget->id, + $availableBudget->start_date->format('Y-m-d'), + $availableBudget->end_date->format('Y-m-d'), + $availableBudget->amount + )); return $availableBudget; } return null; } ); + app('log')->debug(sprintf('Filtered back to %d available budgets', $availableBudgets->count())); // 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'; + app('log')->debug(sprintf('Spent for default currency for all budgets in this period: %s', $spentAmount)); - $days = $today->between($start, $end) ? $today->diffInDays($start) + 1 : $end->diffInDays($start) + 1; + $days = $today->between($start, $end) ? $today->diffInDays($start) + 1 : $end->diffInDays($start) + 1; + app('log')->debug(sprintf('Number of days left: %d', $days)); $spentPerDay = bcdiv($spentAmount, (string)$days); + app('log')->debug(sprintf('Available to spend per day: %s', $spentPerDay)); if ($availableBudgets->count() > 0) { $display = 0; // assume user overspent $boxTitle = (string)trans('firefly.overspent'); $totalAvailableSum = (string)$availableBudgets->sum('amount'); + app('log')->debug(sprintf('Total available sum is %s', $totalAvailableSum)); // calculate with available budget. $leftToSpendAmount = bcadd($totalAvailableSum, $spentAmount); + app('log')->debug(sprintf('So left to spend is %s', $leftToSpendAmount)); if (1 === bccomp($leftToSpendAmount, '0')) { + app('log')->debug(sprintf('Left to spend is positive!')); $boxTitle = (string)trans('firefly.left_to_spend'); $days = $today->diffInDays($end) + 1; $display = 1; // not overspent $leftPerDayAmount = bcdiv($leftToSpendAmount, (string)$days); + app('log')->debug(sprintf('Left to spend per day is %s', $leftPerDayAmount)); } } @@ -118,9 +137,10 @@ class BoxController extends Controller 'left_per_day' => app('amount')->formatAnything($currency, $leftPerDayAmount, false), 'title' => $boxTitle, ]; + app('log')->debug('Final output', $return); $cache->store($return); - + app('log')->debug('Now done with available()'); return response()->json($return); } diff --git a/app/Http/Controllers/Json/FrontpageController.php b/app/Http/Controllers/Json/FrontpageController.php index e0c94ca7e4..3ae35b987e 100644 --- a/app/Http/Controllers/Json/FrontpageController.php +++ b/app/Http/Controllers/Json/FrontpageController.php @@ -75,6 +75,7 @@ class FrontpageController extends Controller $html = view('json.piggy-banks', compact('info'))->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render json.piggy-banks: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $html = 'Could not render view.'; throw new FireflyException($html, 0, $e); } diff --git a/app/Http/Controllers/Json/ReconcileController.php b/app/Http/Controllers/Json/ReconcileController.php index 19d2e3373a..d9d2bc1136 100644 --- a/app/Http/Controllers/Json/ReconcileController.php +++ b/app/Http/Controllers/Json/ReconcileController.php @@ -157,6 +157,7 @@ class ReconcileController extends Controller )->render(); } catch (Throwable $e) { Log::debug(sprintf('View error: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $view = sprintf('Could not render accounts.reconcile.overview: %s', $e->getMessage()); throw new FireflyException($view, 0, $e); } @@ -258,6 +259,7 @@ class ReconcileController extends Controller )->render(); } catch (Throwable $e) { Log::debug(sprintf('Could not render: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $html = sprintf('Could not render accounts.reconcile.transactions: %s', $e->getMessage()); throw new FireflyException($html, 0, $e); } diff --git a/app/Http/Controllers/Json/RuleController.php b/app/Http/Controllers/Json/RuleController.php index d84b18d3c2..9a2a9d6d1f 100644 --- a/app/Http/Controllers/Json/RuleController.php +++ b/app/Http/Controllers/Json/RuleController.php @@ -55,6 +55,7 @@ class RuleController extends Controller $view = view('rules.partials.action', compact('actions', 'count'))->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render rules.partials.action: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $view = 'Could not render view.'; throw new FireflyException($view, 0, $e); } @@ -86,6 +87,7 @@ class RuleController extends Controller $view = view('rules.partials.trigger', compact('triggers', 'count'))->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render rules.partials.trigger: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $view = 'Could not render view.'; throw new FireflyException($view, 0, $e); } diff --git a/app/Http/Controllers/PreferencesController.php b/app/Http/Controllers/PreferencesController.php index 0ae9480ccf..aec2828524 100644 --- a/app/Http/Controllers/PreferencesController.php +++ b/app/Http/Controllers/PreferencesController.php @@ -28,6 +28,7 @@ use FireflyIII\Models\Account; use FireflyIII\Models\AccountType; use FireflyIII\Models\Preference; use FireflyIII\Repositories\Account\AccountRepositoryInterface; +use FireflyIII\Support\Notifications\UrlValidator; use Illuminate\Contracts\View\Factory; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; @@ -207,7 +208,7 @@ class PreferencesController extends Controller // slack URL: if (!auth()->user()->hasRole('demo')) { $url = (string)$request->get('slackUrl'); - if (str_starts_with($url, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($url)) { app('preferences')->set('slack_webhook_url', $url); } if ('' === $url) { diff --git a/app/Http/Controllers/Report/AccountController.php b/app/Http/Controllers/Report/AccountController.php index eac746a1d8..323f289fa7 100644 --- a/app/Http/Controllers/Report/AccountController.php +++ b/app/Http/Controllers/Report/AccountController.php @@ -65,7 +65,8 @@ class AccountController extends Controller try { $result = view('reports.partials.accounts', compact('accountReport'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.accounts: %s', $e->getMessage())); + Log::error(sprintf('Could not render reports.partials.accounts: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render view.'; throw new FireflyException($result, 0, $e); } diff --git a/app/Http/Controllers/Report/BalanceController.php b/app/Http/Controllers/Report/BalanceController.php index 7eeaffc454..b5f17b782c 100644 --- a/app/Http/Controllers/Report/BalanceController.php +++ b/app/Http/Controllers/Report/BalanceController.php @@ -141,7 +141,8 @@ class BalanceController extends Controller try { $result = view('reports.partials.balance', compact('report'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.balance: %s', $e->getMessage())); + Log::error(sprintf('Could not render reports.partials.balance: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render view.'; throw new FireflyException($result, 0, $e); } diff --git a/app/Http/Controllers/Report/BillController.php b/app/Http/Controllers/Report/BillController.php index b75c263c54..bc143c05ff 100644 --- a/app/Http/Controllers/Report/BillController.php +++ b/app/Http/Controllers/Report/BillController.php @@ -61,7 +61,8 @@ class BillController extends Controller try { $result = view('reports.partials.bills', compact('report'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budgets: %s', $e->getMessage())); + Log::error(sprintf('Could not render reports.partials.budgets: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render view.'; throw new FireflyException($result, 0, $e); } diff --git a/app/Http/Controllers/Report/BudgetController.php b/app/Http/Controllers/Report/BudgetController.php index 9c82a31a44..e4d3dea46d 100644 --- a/app/Http/Controllers/Report/BudgetController.php +++ b/app/Http/Controllers/Report/BudgetController.php @@ -195,8 +195,9 @@ class BudgetController extends Controller try { $result = view('reports.budget.partials.avg-expenses', compact('result'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); $result = sprintf('Could not render view: %s', $e->getMessage()); + Log::error($e->getTraceAsString()); throw new FireflyException($result, 0, $e); } @@ -353,7 +354,8 @@ class BudgetController extends Controller try { $result = view('reports.partials.budget-period', compact('report', 'periods'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render view.'; throw new FireflyException($result, 0, $e); } @@ -406,7 +408,7 @@ class BudgetController extends Controller try { $result = view('reports.budget.partials.top-expenses', compact('result'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(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); } diff --git a/app/Http/Controllers/Report/CategoryController.php b/app/Http/Controllers/Report/CategoryController.php index acab659218..bced1f2231 100644 --- a/app/Http/Controllers/Report/CategoryController.php +++ b/app/Http/Controllers/Report/CategoryController.php @@ -315,7 +315,7 @@ class CategoryController extends Controller try { $result = view('reports.category.partials.avg-expenses', compact('result'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(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); } @@ -368,7 +368,7 @@ class CategoryController extends Controller try { $result = view('reports.category.partials.avg-income', compact('result'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(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); } diff --git a/app/Http/Controllers/Report/DoubleController.php b/app/Http/Controllers/Report/DoubleController.php index b2b68938d5..c72eb63732 100644 --- a/app/Http/Controllers/Report/DoubleController.php +++ b/app/Http/Controllers/Report/DoubleController.php @@ -115,7 +115,7 @@ class DoubleController extends Controller try { $result = view('reports.double.partials.avg-expenses', compact('result'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(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); } @@ -168,7 +168,7 @@ class DoubleController extends Controller try { $result = view('reports.double.partials.avg-income', compact('result'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(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); } @@ -463,7 +463,7 @@ class DoubleController extends Controller try { $result = view('reports.double.partials.top-expenses', compact('result'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(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); } @@ -514,7 +514,7 @@ class DoubleController extends Controller try { $result = view('reports.double.partials.top-income', compact('result'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.budget-period: %s', $e->getMessage())); + Log::error(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); } diff --git a/app/Http/Controllers/Report/OperationsController.php b/app/Http/Controllers/Report/OperationsController.php index 7f534dba26..9eb7d89b40 100644 --- a/app/Http/Controllers/Report/OperationsController.php +++ b/app/Http/Controllers/Report/OperationsController.php @@ -85,7 +85,8 @@ class OperationsController extends Controller try { $result = view('reports.partials.income-expenses', compact('report', 'type'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.income-expense: %s', $e->getMessage())); + Log::error(sprintf('Could not render reports.partials.income-expense: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render view.'; throw new FireflyException($result, 0, $e); } @@ -121,7 +122,8 @@ class OperationsController extends Controller try { $result = view('reports.partials.income-expenses', compact('report', 'type'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.income-expenses: %s', $e->getMessage())); + Log::error(sprintf('Could not render reports.partials.income-expenses: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render view.'; throw new FireflyException($result, 0, $e); } @@ -177,7 +179,8 @@ class OperationsController extends Controller try { $result = view('reports.partials.operations', compact('sums'))->render(); } catch (Throwable $e) { - Log::debug(sprintf('Could not render reports.partials.operations: %s', $e->getMessage())); + Log::error(sprintf('Could not render reports.partials.operations: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $result = 'Could not render view.'; throw new FireflyException($result, 0, $e); } diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 1ef3bfd253..5963f8eb5e 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -128,6 +128,7 @@ class SearchController extends Controller $html = view('search.search', compact('groups', 'hasPages', 'searchTime'))->render(); } catch (Throwable $e) { Log::error(sprintf('Cannot render search.search: %s', $e->getMessage())); + Log::error($e->getTraceAsString()); $html = 'Could not render view.'; throw new FireflyException($html, 0, $e); } diff --git a/app/Http/Requests/ReportFormRequest.php b/app/Http/Requests/ReportFormRequest.php index 0ad6760f87..94e6f83f64 100644 --- a/app/Http/Requests/ReportFormRequest.php +++ b/app/Http/Requests/ReportFormRequest.php @@ -158,6 +158,7 @@ class ReportFormRequest extends FormRequest } catch (Exception $e) { // intentional generic exception $error = sprintf('"%s" is not a valid date range: %s', $range, $e->getMessage()); Log::error($error); + Log::error($e->getTraceAsString()); throw new FireflyException($error, 0, $e); } return $date; @@ -192,6 +193,7 @@ class ReportFormRequest extends FormRequest } catch (Exception $e) { // intentional generic exception $error = sprintf('"%s" is not a valid date range: %s', $range, $e->getMessage()); Log::error($error); + Log::error($e->getTraceAsString()); throw new FireflyException($error, 0, $e); } return $date; @@ -220,19 +222,18 @@ class ReportFormRequest extends FormRequest } if (!is_array($set)) { Log::error(sprintf('Set is not an array! "%s"', $set)); + return $collection; } - if (is_array($set)) { - foreach ($set as $tagTag) { - Log::debug(sprintf('Now searching for "%s"', $tagTag)); - $tag = $repository->findByTag($tagTag); - if (null !== $tag) { - $collection->push($tag); - continue; - } - $tag = $repository->find((int)$tagTag); - if (null !== $tag) { - $collection->push($tag); - } + foreach ($set as $tagTag) { + Log::debug(sprintf('Now searching for "%s"', $tagTag)); + $tag = $repository->findByTag($tagTag); + if (null !== $tag) { + $collection->push($tag); + continue; + } + $tag = $repository->find((int)$tagTag); + if (null !== $tag) { + $collection->push($tag); } } diff --git a/app/Notifications/Admin/TestNotification.php b/app/Notifications/Admin/TestNotification.php index 0332f3519c..f4277b34cc 100644 --- a/app/Notifications/Admin/TestNotification.php +++ b/app/Notifications/Admin/TestNotification.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Notifications\Admin; +use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; @@ -99,9 +100,9 @@ class TestNotification extends Notification public function via($notifiable) { /** @var User|null $user */ - $user = auth()->user(); + $user = auth()->user(); $slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data; - if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($slackUrl)) { return ['mail', 'slack']; } return ['mail']; diff --git a/app/Notifications/Admin/UserInvitation.php b/app/Notifications/Admin/UserInvitation.php index 9050b30863..19f4c5668a 100644 --- a/app/Notifications/Admin/UserInvitation.php +++ b/app/Notifications/Admin/UserInvitation.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Notifications\Admin; use FireflyIII\Models\InvitedUser; +use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; @@ -102,9 +103,9 @@ class UserInvitation extends Notification public function via($notifiable) { /** @var User|null $user */ - $user = auth()->user(); + $user = auth()->user(); $slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data; - if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($slackUrl)) { return ['mail', 'slack']; } return ['mail']; diff --git a/app/Notifications/Admin/UserRegistration.php b/app/Notifications/Admin/UserRegistration.php index 8d0ebf5406..ab1174bd15 100644 --- a/app/Notifications/Admin/UserRegistration.php +++ b/app/Notifications/Admin/UserRegistration.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Notifications\Admin; +use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; @@ -99,9 +100,9 @@ class UserRegistration extends Notification public function via($notifiable) { /** @var User|null $user */ - $user = auth()->user(); + $user = auth()->user(); $slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data; - if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($slackUrl)) { return ['mail', 'slack']; } return ['mail']; diff --git a/app/Notifications/Admin/VersionCheckResult.php b/app/Notifications/Admin/VersionCheckResult.php index d6f29ceecd..3555f52538 100644 --- a/app/Notifications/Admin/VersionCheckResult.php +++ b/app/Notifications/Admin/VersionCheckResult.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Notifications\Admin; +use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; @@ -87,21 +88,10 @@ class VersionCheckResult extends Notification */ public function toSlack($notifiable) { - // return (new SlackMessage())->text($this->message) - // ->sectionBlock(function (SectionBlock $block) { - // $button = new ButtonElement('Button'); - // $button->url('https://github.com/firefly-iii/firefly-iii/releases'); - // $block->accessory($button); - // }); - //// ->attachment(function ($attachment) { - //// $attachment->title('Firefly III @ GitHub', 'https://github.com/firefly-iii/firefly-iii/releases'); - //// }); - - return (new SlackMessage())->content($this->message) - ->attachment(function ($attachment) { - $attachment->title('Firefly III @ GitHub', 'https://github.com/firefly-iii/firefly-iii/releases'); - }); + ->attachment(function ($attachment) { + $attachment->title('Firefly III @ GitHub', 'https://github.com/firefly-iii/firefly-iii/releases'); + }); } /** @@ -114,9 +104,9 @@ class VersionCheckResult extends Notification public function via($notifiable) { /** @var User|null $user */ - $user = auth()->user(); + $user = auth()->user(); $slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data; - if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($slackUrl)) { return ['mail', 'slack']; } return ['mail']; diff --git a/app/Notifications/User/BillReminder.php b/app/Notifications/User/BillReminder.php index abe997248b..d3824aca52 100644 --- a/app/Notifications/User/BillReminder.php +++ b/app/Notifications/User/BillReminder.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Notifications\User; use FireflyIII\Models\Bill; +use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; @@ -38,8 +39,8 @@ class BillReminder extends Notification { use Queueable; - private Bill $bill; - private int $diff; + private Bill $bill; + private int $diff; private string $field; /** @@ -49,9 +50,9 @@ class BillReminder extends Notification */ public function __construct(Bill $bill, string $field, int $diff) { - $this->bill = $bill; + $this->bill = $bill; $this->field = $field; - $this->diff = $diff; + $this->diff = $diff; } /** @@ -101,7 +102,7 @@ class BillReminder extends Notification $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]); + $url = route('bills.show', [$bill->id]); return (new SlackMessage()) ->warning() ->attachment(function ($attachment) use ($bill, $url) { @@ -120,9 +121,9 @@ class BillReminder extends Notification public function via($notifiable) { /** @var User|null $user */ - $user = auth()->user(); + $user = auth()->user(); $slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data; - if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($slackUrl)) { return ['mail', 'slack']; } return ['mail']; diff --git a/app/Notifications/User/NewAccessToken.php b/app/Notifications/User/NewAccessToken.php index 69df8107a0..907d27df9e 100644 --- a/app/Notifications/User/NewAccessToken.php +++ b/app/Notifications/User/NewAccessToken.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\Notifications\User; +use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; @@ -96,9 +97,9 @@ class NewAccessToken extends Notification public function via($notifiable) { /** @var User|null $user */ - $user = auth()->user(); + $user = auth()->user(); $slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data; - if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($slackUrl)) { return ['mail', 'slack']; } return ['mail']; diff --git a/app/Notifications/User/RuleActionFailed.php b/app/Notifications/User/RuleActionFailed.php new file mode 100644 index 0000000000..caeef8a5b4 --- /dev/null +++ b/app/Notifications/User/RuleActionFailed.php @@ -0,0 +1,117 @@ +. + */ + +declare(strict_types=1); + +namespace FireflyIII\Notifications\User; + +use FireflyIII\Support\Notifications\UrlValidator; +use FireflyIII\User; +use Illuminate\Bus\Queueable; +use Illuminate\Notifications\Messages\SlackMessage; +use Illuminate\Notifications\Notification; + +/** + * Class RuleActionFailed + */ +class RuleActionFailed extends Notification +{ + use Queueable; + + private string $groupLink; + private string $groupTitle; + private string $message; + private string $ruleLink; + private string $ruleTitle; + + /** + * Create a new notification instance. + * + * @return void + */ + public function __construct(array $params) + { + [$mainMessage, $groupTitle, $groupLink, $ruleTitle, $ruleLink] = $params; + $this->message = $mainMessage; + $this->groupTitle = $groupTitle; + $this->groupLink = $groupLink; + $this->ruleTitle = $ruleTitle; + $this->ruleLink = $ruleLink; + + + } + + /** + * Get the array representation of the notification. + * + * @param mixed $notifiable + * + * @return array + */ + public function toArray($notifiable) + { + return [ + // + ]; + } + + /** + * Get the Slack representation of the notification. + * + * @param mixed $notifiable + * + * @return SlackMessage + */ + public function toSlack($notifiable) + { + $groupTitle = $this->groupTitle; + $groupLink = $this->groupLink; + $ruleTitle = $this->ruleTitle; + $ruleLink = $this->ruleLink; + + return (new SlackMessage())->content($this->message)->attachment(function ($attachment) use ($groupTitle, $groupLink) { + $attachment->title((string)trans('rules.inspect_transaction', ['title' => $groupTitle]), $groupLink); + })->attachment(function ($attachment) use ($ruleTitle, $ruleLink) { + $attachment->title((string)trans('rules.inspect_rule', ['title' => $ruleTitle]), $ruleLink); + }); + } + + /** + * Get the notification's delivery channels. + * + * @param mixed $notifiable + * + * @return array + */ + public function via($notifiable) + { + /** @var User|null $user */ + $user = auth()->user(); + $slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data; + if (UrlValidator::isValidWebhookURL($slackUrl)) { + app('log')->debug('Will send ruleActionFailed through Slack!'); + return ['slack']; + } + app('log')->debug('Will NOT send ruleActionFailed through Slack'); + return []; + } +} diff --git a/app/Notifications/User/UserLogin.php b/app/Notifications/User/UserLogin.php index 4ede883cea..0e6ddd5cdb 100644 --- a/app/Notifications/User/UserLogin.php +++ b/app/Notifications/User/UserLogin.php @@ -25,6 +25,7 @@ declare(strict_types=1); namespace FireflyIII\Notifications\User; use FireflyIII\Exceptions\FireflyException; +use FireflyIII\Support\Notifications\UrlValidator; use FireflyIII\User; use Illuminate\Bus\Queueable; use Illuminate\Notifications\Messages\MailMessage; @@ -124,9 +125,9 @@ class UserLogin extends Notification public function via($notifiable) { /** @var User|null $user */ - $user = auth()->user(); + $user = auth()->user(); $slackUrl = null === $user ? '' : (string)app('preferences')->getForUser(auth()->user(), 'slack_webhook_url', '')->data; - if (str_starts_with($slackUrl, 'https://hooks.slack.com/services/')) { + if (UrlValidator::isValidWebhookURL($slackUrl)) { return ['mail', 'slack']; } return ['mail']; diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 0ef77cded6..8ae53d9a93 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -32,6 +32,8 @@ use FireflyIII\Events\DetectedNewIPAddress; use FireflyIII\Events\Model\BudgetLimit\Created; use FireflyIII\Events\Model\BudgetLimit\Deleted; use FireflyIII\Events\Model\BudgetLimit\Updated; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject; use FireflyIII\Events\NewVersionAvailable; use FireflyIII\Events\RegisteredUser; use FireflyIII\Events\RequestedNewPassword; @@ -170,6 +172,14 @@ class EventServiceProvider extends ServiceProvider 'FireflyIII\Handlers\Events\Model\BudgetLimitHandler@deleted', ], + // rule actions + RuleActionFailedOnArray::class => [ + 'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnArray', + ], + RuleActionFailedOnObject::class => [ + 'FireflyIII\Handlers\Events\Model\RuleHandler@ruleActionFailedOnObject', + ], + ]; /** diff --git a/app/Repositories/Budget/AvailableBudgetRepository.php b/app/Repositories/Budget/AvailableBudgetRepository.php index a17b17d4e2..86ef18f8c4 100644 --- a/app/Repositories/Budget/AvailableBudgetRepository.php +++ b/app/Repositories/Budget/AvailableBudgetRepository.php @@ -39,6 +39,49 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface { private User $user; + /** + * @inheritDoc + */ + public function cleanup(): void + { + $exists = []; + $availableBudgets = $this->user->availableBudgets()->get(); + /** @var AvailableBudget $availableBudget */ + foreach ($availableBudgets as $availableBudget) { + $start = $availableBudget->start_date->format('Y-m-d'); + $end = $availableBudget->end_date->format('Y-m-d'); + $key = sprintf('%s-%s-%s', $availableBudget->transaction_currency_id, $start, $end); + if (array_key_exists($key, $exists)) { + app('log')->debug(sprintf('Found duplicate AB: %s %s, %s-%s. Has been deleted', $availableBudget->transaction_currency_id, $availableBudget->amount, $start, $end)); + $availableBudget->delete(); + } + $exists[$key] = true; + } + } + + /** + * Return a list of all available budgets (in all currencies) (for the selected period). + * + * @param Carbon|null $start + * @param Carbon|null $end + * + * @return Collection + */ + public function get(?Carbon $start = null, ?Carbon $end = null): Collection + { + $query = $this->user->availableBudgets()->with(['transactionCurrency']); + if (null !== $start && null !== $end) { + $query->where( + static function (Builder $q1) use ($start, $end) { + $q1->where('start_date', '=', $start->format('Y-m-d')); + $q1->where('end_date', '=', $end->format('Y-m-d')); + } + ); + } + + return $query->get(['available_budgets.*']); + } + /** * Delete all available budgets. */ @@ -122,29 +165,6 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface return $return; } - /** - * Return a list of all available budgets (in all currencies) (for the selected period). - * - * @param Carbon|null $start - * @param Carbon|null $end - * - * @return Collection - */ - public function get(?Carbon $start = null, ?Carbon $end = null): Collection - { - $query = $this->user->availableBudgets()->with(['transactionCurrency']); - if (null !== $start && null !== $end) { - $query->where( - static function (Builder $q1) use ($start, $end) { - $q1->where('start_date', '=', $start->format('Y-m-d')); - $q1->where('end_date', '=', $end->format('Y-m-d')); - } - ); - } - - return $query->get(['available_budgets.*']); - } - /** * Returns all available budget objects. * @@ -180,6 +200,23 @@ class AvailableBudgetRepository implements AvailableBudgetRepositoryInterface return $query->get(); } + /** + * Returns all available budget objects. + * + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + * + */ + public function getAvailableBudgetsByExactDate(Carbon $start, Carbon $end): Collection + { + return $this->user->availableBudgets() + ->where('start_date', '=', $start->format('Y-m-d')) + ->where('end_date', '=', $end->format('Y-m-d')) + ->get(); + } + /** * @inheritDoc */ diff --git a/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php b/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php index 56cd8172e1..fd2c004e6e 100644 --- a/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php +++ b/app/Repositories/Budget/AvailableBudgetRepositoryInterface.php @@ -35,6 +35,11 @@ use Illuminate\Support\Collection; */ interface AvailableBudgetRepositoryInterface { + /** + * @return void + */ + public function cleanup(): void; + /** * Delete all available budgets. */ @@ -111,6 +116,14 @@ interface AvailableBudgetRepositoryInterface */ public function getAvailableBudgetsByDate(?Carbon $start, ?Carbon $end): Collection; + /** + * @param Carbon $start + * @param Carbon $end + * + * @return Collection + */ + public function getAvailableBudgetsByExactDate(Carbon $start, Carbon $end): Collection; + /** * Get by transaction currency and date. Should always result in one entry or NULL. * diff --git a/app/Support/Http/Controllers/RenderPartialViews.php b/app/Support/Http/Controllers/RenderPartialViews.php index 7d22120392..c68c358255 100644 --- a/app/Support/Http/Controllers/RenderPartialViews.php +++ b/app/Support/Http/Controllers/RenderPartialViews.php @@ -294,7 +294,7 @@ trait RenderPartialViews } 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); + throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e); } ++$index; @@ -349,7 +349,7 @@ trait RenderPartialViews } 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); + throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e); } ++$index; diff --git a/app/Support/Http/Controllers/RuleManagement.php b/app/Support/Http/Controllers/RuleManagement.php index f5f67e7ca2..ab382afa21 100644 --- a/app/Support/Http/Controllers/RuleManagement.php +++ b/app/Support/Http/Controllers/RuleManagement.php @@ -62,7 +62,7 @@ trait RuleManagement } catch (Throwable $e) { Log::error(sprintf('Throwable was thrown in getPreviousActions(): %s', $e->getMessage())); Log::error($e->getTraceAsString()); - throw new FireflyException('Could not render', 0, $e); + throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e); } $index++; } @@ -109,7 +109,7 @@ trait RuleManagement } 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); + throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e); } $index++; } @@ -153,7 +153,7 @@ trait RuleManagement } 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); + throw new FireflyException(sprintf('Could not render: %s', $e->getMessage()), 0, $e); } $index++; } diff --git a/app/Support/Notifications/UrlValidator.php b/app/Support/Notifications/UrlValidator.php new file mode 100644 index 0000000000..8948c00f82 --- /dev/null +++ b/app/Support/Notifications/UrlValidator.php @@ -0,0 +1,40 @@ +. + */ + +namespace FireflyIII\Support\Notifications; + +/** + * Class UrlValidator + */ +class UrlValidator +{ + /** + * @param string $url + * + * @return bool + */ + public static function isValidWebhookURL(string $url): bool + { + return str_starts_with($url, 'https://hooks.slack.com/services/') || str_starts_with($url, 'https://discord.com/api/webhooks/'); + } +} diff --git a/app/Support/Search/OperatorQuerySearch.php b/app/Support/Search/OperatorQuerySearch.php index 4d9f692e63..b0a64829fc 100644 --- a/app/Support/Search/OperatorQuerySearch.php +++ b/app/Support/Search/OperatorQuerySearch.php @@ -1004,151 +1004,151 @@ class OperatorQuerySearch implements SearchInterface // case '-date_on': case 'date_on': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setExactDateParams($range, $prohibited); return false; case 'date_before': case '-date_after': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setDateBeforeParams($range); return false; case 'date_after': case '-date_before': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setDateAfterParams($range); return false; case 'interest_date_on': case '-interest_date_on': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setExactMetaDateParams('interest_date', $range, $prohibited); return false; case 'interest_date_before': case '-interest_date_after': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateBeforeParams('interest_date', $range); return false; case 'interest_date_after': case '-interest_date_before': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateAfterParams('interest_date', $range); return false; case 'book_date_on': case '-book_date_on': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setExactMetaDateParams('book_date', $range, $prohibited); return false; case 'book_date_before': case '-book_date_after': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateBeforeParams('book_date', $range); return false; case 'book_date_after': case '-book_date_before': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateAfterParams('book_date', $range); return false; case 'process_date_on': case '-process_date_on': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setExactMetaDateParams('process_date', $range, $prohibited); return false; case 'process_date_before': case '-process_date_after': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateBeforeParams('process_date', $range); return false; case 'process_date_after': case '-process_date_before': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateAfterParams('process_date', $range); return false; case 'due_date_on': case '-due_date_on': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setExactMetaDateParams('due_date', $range, $prohibited); return false; case 'due_date_before': case '-due_date_after': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateBeforeParams('due_date', $range); return false; case 'due_date_after': case '-due_date_before': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateAfterParams('due_date', $range); return false; case 'payment_date_on': case '-payment_date_on': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setExactMetaDateParams('payment_date', $range, $prohibited); return false; case 'payment_date_before': case '-payment_date_after': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateBeforeParams('payment_date', $range); return false; case 'payment_date_after': case '-payment_date_before': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateAfterParams('payment_date', $range); return false; case 'invoice_date_on': case '-invoice_date_on': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setExactMetaDateParams('invoice_date', $range, $prohibited); return false; case 'invoice_date_before': case '-invoice_date_after': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $value); $this->setMetaDateBeforeParams('invoice_date', $range); return false; case 'invoice_date_after': case '-invoice_date_before': - $range = $this->parseDateRange($value); + $range = $this->parseDateRange($operator, $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); + $range = $this->parseDateRange($operator, $value); $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); + $range = $this->parseDateRange($operator, $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); + $range = $this->parseDateRange($operator, $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); + $range = $this->parseDateRange($operator, $value); $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); + $range = $this->parseDateRange($operator, $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); + $range = $this->parseDateRange($operator, $value); $this->setObjectDateAfterParams('updated_at', $range); return false; // @@ -1550,13 +1550,22 @@ class OperatorQuerySearch implements SearchInterface * @return array * @throws FireflyException */ - private function parseDateRange(string $value): array + private function parseDateRange(string $type, string $value): array { $parser = new ParseDateString(); if ($parser->isDateRange($value)) { return $parser->parseRange($value); } - $parsedDate = $parser->parseDate($value); + try { + $parsedDate = $parser->parseDate($value); + } catch (FireflyException $e) { + Log::debug(sprintf('Could not parse date "%s", will return empty array.', $value)); + $this->invalidOperators[] = [ + 'type' => $type, + 'value' => (string)$value, + ]; + return []; + } return [ 'exact' => $parsedDate, diff --git a/app/TransactionRules/Actions/AddTag.php b/app/TransactionRules/Actions/AddTag.php index 44ffabbafe..057473463c 100644 --- a/app/TransactionRules/Actions/AddTag.php +++ b/app/TransactionRules/Actions/AddTag.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Factory\TagFactory; use FireflyIII\Models\RuleAction; @@ -61,7 +62,7 @@ class AddTag implements ActionInterface if (null === $tag) { // could not find, could not create tag. - Log::error(sprintf('RuleAction AddTag. Could not find or create tag "%s"', $this->action->action_value)); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.find_or_create_tag_failed', ['tag' => $this->action->action_value]))); return false; } @@ -78,12 +79,12 @@ class AddTag implements ActionInterface // event for audit log entry event(new TriggeredAuditLog($this->action->rule, $object, 'add_tag', null, $tag->tag)); - return true; } Log::debug( sprintf('RuleAction AddTag fired but tag %d ("%s") was already added to journal %d.', $tag->id, $tag->tag, $journal['transaction_journal_id']) ); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.tag_already_added', ['tag' => $this->action->action_value]))); return false; } diff --git a/app/TransactionRules/Actions/AppendDescriptionToNotes.php b/app/TransactionRules/Actions/AppendDescriptionToNotes.php index f5c0280e48..a10e442140 100644 --- a/app/TransactionRules/Actions/AppendDescriptionToNotes.php +++ b/app/TransactionRules/Actions/AppendDescriptionToNotes.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\Note; use FireflyIII\Models\RuleAction; @@ -56,6 +57,7 @@ class AppendDescriptionToNotes implements ActionInterface $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'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_other_user'))); return false; } $note = $object->notes()->first(); diff --git a/app/TransactionRules/Actions/AppendNotesToDescription.php b/app/TransactionRules/Actions/AppendNotesToDescription.php index 20a48901d7..93469788a8 100644 --- a/app/TransactionRules/Actions/AppendNotesToDescription.php +++ b/app/TransactionRules/Actions/AppendNotesToDescription.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\Note; use FireflyIII\Models\RuleAction; @@ -60,6 +61,7 @@ class AppendNotesToDescription implements ActionInterface $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'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_other_user'))); return false; } $note = $object->notes()->first(); @@ -80,6 +82,7 @@ class AppendNotesToDescription implements ActionInterface return true; } + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.new_notes_empty'))); return false; } diff --git a/app/TransactionRules/Actions/ClearBudget.php b/app/TransactionRules/Actions/ClearBudget.php index 24599dcc7e..2c79a535fb 100644 --- a/app/TransactionRules/Actions/ClearBudget.php +++ b/app/TransactionRules/Actions/ClearBudget.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionJournal; @@ -56,6 +57,7 @@ class ClearBudget implements ActionInterface $budget = $object->budgets()->first(); if (null === $budget) { Log::debug(sprintf('RuleAction ClearBudget, no budget in journal #%d.', $journal['transaction_journal_id'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_already_no_budget'))); return false; } diff --git a/app/TransactionRules/Actions/ClearCategory.php b/app/TransactionRules/Actions/ClearCategory.php index c478ea05d8..22b9df33f7 100644 --- a/app/TransactionRules/Actions/ClearCategory.php +++ b/app/TransactionRules/Actions/ClearCategory.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionJournal; @@ -56,6 +57,7 @@ class ClearCategory implements ActionInterface $category = $object->categories()->first(); if (null === $category) { Log::debug(sprintf('RuleAction ClearCategory, no category in journal #%d.', $journal['transaction_journal_id'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_already_no_category'))); return false; } diff --git a/app/TransactionRules/Actions/ClearNotes.php b/app/TransactionRules/Actions/ClearNotes.php index 77757456df..d67a1b3d90 100644 --- a/app/TransactionRules/Actions/ClearNotes.php +++ b/app/TransactionRules/Actions/ClearNotes.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionJournal; @@ -55,6 +56,7 @@ class ClearNotes implements ActionInterface $notes = $object->notes()->first(); if (null === $notes) { Log::debug(sprintf('RuleAction ClearNotes, journal #%d has no notes.', $journal['transaction_journal_id'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_already_no_notes'))); return false; } $before = $notes->text; diff --git a/app/TransactionRules/Actions/ConvertToDeposit.php b/app/TransactionRules/Actions/ConvertToDeposit.php index 803b2c7516..36091f7905 100644 --- a/app/TransactionRules/Actions/ConvertToDeposit.php +++ b/app/TransactionRules/Actions/ConvertToDeposit.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\AccountFactory; @@ -65,11 +66,13 @@ class ConvertToDeposit implements ActionInterface $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); if (null === $object) { Log::error(sprintf('Cannot find journal #%d, cannot convert to deposit.', $journal['transaction_journal_id'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_not_found'))); return false; } $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'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.split_group'))); return false; } @@ -77,7 +80,7 @@ class ConvertToDeposit implements ActionInterface $type = $object->transactionType->type; if (TransactionType::DEPOSIT === $type) { Log::error(sprintf('Journal #%d is already a deposit (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id)); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_already_deposit'))); return false; } @@ -89,6 +92,7 @@ class ConvertToDeposit implements ActionInterface } catch (JsonException | FireflyException $e) { Log::debug('Could not convert withdrawal to deposit.'); Log::error($e->getMessage()); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error'))); return false; } @@ -104,13 +108,14 @@ class ConvertToDeposit implements ActionInterface } catch (JsonException | FireflyException $e) { Log::debug('Could not convert transfer to deposit.'); Log::error($e->getMessage()); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error'))); return false; } event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::TRANSFER, TransactionType::DEPOSIT)); return $res; } - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_deposit', ['type' => $type]))); return false; } diff --git a/app/TransactionRules/Actions/ConvertToTransfer.php b/app/TransactionRules/Actions/ConvertToTransfer.php index ddfbab0d6c..14fe267fc7 100644 --- a/app/TransactionRules/Actions/ConvertToTransfer.php +++ b/app/TransactionRules/Actions/ConvertToTransfer.php @@ -24,6 +24,8 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnObject; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; @@ -62,11 +64,13 @@ class ConvertToTransfer implements ActionInterface $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); if (null === $object) { Log::error(sprintf('Cannot find journal #%d, cannot convert to transfer.', $journal['transaction_journal_id'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_not_found'))); return false; } $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'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.split_group'))); return false; } @@ -77,15 +81,19 @@ class ConvertToTransfer implements ActionInterface Log::error( sprintf('Journal #%d is already a transfer so cannot be converted (rule #%d).', $object->id, $this->action->rule_id) ); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_already_transfer'))); return false; } + if (TransactionType::DEPOSIT !== $type && TransactionType::WITHDRAWAL !== $type) { + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_transfer', ['type' => $type]))); + return false; + } // find the asset account in the action value. /** @var AccountRepositoryInterface $repository */ $repository = app(AccountRepositoryInterface::class); $repository->setUser($user); - $opposing = null; $expectedType = null; if (TransactionType::WITHDRAWAL === $type) { $expectedType = $this->getSourceType($journalId); @@ -107,6 +115,7 @@ class ConvertToTransfer implements ActionInterface $this->action->rule_id ) ); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_valid_opposing', ['name' => $this->action->action_value]))); return false; } @@ -118,9 +127,12 @@ class ConvertToTransfer implements ActionInterface } catch (FireflyException $e) { Log::debug('Could not convert withdrawal to transfer.'); Log::error($e->getMessage()); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error'))); return false; } - event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::WITHDRAWAL, TransactionType::TRANSFER)); + if (false !== $res) { + event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::WITHDRAWAL, TransactionType::TRANSFER)); + } return $res; } if (TransactionType::DEPOSIT === $type) { @@ -130,12 +142,15 @@ class ConvertToTransfer implements ActionInterface } catch (FireflyException $e) { Log::debug('Could not convert deposit to transfer.'); Log::error($e->getMessage()); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error'))); return false; } - event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::TRANSFER)); + if (false !== $res) { + event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::TRANSFER)); + } return $res; } - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_transfer', ['type' => $type]))); return false; } @@ -192,6 +207,7 @@ class ConvertToTransfer implements ActionInterface [$journal->id, $opposing->name, $this->action->rule_id] ) ); + event(new RuleActionFailedOnObject($this->action, $journal, trans('rules.already_has_source_asset', ['name' => $opposing->name]))); return false; } @@ -250,6 +266,7 @@ class ConvertToTransfer implements ActionInterface [$journal->id, $opposing->name, $this->action->rule_id] ) ); + event(new RuleActionFailedOnObject($this->action, $journal, trans('rules.already_has_destination_asset', ['name' => $opposing->name]))); return false; } diff --git a/app/TransactionRules/Actions/ConvertToWithdrawal.php b/app/TransactionRules/Actions/ConvertToWithdrawal.php index 8ce97e5c8c..f844e213a0 100644 --- a/app/TransactionRules/Actions/ConvertToWithdrawal.php +++ b/app/TransactionRules/Actions/ConvertToWithdrawal.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Factory\AccountFactory; @@ -65,21 +66,26 @@ class ConvertToWithdrawal implements ActionInterface $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); if (null === $object) { Log::error(sprintf('Cannot find journal #%d, cannot convert to withdrawal.', $journal['transaction_journal_id'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_not_found'))); return false; } $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'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.split_group'))); return false; } $type = $object->transactionType->type; if (TransactionType::WITHDRAWAL === $type) { Log::error(sprintf('Journal #%d is already a withdrawal (rule #%d).', $journal['transaction_journal_id'], $this->action->rule_id)); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_already_withdrawal'))); + return false; + } + if (TransactionType::DEPOSIT !== $type && TransactionType::TRANSFER !== $type) { + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_withdrawal', ['type' => $type]))); return false; } - if (TransactionType::DEPOSIT === $type) { Log::debug('Going to transform a deposit to a withdrawal.'); try { @@ -87,6 +93,7 @@ class ConvertToWithdrawal implements ActionInterface } catch (JsonException | FireflyException $e) { Log::debug('Could not convert transfer to deposit.'); Log::error($e->getMessage()); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error'))); return false; } event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::DEPOSIT, TransactionType::WITHDRAWAL)); @@ -101,13 +108,14 @@ class ConvertToWithdrawal implements ActionInterface } catch (JsonException | FireflyException $e) { Log::debug('Could not convert transfer to deposit.'); Log::error($e->getMessage()); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.complex_error'))); return false; } event(new TriggeredAuditLog($this->action->rule, $object, 'update_transaction_type', TransactionType::TRANSFER, TransactionType::WITHDRAWAL)); return $res; } - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.unsupported_transaction_type_withdrawal', ['type' => $type]))); return false; } diff --git a/app/TransactionRules/Actions/LinkToBill.php b/app/TransactionRules/Actions/LinkToBill.php index a996116bfd..74de2eeb41 100644 --- a/app/TransactionRules/Actions/LinkToBill.php +++ b/app/TransactionRules/Actions/LinkToBill.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionJournal; @@ -73,6 +74,7 @@ class LinkToBill implements ActionInterface $billName ) ); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_linked_to_subscription', ['name' => $billName]))); return false; } @@ -97,7 +99,7 @@ class LinkToBill implements ActionInterface $billName ) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_subscription', ['name' => $billName]))); return false; } } diff --git a/app/TransactionRules/Actions/MoveDescriptionToNotes.php b/app/TransactionRules/Actions/MoveDescriptionToNotes.php index 611c1841a0..9d17dd8ae2 100644 --- a/app/TransactionRules/Actions/MoveDescriptionToNotes.php +++ b/app/TransactionRules/Actions/MoveDescriptionToNotes.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\Note; use FireflyIII\Models\RuleAction; @@ -57,6 +58,7 @@ class MoveDescriptionToNotes implements ActionInterface $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'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_other_user'))); return false; } $note = $object->notes()->first(); diff --git a/app/TransactionRules/Actions/MoveNotesToDescription.php b/app/TransactionRules/Actions/MoveNotesToDescription.php index 5c670629bd..8ce108aa02 100644 --- a/app/TransactionRules/Actions/MoveNotesToDescription.php +++ b/app/TransactionRules/Actions/MoveNotesToDescription.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionJournal; @@ -63,16 +64,19 @@ class MoveNotesToDescription implements ActionInterface $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'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.journal_other_user'))); return false; } $note = $object->notes()->first(); if (null === $note) { + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_notes_to_move'))); // nothing to move, return null return false; } if ('' === $note->text) { // nothing to move, return null $note->delete(); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_notes_to_move'))); return false; } $before = $object->description; diff --git a/app/TransactionRules/Actions/RemoveAllTags.php b/app/TransactionRules/Actions/RemoveAllTags.php index c2ee19ad0b..87ccbe0b2f 100644 --- a/app/TransactionRules/Actions/RemoveAllTags.php +++ b/app/TransactionRules/Actions/RemoveAllTags.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionJournal; @@ -55,6 +56,7 @@ class RemoveAllTags implements ActionInterface $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'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_tags_to_remove'))); return false; } Log::debug(sprintf('RuleAction RemoveAllTags removed all tags from journal %d.', $journal['transaction_journal_id'])); diff --git a/app/TransactionRules/Actions/RemoveTag.php b/app/TransactionRules/Actions/RemoveTag.php index c72454e67a..f3f23ad9e9 100644 --- a/app/TransactionRules/Actions/RemoveTag.php +++ b/app/TransactionRules/Actions/RemoveTag.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionJournal; @@ -61,6 +62,7 @@ class RemoveTag implements ActionInterface Log::debug( sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag exists.', $name, $journal['transaction_journal_id']) ); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_tag', ['tag' => $name]))); return false; } $count = DB::table('tag_transaction_journal')->where('transaction_journal_id', $journal['transaction_journal_id'])->where('tag_id', $tag->id)->count(); @@ -68,6 +70,7 @@ class RemoveTag implements ActionInterface Log::debug( sprintf('RuleAction RemoveTag tried to remove tag "%s" from journal #%d but no such tag is linked.', $name, $journal['transaction_journal_id']) ); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_unlink_tag', ['tag' => $name]))); return false; } diff --git a/app/TransactionRules/Actions/SetBudget.php b/app/TransactionRules/Actions/SetBudget.php index 0ce333dfcb..ed48a2cea5 100644 --- a/app/TransactionRules/Actions/SetBudget.php +++ b/app/TransactionRules/Actions/SetBudget.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\TransactionJournal; @@ -65,7 +66,7 @@ class SetBudget implements ActionInterface $search ) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_budget', ['name' => $search]))); return false; } @@ -78,7 +79,7 @@ class SetBudget implements ActionInterface $journal['transaction_type_type'] ) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_set_budget', ['type' => $journal['transaction_type_type'], 'name' => $search]))); return false; } diff --git a/app/TransactionRules/Actions/SetCategory.php b/app/TransactionRules/Actions/SetCategory.php index a0fdab020e..1277d1e2ce 100644 --- a/app/TransactionRules/Actions/SetCategory.php +++ b/app/TransactionRules/Actions/SetCategory.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Factory\CategoryFactory; use FireflyIII\Models\RuleAction; @@ -57,7 +58,7 @@ class SetCategory implements ActionInterface $search = $this->action->action_value; if (null === $user) { Log::error(sprintf('Journal has no valid user ID so action SetCategory("%s") cannot be applied', $search), $journal); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal'))); return false; } @@ -73,7 +74,7 @@ class SetCategory implements ActionInterface $search ) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_category', ['name' => $search]))); return false; } diff --git a/app/TransactionRules/Actions/SetDestinationAccount.php b/app/TransactionRules/Actions/SetDestinationAccount.php index 7cb68f68de..1daa030c64 100644 --- a/app/TransactionRules/Actions/SetDestinationAccount.php +++ b/app/TransactionRules/Actions/SetDestinationAccount.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\Account; use FireflyIII\Models\RuleAction; @@ -65,7 +66,7 @@ class SetDestinationAccount implements ActionInterface if (null === $object) { Log::error('Could not find journal.'); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal'))); return false; } $type = $object->transactionType->type; @@ -81,7 +82,7 @@ class SetDestinationAccount implements ActionInterface $this->action->action_value ) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_asset', ['name' => $this->action->action_value]))); return false; } @@ -90,13 +91,13 @@ class SetDestinationAccount implements ActionInterface $source = $object->transactions()->where('amount', '<', 0)->first(); if (null === $source) { Log::error('Could not find source transaction.'); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_source_transaction'))); return false; } // account must not be deleted (in the meantime): if (null === $source->account) { Log::error('Could not find source transaction account.'); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_source_transaction_account'))); return false; } if (null !== $newAccount && (int)$newAccount->id === (int)$source->account_id) { @@ -108,6 +109,7 @@ class SetDestinationAccount implements ActionInterface ) ); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_has_destination', ['name' => $newAccount->name]))); return false; } diff --git a/app/TransactionRules/Actions/SetSourceAccount.php b/app/TransactionRules/Actions/SetSourceAccount.php index 6493411c4a..724b47b986 100644 --- a/app/TransactionRules/Actions/SetSourceAccount.php +++ b/app/TransactionRules/Actions/SetSourceAccount.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\Account; use FireflyIII\Models\RuleAction; @@ -64,7 +65,7 @@ class SetSourceAccount implements ActionInterface $this->repository = app(AccountRepositoryInterface::class); if (null === $object) { Log::error('Could not find journal.'); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal'))); return false; } $type = $object->transactionType->type; @@ -76,7 +77,7 @@ class SetSourceAccount implements ActionInterface Log::error( sprintf('Cant change source account of journal #%d because no asset account with name "%s" exists.', $object->id, $this->action->action_value) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_asset', ['name' => $this->action->action_value]))); return false; } @@ -85,13 +86,13 @@ class SetSourceAccount implements ActionInterface $destination = $object->transactions()->where('amount', '>', 0)->first(); if (null === $destination) { Log::error('Could not find destination transaction.'); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_destination_transaction'))); return false; } // account must not be deleted (in the meantime): if (null === $destination->account) { Log::error('Could not find destination transaction account.'); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_destination_transaction_account'))); return false; } if (null !== $newAccount && (int)$newAccount->id === (int)$destination->account_id) { @@ -102,12 +103,12 @@ class SetSourceAccount implements ActionInterface $destination->account_id ) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.already_has_source', ['name' => $newAccount->name]))); return false; } // if this is a deposit, the new source account must be a revenue account and may be created: - // or its a liability + // or it's a liability if (TransactionType::DEPOSIT === $type) { $newAccount = $this->findDepositSourceAccount(); } diff --git a/app/TransactionRules/Actions/SwitchAccounts.php b/app/TransactionRules/Actions/SwitchAccounts.php index 98d67259fc..29d71b6bcc 100644 --- a/app/TransactionRules/Actions/SwitchAccounts.php +++ b/app/TransactionRules/Actions/SwitchAccounts.php @@ -24,6 +24,7 @@ declare(strict_types=1); namespace FireflyIII\TransactionRules\Actions; use DB; +use FireflyIII\Events\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\RuleAction; use FireflyIII\Models\Transaction; @@ -59,18 +60,20 @@ class SwitchAccounts implements ActionInterface $object = TransactionJournal::where('user_id', $journal['user_id'])->find($journal['transaction_journal_id']); if (null === $object) { Log::error(sprintf('Cannot find journal #%d, cannot switch accounts.', $journal['transaction_journal_id'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_such_journal'))); return false; } $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 switch accounts.', $journal['transaction_group_id'])); + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.split_group'))); return false; } $type = $object->transactionType->type; if (TransactionType::TRANSFER !== $type) { Log::error(sprintf('Journal #%d is NOT a transfer (rule #%d), cannot switch accounts.', $journal['transaction_journal_id'], $this->action->rule_id)); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.is_not_transfer'))); return false; } @@ -80,7 +83,7 @@ class SwitchAccounts implements ActionInterface $destTransaction = $object->transactions()->where('amount', '>', 0)->first(); if (null === $sourceTransaction || null === $destTransaction) { Log::error(sprintf('Journal #%d has no source or destination transaction (rule #%d), cannot switch accounts.', $journal['transaction_journal_id'], $this->action->rule_id)); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_accounts'))); return false; } $sourceAccountId = (int)$sourceTransaction->account_id; diff --git a/app/TransactionRules/Actions/UpdatePiggybank.php b/app/TransactionRules/Actions/UpdatePiggybank.php index a70c0dc548..c0699f258d 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\Model\Rule\RuleActionFailedOnArray; use FireflyIII\Events\TriggeredAuditLog; use FireflyIII\Models\PiggyBank; use FireflyIII\Models\RuleAction; @@ -61,16 +62,15 @@ class UpdatePiggybank implements ActionInterface // refresh the transaction type. $user = User::find($journal['user_id']); /** @var TransactionJournal $journalObj */ - $journalObj = $user->transactionJournals()->find($journal['transaction_journal_id']); - $type = TransactionType::find((int)$journalObj->transaction_type_id); - $journal['transaction_type_type'] = $type->type; + $journalObj = $user->transactionJournals()->find($journal['transaction_journal_id']); + $type = TransactionType::find((int)$journalObj->transaction_type_id); $piggyBank = $this->findPiggyBank($user); if (null === $piggyBank) { Log::info( sprintf('No piggy bank named "%s", cant execute action #%d of rule #%d', $this->action->action_value, $this->action->id, $this->action->rule_id) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.cannot_find_piggy', ['name' => $this->action->action_value]))); return false; } @@ -130,7 +130,7 @@ class UpdatePiggybank implements ActionInterface $destination->account_id ) ); - + event(new RuleActionFailedOnArray($this->action, $journal, trans('rules.no_link_piggy', ['name' => $this->action->action_value]))); return false; } diff --git a/app/Transformers/V2/AccountTransformer.php b/app/Transformers/V2/AccountTransformer.php index b5afd3e84b..175704ca03 100644 --- a/app/Transformers/V2/AccountTransformer.php +++ b/app/Transformers/V2/AccountTransformer.php @@ -28,6 +28,7 @@ use Carbon\Carbon; use FireflyIII\Exceptions\FireflyException; use FireflyIII\Models\Account; use FireflyIII\Models\AccountMeta; +use FireflyIII\Models\AccountType; use FireflyIII\Models\TransactionCurrency; use FireflyIII\Repositories\Currency\CurrencyRepositoryInterface; use Illuminate\Support\Collection; @@ -38,6 +39,7 @@ use Illuminate\Support\Collection; class AccountTransformer extends AbstractTransformer { private array $accountMeta; + private array $accountTypes; private array $balances; private array $convertedBalances; private array $currencies; @@ -51,6 +53,7 @@ class AccountTransformer extends AbstractTransformer { $this->currencies = []; $this->accountMeta = []; + $this->accountTypes = []; $this->balances = app('steam')->balancesByAccounts($objects, $this->getDate()); $this->convertedBalances = app('steam')->balancesByAccountsConverted($objects, $this->getDate()); $repository = app(CurrencyRepositoryInterface::class); @@ -72,6 +75,15 @@ class AccountTransformer extends AbstractTransformer $id = (int)$entry->account_id; $this->accountMeta[$id][$entry->name] = $entry->data; } + // get account types: + // select accounts.id, account_types.type from account_types left join accounts on accounts.account_type_id = account_types.id; + $accountTypes = AccountType::leftJoin('accounts', 'accounts.account_type_id', '=', 'account_types.id') + ->whereIn('accounts.id', $accountIds) + ->get(['accounts.id', 'account_types.type']); + /** @var AccountType $row */ + foreach ($accountTypes as $row) { + $this->accountTypes[(int)$row->id] = (string)config(sprintf('firefly.shortNamesByFullName.%s', $row->type)); + } } /** @@ -96,10 +108,13 @@ class AccountTransformer extends AbstractTransformer */ public function transform(Account $account): array { - //$fullType = $account->accountType->type; - //$accountType = (string) config(sprintf('firefly.shortNamesByFullName.%s', $fullType)); $id = (int)$account->id; + // various meta + $accountRole = $this->accountMeta[$id]['account_role'] ?? null; + $accountType = $this->accountTypes[$id]; + $order = (int)$account->order; + // no currency? use default $currency = $this->default; if (0 !== (int)$this->accountMeta[$id]['currency_id']) { @@ -109,16 +124,21 @@ class AccountTransformer extends AbstractTransformer $balance = $this->balances[$id] ?? null; $nativeBalance = $this->convertedBalances[$id]['native_balance'] ?? null; + // no order for some accounts: + if (!in_array(strtolower($accountType), ['liability', 'liabilities', 'asset'], true)) { + $order = null; + } + return [ 'id' => (string)$account->id, 'created_at' => $account->created_at->toAtomString(), 'updated_at' => $account->updated_at->toAtomString(), 'active' => $account->active, - //'order' => $order, + 'order' => $order, 'name' => $account->name, 'iban' => '' === $account->iban ? null : $account->iban, - // 'type' => strtolower($accountType), - // 'account_role' => $accountRole, + 'type' => strtolower($accountType), + 'account_role' => $accountRole, 'currency_id' => (string)$currency->id, 'currency_code' => $currency->code, 'currency_symbol' => $currency->symbol, diff --git a/app/Transformers/V2/TransactionGroupTransformer.php b/app/Transformers/V2/TransactionGroupTransformer.php index 9b16fd3e14..fcb4b89501 100644 --- a/app/Transformers/V2/TransactionGroupTransformer.php +++ b/app/Transformers/V2/TransactionGroupTransformer.php @@ -302,7 +302,7 @@ class TransactionGroupTransformer extends AbstractTransformer if (null === $string) { return null; } - Log::debug(sprintf('Now in date("%s")', $string)); + // Log::debug(sprintf('Now in date("%s")', $string)); if (10 === strlen($string)) { return Carbon::createFromFormat('Y-m-d', $string, config('app.timezone')); } diff --git a/app/Validation/Account/DepositValidation.php b/app/Validation/Account/DepositValidation.php index cfb3c3d032..3fc58764ac 100644 --- a/app/Validation/Account/DepositValidation.php +++ b/app/Validation/Account/DepositValidation.php @@ -114,7 +114,11 @@ trait DepositValidation // source can be any of the following types. $validTypes = array_keys($this->combinations[$this->transactionType]); - if (null === $accountId && null === $accountName && false === $this->canCreateTypes($validTypes)) { + if (null === $accountId && + null === $accountName && + null === $accountIban && + null === $accountNumber && + false === $this->canCreateTypes($validTypes)) { // if both values are NULL return false, // because the source of a deposit can't be created. // (this never happens). @@ -122,12 +126,12 @@ trait DepositValidation $result = false; } - // if there is an iban, it can only be in use by a revenue account or we will fail. + // if there is an iban, it can only be in use by a revenue account, or we will fail. if (null !== $accountIban && '' !== $accountIban) { app('log')->debug('Check if there is not already an account with this IBAN'); $existing = $this->findExistingAccount([AccountType::ASSET, AccountType::LOAN, AccountType::DEBT, AccountType::MORTGAGE], ['iban' => $accountIban]); if (null !== $existing) { - $this->destError = (string)trans('validation.deposit_src_iban_exists'); + $this->sourceError = (string)trans('validation.deposit_src_iban_exists'); return false; } } diff --git a/app/Validation/AccountValidator.php b/app/Validation/AccountValidator.php index 3e3027b8ae..159779fbd9 100644 --- a/app/Validation/AccountValidator.php +++ b/app/Validation/AccountValidator.php @@ -265,6 +265,7 @@ class AccountValidator if (null !== $accountId && $accountId > 0) { $first = $this->accountRepository->find($accountId); if ((null !== $first) && in_array($first->accountType->type, $validTypes, true)) { + app('log')->debug(sprintf('ID: Found %s account #%d ("%s", IBAN "%s")', $first->accountType->type, $first->id, $first->name, $first->iban ?? 'no iban')); return $first; } } @@ -273,6 +274,7 @@ class AccountValidator if (null !== $accountIban && '' !== (string)$accountIban) { $first = $this->accountRepository->findByIbanNull($accountIban, $validTypes); if ((null !== $first) && in_array($first->accountType->type, $validTypes, true)) { + app('log')->debug(sprintf('Iban: Found %s account #%d ("%s", IBAN "%s")', $first->accountType->type, $first->id, $first->name, $first->iban ?? 'no iban')); return $first; } } @@ -281,14 +283,19 @@ class AccountValidator if (null !== $accountNumber && '' !== (string)$accountNumber) { $first = $this->accountRepository->findByAccountNumber($accountNumber, $validTypes); if ((null !== $first) && in_array($first->accountType->type, $validTypes, true)) { + app('log')->debug(sprintf('Number: Found %s account #%d ("%s", IBAN "%s")', $first->accountType->type, $first->id, $first->name, $first->iban ?? 'no iban')); return $first; } } // find by name: if ('' !== (string)$accountName) { - return $this->accountRepository->findByName($accountName, $validTypes); + $first = $this->accountRepository->findByName($accountName, $validTypes); + if (null !== $first) { + app('log')->debug(sprintf('Name: Found %s account #%d ("%s", IBAN "%s")', $first->accountType->type, $first->id, $first->name, $first->iban ?? 'no iban')); + } } + app('log')->debug('Found nothing!'); return null; } diff --git a/app/Validation/TransactionValidation.php b/app/Validation/TransactionValidation.php index 1c22bd17c1..54ce6d14b3 100644 --- a/app/Validation/TransactionValidation.php +++ b/app/Validation/TransactionValidation.php @@ -103,6 +103,7 @@ trait TransactionValidation */ protected function validateSingleAccount(Validator $validator, int $index, string $transactionType, array $transaction): void { + app('log')->debug(sprintf('Now in validateSingleAccount(%d)', $index)); /** @var AccountValidator $accountValidator */ $accountValidator = app(AccountValidator::class); @@ -784,8 +785,8 @@ trait TransactionValidation private function compareAccountData(string $type, array $comparison): bool { return match ($type) { - default => $this->compareAccountDataWithdrawal($comparison), - 'deposit' => $this->compareAccountDataDeposit($comparison), + default => $this->compareAccountDataWithdrawal($comparison), + 'deposit' => $this->compareAccountDataDeposit($comparison), 'transfer' => $this->compareAccountDataTransfer($comparison), }; } diff --git a/changelog.md b/changelog.md index 0add30fe86..f2229b2902 100644 --- a/changelog.md +++ b/changelog.md @@ -3,6 +3,31 @@ All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning](http://semver.org/). +## 6.0.21 - 2023-09-02 + +### Added + +- Rules will now report failures if a Slack/Discord notification channel is configured +- Notifications can be sent to Discord +- Beta layout `v2`, activate with `FIRELY_III_LAYOUT=v2` + +### Changed + +- Audit log settings are changed, refer to the `.env.example`-file. +- Many URLs are new rendered as relative URLs. + +### Fixed + +- [Issue 7853](https://github.com/firefly-iii/firefly-iii/issues/7853) Left to spend on main page shows incorrect value +- [Issue 7883](https://github.com/firefly-iii/firefly-iii/issues/7883) Missing translation +- [Issue 7910](https://github.com/firefly-iii/firefly-iii/issues/7910) Type format error +- Home page respects account order +- JS errors for users using Firefly III in a subdir. + +### API + +- Bumped to v2.0.6 but only so the docs match again. + ## 6.0.20 - 2023-08-13 ### Fixed diff --git a/composer.json b/composer.json index 3d9046567f..d22dee38b1 100644 --- a/composer.json +++ b/composer.json @@ -85,7 +85,7 @@ "diglactic/laravel-breadcrumbs": "^8.1", "doctrine/dbal": "3.*", "gdbots/query-parser": "^3.0", - "guzzlehttp/guzzle": "^7.7", + "guzzlehttp/guzzle": "^7.8", "jc5/google2fa-laravel": "^2.0", "jc5/recovery": "^2", "laravel/framework": "^10", @@ -111,7 +111,7 @@ }, "require-dev": { "barryvdh/laravel-ide-helper": "2.*", - "ergebnis/phpstan-rules": "^2.0", + "ergebnis/phpstan-rules": "^2.1", "fakerphp/faker": "1.*", "filp/whoops": "2.*", "mockery/mockery": "1.*", diff --git a/composer.lock b/composer.lock index 664743cea4..3280806b1d 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": "8c97249c2a4e91bce05b1c2caab82909", + "content-hash": "8d6d03ba7c6916497caf509f8b97a140", "packages": [ { "name": "bacon/bacon-qr-code", @@ -117,16 +117,16 @@ }, { "name": "dasprid/enum", - "version": "1.0.4", + "version": "1.0.5", "source": { "type": "git", "url": "https://github.com/DASPRiD/Enum.git", - "reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f" + "reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/8e6b6ea76eabbf19ea2bf5b67b98e1860474012f", - "reference": "8e6b6ea76eabbf19ea2bf5b67b98e1860474012f", + "url": "https://api.github.com/repos/DASPRiD/Enum/zipball/6faf451159fb8ba4126b925ed2d78acfce0dc016", + "reference": "6faf451159fb8ba4126b925ed2d78acfce0dc016", "shasum": "" }, "require": { @@ -161,9 +161,9 @@ ], "support": { "issues": "https://github.com/DASPRiD/Enum/issues", - "source": "https://github.com/DASPRiD/Enum/tree/1.0.4" + "source": "https://github.com/DASPRiD/Enum/tree/1.0.5" }, - "time": "2023-03-01T18:44:03+00:00" + "time": "2023-08-25T16:18:39+00:00" }, { "name": "defuse/php-encryption", @@ -473,16 +473,16 @@ }, { "name": "doctrine/dbal", - "version": "3.6.5", + "version": "3.6.6", "source": { "type": "git", "url": "https://github.com/doctrine/dbal.git", - "reference": "96d5a70fd91efdcec81fc46316efc5bf3da17ddf" + "reference": "63646ffd71d1676d2f747f871be31b7e921c7864" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/dbal/zipball/96d5a70fd91efdcec81fc46316efc5bf3da17ddf", - "reference": "96d5a70fd91efdcec81fc46316efc5bf3da17ddf", + "url": "https://api.github.com/repos/doctrine/dbal/zipball/63646ffd71d1676d2f747f871be31b7e921c7864", + "reference": "63646ffd71d1676d2f747f871be31b7e921c7864", "shasum": "" }, "require": { @@ -498,10 +498,11 @@ "doctrine/coding-standard": "12.0.0", "fig/log-test": "^1", "jetbrains/phpstorm-stubs": "2023.1", - "phpstan/phpstan": "1.10.21", + "phpstan/phpstan": "1.10.29", "phpstan/phpstan-strict-rules": "^1.5", "phpunit/phpunit": "9.6.9", "psalm/plugin-phpunit": "0.18.4", + "slevomat/coding-standard": "8.13.1", "squizlabs/php_codesniffer": "3.7.2", "symfony/cache": "^5.4|^6.0", "symfony/console": "^4.4|^5.4|^6.0", @@ -565,7 +566,7 @@ ], "support": { "issues": "https://github.com/doctrine/dbal/issues", - "source": "https://github.com/doctrine/dbal/tree/3.6.5" + "source": "https://github.com/doctrine/dbal/tree/3.6.6" }, "funding": [ { @@ -581,7 +582,7 @@ "type": "tidelift" } ], - "time": "2023-07-17T09:15:50+00:00" + "time": "2023-08-17T05:38:17+00:00" }, { "name": "doctrine/deprecations", @@ -1378,22 +1379,22 @@ }, { "name": "guzzlehttp/guzzle", - "version": "7.7.0", + "version": "7.8.0", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5" + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5", - "reference": "fb7566caccf22d74d1ab270de3551f72a58399f5", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/1110f66a6530a40fe7aea0378fe608ee2b2248f9", + "reference": "1110f66a6530a40fe7aea0378fe608ee2b2248f9", "shasum": "" }, "require": { "ext-json": "*", - "guzzlehttp/promises": "^1.5.3 || ^2.0", - "guzzlehttp/psr7": "^1.9.1 || ^2.4.5", + "guzzlehttp/promises": "^1.5.3 || ^2.0.1", + "guzzlehttp/psr7": "^1.9.1 || ^2.5.1", "php": "^7.2.5 || ^8.0", "psr/http-client": "^1.0", "symfony/deprecation-contracts": "^2.2 || ^3.0" @@ -1484,7 +1485,7 @@ ], "support": { "issues": "https://github.com/guzzle/guzzle/issues", - "source": "https://github.com/guzzle/guzzle/tree/7.7.0" + "source": "https://github.com/guzzle/guzzle/tree/7.8.0" }, "funding": [ { @@ -1500,7 +1501,7 @@ "type": "tidelift" } ], - "time": "2023-05-21T14:04:53+00:00" + "time": "2023-08-27T10:20:53+00:00" }, { "name": "guzzlehttp/promises", @@ -1587,16 +1588,16 @@ }, { "name": "guzzlehttp/psr7", - "version": "2.6.0", + "version": "2.6.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77" + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/8bd7c33a0734ae1c5d074360512beb716bef3f77", - "reference": "8bd7c33a0734ae1c5d074360512beb716bef3f77", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/be45764272e8873c72dbe3d2edcfdfcc3bc9f727", + "reference": "be45764272e8873c72dbe3d2edcfdfcc3bc9f727", "shasum": "" }, "require": { @@ -1683,7 +1684,7 @@ ], "support": { "issues": "https://github.com/guzzle/psr7/issues", - "source": "https://github.com/guzzle/psr7/tree/2.6.0" + "source": "https://github.com/guzzle/psr7/tree/2.6.1" }, "funding": [ { @@ -1699,20 +1700,20 @@ "type": "tidelift" } ], - "time": "2023-08-03T15:06:02+00:00" + "time": "2023-08-27T10:13:57+00:00" }, { "name": "guzzlehttp/uri-template", - "version": "v1.0.1", + "version": "v1.0.2", "source": { "type": "git", "url": "https://github.com/guzzle/uri-template.git", - "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2" + "reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/uri-template/zipball/b945d74a55a25a949158444f09ec0d3c120d69e2", - "reference": "b945d74a55a25a949158444f09ec0d3c120d69e2", + "url": "https://api.github.com/repos/guzzle/uri-template/zipball/61bf437fc2197f587f6857d3ff903a24f1731b5d", + "reference": "61bf437fc2197f587f6857d3ff903a24f1731b5d", "shasum": "" }, "require": { @@ -1720,15 +1721,11 @@ "symfony/polyfill-php80": "^1.17" }, "require-dev": { + "bamarni/composer-bin-plugin": "^1.8.1", "phpunit/phpunit": "^8.5.19 || ^9.5.8", "uri-template/tests": "1.0.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.0-dev" - } - }, "autoload": { "psr-4": { "GuzzleHttp\\UriTemplate\\": "src" @@ -1767,7 +1764,7 @@ ], "support": { "issues": "https://github.com/guzzle/uri-template/issues", - "source": "https://github.com/guzzle/uri-template/tree/v1.0.1" + "source": "https://github.com/guzzle/uri-template/tree/v1.0.2" }, "funding": [ { @@ -1783,7 +1780,7 @@ "type": "tidelift" } ], - "time": "2021-10-07T12:57:01+00:00" + "time": "2023-08-27T10:19:19+00:00" }, { "name": "jc5/google2fa-laravel", @@ -1942,16 +1939,16 @@ }, { "name": "laravel/framework", - "version": "v10.18.0", + "version": "v10.21.0", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "9d41928900f7ecf409627a7d06c0a4dfecff2ea7" + "reference": "96b15c7ac382a9adb4a56d40c640e782d669a112" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/9d41928900f7ecf409627a7d06c0a4dfecff2ea7", - "reference": "9d41928900f7ecf409627a7d06c0a4dfecff2ea7", + "url": "https://api.github.com/repos/laravel/framework/zipball/96b15c7ac382a9adb4a56d40c640e782d669a112", + "reference": "96b15c7ac382a9adb4a56d40c640e782d669a112", "shasum": "" }, "require": { @@ -2138,20 +2135,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2023-08-08T14:30:38+00:00" + "time": "2023-08-29T13:55:56+00:00" }, { "name": "laravel/passport", - "version": "v11.8.8", + "version": "v11.9.0", "source": { "type": "git", "url": "https://github.com/laravel/passport.git", - "reference": "401836130d46c94138a637ada29f9e5b2bf053b6" + "reference": "2582d2a58ff32761cb3aecb337a146ba17483f76" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/passport/zipball/401836130d46c94138a637ada29f9e5b2bf053b6", - "reference": "401836130d46c94138a637ada29f9e5b2bf053b6", + "url": "https://api.github.com/repos/laravel/passport/zipball/2582d2a58ff32761cb3aecb337a146ba17483f76", + "reference": "2582d2a58ff32761cb3aecb337a146ba17483f76", "shasum": "" }, "require": { @@ -2216,20 +2213,20 @@ "issues": "https://github.com/laravel/passport/issues", "source": "https://github.com/laravel/passport" }, - "time": "2023-07-07T06:37:11+00:00" + "time": "2023-08-29T13:48:41+00:00" }, { "name": "laravel/prompts", - "version": "v0.1.4", + "version": "v0.1.6", "source": { "type": "git", "url": "https://github.com/laravel/prompts.git", - "reference": "1b3ab520a75eddefcda99f49fb551d231769b1fa" + "reference": "b514c5620e1b3b61221b0024dc88def26d9654f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/prompts/zipball/1b3ab520a75eddefcda99f49fb551d231769b1fa", - "reference": "1b3ab520a75eddefcda99f49fb551d231769b1fa", + "url": "https://api.github.com/repos/laravel/prompts/zipball/b514c5620e1b3b61221b0024dc88def26d9654f4", + "reference": "b514c5620e1b3b61221b0024dc88def26d9654f4", "shasum": "" }, "require": { @@ -2262,22 +2259,22 @@ ], "support": { "issues": "https://github.com/laravel/prompts/issues", - "source": "https://github.com/laravel/prompts/tree/v0.1.4" + "source": "https://github.com/laravel/prompts/tree/v0.1.6" }, - "time": "2023-08-07T13:14:59+00:00" + "time": "2023-08-18T13:32:23+00:00" }, { "name": "laravel/sanctum", - "version": "v3.2.5", + "version": "v3.2.6", "source": { "type": "git", "url": "https://github.com/laravel/sanctum.git", - "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876" + "reference": "217e8a2bc5aa6a827ced97fcb76504029d3115d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/sanctum/zipball/8ebda85d59d3c414863a7f4d816ef8302faad876", - "reference": "8ebda85d59d3c414863a7f4d816ef8302faad876", + "url": "https://api.github.com/repos/laravel/sanctum/zipball/217e8a2bc5aa6a827ced97fcb76504029d3115d7", + "reference": "217e8a2bc5aa6a827ced97fcb76504029d3115d7", "shasum": "" }, "require": { @@ -2290,9 +2287,9 @@ }, "require-dev": { "mockery/mockery": "^1.0", - "orchestra/testbench": "^7.0|^8.0", + "orchestra/testbench": "^7.28.2|^8.8.3", "phpstan/phpstan": "^1.10", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^9.6" }, "type": "library", "extra": { @@ -2330,7 +2327,7 @@ "issues": "https://github.com/laravel/sanctum/issues", "source": "https://github.com/laravel/sanctum" }, - "time": "2023-05-01T19:39:51+00:00" + "time": "2023-08-22T13:21:11+00:00" }, { "name": "laravel/serializable-closure", @@ -2660,16 +2657,16 @@ }, { "name": "league/commonmark", - "version": "2.4.0", + "version": "2.4.1", "source": { "type": "git", "url": "https://github.com/thephpleague/commonmark.git", - "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048" + "reference": "3669d6d5f7a47a93c08ddff335e6d945481a1dd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d44a24690f16b8c1808bf13b1bd54ae4c63ea048", - "reference": "d44a24690f16b8c1808bf13b1bd54ae4c63ea048", + "url": "https://api.github.com/repos/thephpleague/commonmark/zipball/3669d6d5f7a47a93c08ddff335e6d945481a1dd5", + "reference": "3669d6d5f7a47a93c08ddff335e6d945481a1dd5", "shasum": "" }, "require": { @@ -2762,7 +2759,7 @@ "type": "tidelift" } ], - "time": "2023-03-24T15:16:10+00:00" + "time": "2023-08-30T16:55:00+00:00" }, { "name": "league/config", @@ -3264,16 +3261,16 @@ }, { "name": "league/oauth2-server", - "version": "8.5.3", + "version": "8.5.4", "source": { "type": "git", "url": "https://github.com/thephpleague/oauth2-server.git", - "reference": "eb91b4190e7f6169053ebf8ffa352d47e756b2ce" + "reference": "ab7714d073844497fd222d5d0a217629089936bc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/eb91b4190e7f6169053ebf8ffa352d47e756b2ce", - "reference": "eb91b4190e7f6169053ebf8ffa352d47e756b2ce", + "url": "https://api.github.com/repos/thephpleague/oauth2-server/zipball/ab7714d073844497fd222d5d0a217629089936bc", + "reference": "ab7714d073844497fd222d5d0a217629089936bc", "shasum": "" }, "require": { @@ -3282,7 +3279,7 @@ "lcobucci/clock": "^2.2 || ^3.0", "lcobucci/jwt": "^4.3 || ^5.0", "league/event": "^2.2", - "league/uri": "^6.7", + "league/uri": "^6.7 || ^7.0", "php": "^8.0", "psr/http-message": "^1.0.1 || ^2.0" }, @@ -3340,7 +3337,7 @@ ], "support": { "issues": "https://github.com/thephpleague/oauth2-server/issues", - "source": "https://github.com/thephpleague/oauth2-server/tree/8.5.3" + "source": "https://github.com/thephpleague/oauth2-server/tree/8.5.4" }, "funding": [ { @@ -3348,58 +3345,48 @@ "type": "github" } ], - "time": "2023-07-05T23:01:32+00:00" + "time": "2023-08-25T22:35:12+00:00" }, { "name": "league/uri", - "version": "6.8.0", + "version": "7.2.1", "source": { "type": "git", "url": "https://github.com/thephpleague/uri.git", - "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39" + "reference": "8b644f8ff80352530bbc0ea467d5b5a89b60d832" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri/zipball/a700b4656e4c54371b799ac61e300ab25a2d1d39", - "reference": "a700b4656e4c54371b799ac61e300ab25a2d1d39", + "url": "https://api.github.com/repos/thephpleague/uri/zipball/8b644f8ff80352530bbc0ea467d5b5a89b60d832", + "reference": "8b644f8ff80352530bbc0ea467d5b5a89b60d832", "shasum": "" }, "require": { - "ext-json": "*", - "league/uri-interfaces": "^2.3", - "php": "^8.1", - "psr/http-message": "^1.0.1" + "league/uri-interfaces": "^7.2", + "php": "^8.1" }, "conflict": { "league/uri-schemes": "^1.0" }, - "require-dev": { - "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.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", - "ext-intl": "Needed to improve host validation", - "league/uri-components": "Needed to easily manipulate URI objects", - "psr/http-factory": "Needed to use the URI factory" + "ext-bcmath": "to improve IPV4 host parsing", + "ext-fileinfo": "to create Data URI from file contennts", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "jeremykendall/php-domain-parser": "to resolve Public Suffix and Top Level Domain", + "league/uri-components": "Needed to easily manipulate URI objects components", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "6.x-dev" + "dev-master": "7.x-dev" } }, "autoload": { "psr-4": { - "League\\Uri\\": "src" + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -3439,8 +3426,8 @@ "support": { "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.8.0" + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri/tree/7.2.1" }, "funding": [ { @@ -3448,46 +3435,44 @@ "type": "github" } ], - "time": "2022-09-13T19:58:47+00:00" + "time": "2023-08-30T21:06:57+00:00" }, { "name": "league/uri-interfaces", - "version": "2.3.0", + "version": "7.2.0", "source": { "type": "git", "url": "https://github.com/thephpleague/uri-interfaces.git", - "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383" + "reference": "43fa071050fcba89aefb5d4789a4a5a73874c44b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/00e7e2943f76d8cb50c7dfdc2f6dee356e15e383", - "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383", + "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/43fa071050fcba89aefb5d4789a4a5a73874c44b", + "reference": "43fa071050fcba89aefb5d4789a4a5a73874c44b", "shasum": "" }, "require": { - "ext-json": "*", - "php": "^7.2 || ^8.0" - }, - "require-dev": { - "friendsofphp/php-cs-fixer": "^2.19", - "phpstan/phpstan": "^0.12.90", - "phpstan/phpstan-phpunit": "^0.12.19", - "phpstan/phpstan-strict-rules": "^0.12.9", - "phpunit/phpunit": "^8.5.15 || ^9.5" + "ext-filter": "*", + "php": "^8.1", + "psr/http-factory": "^1", + "psr/http-message": "^1.1 || ^2.0" }, "suggest": { - "ext-intl": "to use the IDNA feature", - "symfony/intl": "to use the IDNA feature via Symfony Polyfill" + "ext-bcmath": "to improve IPV4 host parsing", + "ext-gmp": "to improve IPV4 host parsing", + "ext-intl": "to handle IDN host with the best performance", + "php-64bit": "to improve IPV4 host parsing", + "symfony/polyfill-intl-idn": "to handle IDN host via the Symfony polyfill if ext-intl is not present" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.x-dev" + "dev-master": "7.x-dev" } }, "autoload": { "psr-4": { - "League\\Uri\\": "src/" + "League\\Uri\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -3501,17 +3486,32 @@ "homepage": "https://nyamsprod.com" } ], - "description": "Common interface for URI representation", - "homepage": "http://github.com/thephpleague/uri-interfaces", + "description": "Common interfaces and classes for URI representation and interaction", + "homepage": "https://uri.thephpleague.com", "keywords": [ + "data-uri", + "file-uri", + "ftp", + "hostname", + "http", + "https", + "parse_str", + "parse_url", + "psr-7", + "query-string", + "querystring", "rfc3986", "rfc3987", + "rfc6570", "uri", - "url" + "url", + "ws" ], "support": { - "issues": "https://github.com/thephpleague/uri-interfaces/issues", - "source": "https://github.com/thephpleague/uri-interfaces/tree/2.3.0" + "docs": "https://uri.thephpleague.com", + "forum": "https://thephpleague.slack.com", + "issues": "https://github.com/thephpleague/uri-src/issues", + "source": "https://github.com/thephpleague/uri-interfaces/tree/7.2.0" }, "funding": [ { @@ -3519,7 +3519,7 @@ "type": "github" } ], - "time": "2021-06-28T04:27:21+00:00" + "time": "2023-08-30T19:43:38+00:00" }, { "name": "mailchimp/transactional", @@ -3678,25 +3678,29 @@ }, { "name": "nesbot/carbon", - "version": "2.68.1", + "version": "2.69.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da" + "reference": "4308217830e4ca445583a37d1bf4aff4153fa81c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4f991ed2a403c85efbc4f23eb4030063fdbe01da", - "reference": "4f991ed2a403c85efbc4f23eb4030063fdbe01da", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4308217830e4ca445583a37d1bf4aff4153fa81c", + "reference": "4308217830e4ca445583a37d1bf4aff4153fa81c", "shasum": "" }, "require": { "ext-json": "*", "php": "^7.1.8 || ^8.0", + "psr/clock": "^1.0", "symfony/polyfill-mbstring": "^1.0", "symfony/polyfill-php80": "^1.16", "symfony/translation": "^3.4 || ^4.0 || ^5.0 || ^6.0" }, + "provide": { + "psr/clock-implementation": "1.0" + }, "require-dev": { "doctrine/dbal": "^2.0 || ^3.1.4", "doctrine/orm": "^2.7", @@ -3776,7 +3780,7 @@ "type": "tidelift" } ], - "time": "2023-06-20T18:29:04+00:00" + "time": "2023-08-03T09:00:52+00:00" }, { "name": "nette/schema", @@ -4669,16 +4673,16 @@ }, { "name": "predis/predis", - "version": "v2.2.0", + "version": "v2.2.1", "source": { "type": "git", "url": "https://github.com/predis/predis.git", - "reference": "33b70b971a32b0d28b4f748b0547593dce316e0d" + "reference": "5f2b410a74afaff296a87a494e4c5488cf9fab57" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/predis/predis/zipball/33b70b971a32b0d28b4f748b0547593dce316e0d", - "reference": "33b70b971a32b0d28b4f748b0547593dce316e0d", + "url": "https://api.github.com/repos/predis/predis/zipball/5f2b410a74afaff296a87a494e4c5488cf9fab57", + "reference": "5f2b410a74afaff296a87a494e4c5488cf9fab57", "shasum": "" }, "require": { @@ -4718,7 +4722,7 @@ ], "support": { "issues": "https://github.com/predis/predis/issues", - "source": "https://github.com/predis/predis/tree/v2.2.0" + "source": "https://github.com/predis/predis/tree/v2.2.1" }, "funding": [ { @@ -4726,7 +4730,7 @@ "type": "github" } ], - "time": "2023-06-14T10:37:31+00:00" + "time": "2023-08-15T23:01:46+00:00" }, { "name": "psr/cache", @@ -5037,16 +5041,16 @@ }, { "name": "psr/http-message", - "version": "1.1", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/php-fig/http-message.git", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba" + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/cb6ce4845ce34a8ad9e68117c10ee90a29919eba", - "reference": "cb6ce4845ce34a8ad9e68117c10ee90a29919eba", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", "shasum": "" }, "require": { @@ -5055,7 +5059,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1.x-dev" + "dev-master": "2.0.x-dev" } }, "autoload": { @@ -5070,7 +5074,7 @@ "authors": [ { "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "homepage": "https://www.php-fig.org/" } ], "description": "Common interface for HTTP messages", @@ -5084,9 +5088,9 @@ "response" ], "support": { - "source": "https://github.com/php-fig/http-message/tree/1.1" + "source": "https://github.com/php-fig/http-message/tree/2.0" }, - "time": "2023-04-04T09:50:52+00:00" + "time": "2023-04-04T09:54:51+00:00" }, { "name": "psr/log", @@ -5624,16 +5628,16 @@ }, { "name": "spatie/ignition", - "version": "1.9.0", + "version": "1.10.1", "source": { "type": "git", "url": "https://github.com/spatie/ignition.git", - "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973" + "reference": "d92b9a081e99261179b63a858c7a4b01541e7dd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/ignition/zipball/de24ff1e01814d5043bd6eb4ab36a5a852a04973", - "reference": "de24ff1e01814d5043bd6eb4ab36a5a852a04973", + "url": "https://api.github.com/repos/spatie/ignition/zipball/d92b9a081e99261179b63a858c7a4b01541e7dd1", + "reference": "d92b9a081e99261179b63a858c7a4b01541e7dd1", "shasum": "" }, "require": { @@ -5703,7 +5707,7 @@ "type": "github" } ], - "time": "2023-06-28T13:24:59+00:00" + "time": "2023-08-21T15:06:37+00:00" }, { "name": "spatie/laravel-html", @@ -5785,16 +5789,16 @@ }, { "name": "spatie/laravel-ignition", - "version": "2.2.0", + "version": "2.3.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-ignition.git", - "reference": "dd15fbe82ef5392798941efae93c49395a87d943" + "reference": "4ed813d16edb5a1ab0d7f4b1d116c37ee8cdf3c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/dd15fbe82ef5392798941efae93c49395a87d943", - "reference": "dd15fbe82ef5392798941efae93c49395a87d943", + "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/4ed813d16edb5a1ab0d7f4b1d116c37ee8cdf3c0", + "reference": "4ed813d16edb5a1ab0d7f4b1d116c37ee8cdf3c0", "shasum": "" }, "require": { @@ -5873,7 +5877,7 @@ "type": "github" } ], - "time": "2023-06-28T13:51:52+00:00" + "time": "2023-08-23T06:24:34+00:00" }, { "name": "spatie/period", @@ -5931,16 +5935,16 @@ }, { "name": "symfony/console", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898" + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/aa5d64ad3f63f2e48964fc81ee45cb318a723898", - "reference": "aa5d64ad3f63f2e48964fc81ee45cb318a723898", + "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", "shasum": "" }, "require": { @@ -6001,7 +6005,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.3.2" + "source": "https://github.com/symfony/console/tree/v6.3.4" }, "funding": [ { @@ -6017,7 +6021,7 @@ "type": "tidelift" } ], - "time": "2023-07-19T20:17:28+00:00" + "time": "2023-08-16T10:10:12+00:00" }, { "name": "symfony/css-selector", @@ -6617,16 +6621,16 @@ }, { "name": "symfony/http-foundation", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "43ed99d30f5f466ffa00bdac3f5f7aa9cd7617c3" + "reference": "cac1556fdfdf6719668181974104e6fcfa60e844" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/43ed99d30f5f466ffa00bdac3f5f7aa9cd7617c3", - "reference": "43ed99d30f5f466ffa00bdac3f5f7aa9cd7617c3", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/cac1556fdfdf6719668181974104e6fcfa60e844", + "reference": "cac1556fdfdf6719668181974104e6fcfa60e844", "shasum": "" }, "require": { @@ -6674,7 +6678,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.3.2" + "source": "https://github.com/symfony/http-foundation/tree/v6.3.4" }, "funding": [ { @@ -6690,20 +6694,20 @@ "type": "tidelift" } ], - "time": "2023-07-23T21:58:39+00:00" + "time": "2023-08-22T08:20:46+00:00" }, { "name": "symfony/http-kernel", - "version": "v6.3.3", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "d3b567f0addf695e10b0c6d57564a9bea2e058ee" + "reference": "36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/d3b567f0addf695e10b0c6d57564a9bea2e058ee", - "reference": "d3b567f0addf695e10b0c6d57564a9bea2e058ee", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb", + "reference": "36abb425b4af863ae1fe54d8a8b8b4c76a2bccdb", "shasum": "" }, "require": { @@ -6712,7 +6716,7 @@ "symfony/deprecation-contracts": "^2.5|^3", "symfony/error-handler": "^6.3", "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/http-foundation": "^6.2.7", + "symfony/http-foundation": "^6.3.4", "symfony/polyfill-ctype": "^1.8" }, "conflict": { @@ -6720,7 +6724,7 @@ "symfony/cache": "<5.4", "symfony/config": "<6.1", "symfony/console": "<5.4", - "symfony/dependency-injection": "<6.3", + "symfony/dependency-injection": "<6.3.4", "symfony/doctrine-bridge": "<5.4", "symfony/form": "<5.4", "symfony/http-client": "<5.4", @@ -6744,7 +6748,7 @@ "symfony/config": "^6.1", "symfony/console": "^5.4|^6.0", "symfony/css-selector": "^5.4|^6.0", - "symfony/dependency-injection": "^6.3", + "symfony/dependency-injection": "^6.3.4", "symfony/dom-crawler": "^5.4|^6.0", "symfony/expression-language": "^5.4|^6.0", "symfony/finder": "^5.4|^6.0", @@ -6787,7 +6791,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.3.3" + "source": "https://github.com/symfony/http-kernel/tree/v6.3.4" }, "funding": [ { @@ -6803,7 +6807,7 @@ "type": "tidelift" } ], - "time": "2023-07-31T10:33:00+00:00" + "time": "2023-08-26T13:54:49+00:00" }, { "name": "symfony/mailer", @@ -7040,16 +7044,16 @@ }, { "name": "symfony/polyfill-ctype", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", - "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", + "reference": "ea208ce43cbb04af6867b4fdddb1bdbf84cc28cb", "shasum": "" }, "require": { @@ -7064,7 +7068,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7102,7 +7106,7 @@ "portable" ], "support": { - "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.28.0" }, "funding": [ { @@ -7118,20 +7122,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + "reference": "875e90aeea2777b6f135677f618529449334a612" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", - "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/875e90aeea2777b6f135677f618529449334a612", + "reference": "875e90aeea2777b6f135677f618529449334a612", "shasum": "" }, "require": { @@ -7143,7 +7147,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7183,7 +7187,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.28.0" }, "funding": [ { @@ -7199,20 +7203,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-intl-idn", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-idn.git", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da" + "reference": "ecaafce9f77234a6a449d29e49267ba10499116d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/639084e360537a19f9ee352433b84ce831f3d2da", - "reference": "639084e360537a19f9ee352433b84ce831f3d2da", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/ecaafce9f77234a6a449d29e49267ba10499116d", + "reference": "ecaafce9f77234a6a449d29e49267ba10499116d", "shasum": "" }, "require": { @@ -7226,7 +7230,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7270,7 +7274,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.28.0" }, "funding": [ { @@ -7286,20 +7290,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:30:37+00:00" }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", - "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", + "reference": "8c4ad05dd0120b6a53c1ca374dca2ad0a1c4ed92", "shasum": "" }, "require": { @@ -7311,7 +7315,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7354,7 +7358,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.28.0" }, "funding": [ { @@ -7370,20 +7374,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + "reference": "42292d99c55abe617799667f454222c54c60e229" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", - "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/42292d99c55abe617799667f454222c54c60e229", + "reference": "42292d99c55abe617799667f454222c54c60e229", "shasum": "" }, "require": { @@ -7398,7 +7402,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7437,7 +7441,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.28.0" }, "funding": [ { @@ -7453,20 +7457,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-07-28T09:04:16+00:00" }, { "name": "symfony/polyfill-php72", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php72.git", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97" + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/869329b1e9894268a8a61dabb69153029b7a8c97", - "reference": "869329b1e9894268a8a61dabb69153029b7a8c97", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/70f4aebd92afca2f865444d30a4d2151c13c3179", + "reference": "70f4aebd92afca2f865444d30a4d2151c13c3179", "shasum": "" }, "require": { @@ -7475,7 +7479,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7513,7 +7517,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php72/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php72/tree/v1.28.0" }, "funding": [ { @@ -7529,20 +7533,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php80", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php80.git", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936" + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", - "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/6caa57379c4aec19c0a12a38b59b26487dcfe4b5", + "reference": "6caa57379c4aec19c0a12a38b59b26487dcfe4b5", "shasum": "" }, "require": { @@ -7551,7 +7555,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7596,7 +7600,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php80/tree/v1.28.0" }, "funding": [ { @@ -7612,20 +7616,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/polyfill-php83", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php83.git", - "reference": "508c652ba3ccf69f8c97f251534f229791b52a57" + "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/508c652ba3ccf69f8c97f251534f229791b52a57", - "reference": "508c652ba3ccf69f8c97f251534f229791b52a57", + "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", + "reference": "b0f46ebbeeeda3e9d2faebdfbf4b4eae9b59fa11", "shasum": "" }, "require": { @@ -7635,7 +7639,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7648,7 +7652,10 @@ ], "psr-4": { "Symfony\\Polyfill\\Php83\\": "" - } + }, + "classmap": [ + "Resources/stubs" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -7673,7 +7680,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-php83/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-php83/tree/v1.28.0" }, "funding": [ { @@ -7689,20 +7696,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-08-16T06:22:46+00:00" }, { "name": "symfony/polyfill-uuid", - "version": "v1.27.0", + "version": "v1.28.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-uuid.git", - "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166" + "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/f3cf1a645c2734236ed1e2e671e273eeb3586166", - "reference": "f3cf1a645c2734236ed1e2e671e273eeb3586166", + "url": "https://api.github.com/repos/symfony/polyfill-uuid/zipball/9c44518a5aff8da565c8a55dbe85d2769e6f630e", + "reference": "9c44518a5aff8da565c8a55dbe85d2769e6f630e", "shasum": "" }, "require": { @@ -7717,7 +7724,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "1.27-dev" + "dev-main": "1.28-dev" }, "thanks": { "name": "symfony/polyfill", @@ -7755,7 +7762,7 @@ "uuid" ], "support": { - "source": "https://github.com/symfony/polyfill-uuid/tree/v1.27.0" + "source": "https://github.com/symfony/polyfill-uuid/tree/v1.28.0" }, "funding": [ { @@ -7771,20 +7778,20 @@ "type": "tidelift" } ], - "time": "2022-11-03T14:55:06+00:00" + "time": "2023-01-26T09:26:14+00:00" }, { "name": "symfony/process", - "version": "v6.3.2", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d" + "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d", - "reference": "c5ce962db0d9b6e80247ca5eb9af6472bd4d7b5d", + "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", + "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", "shasum": "" }, "require": { @@ -7816,7 +7823,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v6.3.2" + "source": "https://github.com/symfony/process/tree/v6.3.4" }, "funding": [ { @@ -7832,7 +7839,7 @@ "type": "tidelift" } ], - "time": "2023-07-12T16:00:22+00:00" + "time": "2023-08-07T10:39:22+00:00" }, { "name": "symfony/psr-http-message-bridge", @@ -8423,16 +8430,16 @@ }, { "name": "symfony/var-dumper", - "version": "v6.3.3", + "version": "v6.3.4", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "77fb4f2927f6991a9843633925d111147449ee7a" + "reference": "2027be14f8ae8eae999ceadebcda5b4909b81d45" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/77fb4f2927f6991a9843633925d111147449ee7a", - "reference": "77fb4f2927f6991a9843633925d111147449ee7a", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/2027be14f8ae8eae999ceadebcda5b4909b81d45", + "reference": "2027be14f8ae8eae999ceadebcda5b4909b81d45", "shasum": "" }, "require": { @@ -8487,7 +8494,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v6.3.3" + "source": "https://github.com/symfony/var-dumper/tree/v6.3.4" }, "funding": [ { @@ -8503,7 +8510,7 @@ "type": "tidelift" } ], - "time": "2023-07-31T07:08:24+00:00" + "time": "2023-08-24T14:51:05+00:00" }, { "name": "therobfonz/laravel-mandrill-driver", @@ -8622,16 +8629,16 @@ }, { "name": "twig/twig", - "version": "v3.7.0", + "version": "v3.7.1", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "5cf942bbab3df42afa918caeba947f1b690af64b" + "reference": "a0ce373a0ca3bf6c64b9e3e2124aca502ba39554" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/5cf942bbab3df42afa918caeba947f1b690af64b", - "reference": "5cf942bbab3df42afa918caeba947f1b690af64b", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/a0ce373a0ca3bf6c64b9e3e2124aca502ba39554", + "reference": "a0ce373a0ca3bf6c64b9e3e2124aca502ba39554", "shasum": "" }, "require": { @@ -8641,7 +8648,7 @@ }, "require-dev": { "psr/container": "^1.0|^2.0", - "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" + "symfony/phpunit-bridge": "^5.4.9|^6.3" }, "type": "library", "autoload": { @@ -8677,7 +8684,7 @@ ], "support": { "issues": "https://github.com/twigphp/Twig/issues", - "source": "https://github.com/twigphp/Twig/tree/v3.7.0" + "source": "https://github.com/twigphp/Twig/tree/v3.7.1" }, "funding": [ { @@ -8689,7 +8696,7 @@ "type": "tidelift" } ], - "time": "2023-07-26T07:16:09+00:00" + "time": "2023-08-28T11:09:02+00:00" }, { "name": "vlucas/phpdotenv", @@ -9201,38 +9208,39 @@ }, { "name": "ergebnis/phpstan-rules", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/ergebnis/phpstan-rules.git", - "reference": "99360283faf07a6d553f384183f3551a054c5aeb" + "reference": "119e229c48688946450ccca9f1c57c9ca4fb6f02" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/99360283faf07a6d553f384183f3551a054c5aeb", - "reference": "99360283faf07a6d553f384183f3551a054c5aeb", + "url": "https://api.github.com/repos/ergebnis/phpstan-rules/zipball/119e229c48688946450ccca9f1c57c9ca4fb6f02", + "reference": "119e229c48688946450ccca9f1c57c9ca4fb6f02", "shasum": "" }, "require": { "ext-mbstring": "*", "nikic/php-parser": "^4.2.3", - "php": "~8.0.0 || ~8.1.0 || ~8.2.0", - "phpstan/phpstan": "^1.7.15" + "php": "~8.1.0 || ~8.2.0 || ~8.3.0", + "phpstan/phpstan": "^1.10.21" }, "require-dev": { - "doctrine/orm": "^2.14.3", - "ergebnis/composer-normalize": "^2.30.2", + "doctrine/orm": "^2.16.1", + "ergebnis/composer-normalize": "^2.35.0", "ergebnis/license": "^2.1.0", - "ergebnis/php-cs-fixer-config": "^5.5.2", - "infection/infection": "~0.26.19", - "nette/di": "^3.1.2", - "phpstan/phpstan-deprecation-rules": "^1.0.0", + "ergebnis/php-cs-fixer-config": "^5.13.0", + "ergebnis/phpunit-slow-test-detector": "^2.3.0", + "infection/infection": "~0.27.0", + "nette/di": "^3.1.3", + "phpstan/phpstan-deprecation-rules": "^1.1.4", "phpstan/phpstan-strict-rules": "^1.1.0", - "phpunit/phpunit": "^9.6.7", + "phpunit/phpunit": "^10.3.2", "psalm/plugin-phpunit": "~0.18.4", "psr/container": "^1.1.2", - "rector/rector": "~0.15.25", - "vimeo/psalm": "^5.9.0" + "rector/rector": "~0.17.13", + "vimeo/psalm": "^5.14.1" }, "type": "phpstan-extension", "extra": { @@ -9268,7 +9276,7 @@ "issues": "https://github.com/ergebnis/phpstan-rules/issues", "source": "https://github.com/ergebnis/phpstan-rules" }, - "time": "2023-05-01T17:59:46+00:00" + "time": "2023-08-17T10:28:37+00:00" }, { "name": "fakerphp/faker", @@ -9535,16 +9543,16 @@ }, { "name": "nikic/php-parser", - "version": "v4.16.0", + "version": "v4.17.1", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17" + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/19526a33fb561ef417e822e85f08a00db4059c17", - "reference": "19526a33fb561ef417e822e85f08a00db4059c17", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", "shasum": "" }, "require": { @@ -9585,9 +9593,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.16.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" }, - "time": "2023-06-25T14:52:30+00:00" + "time": "2023-08-13T19:53:39+00:00" }, { "name": "nunomaduro/larastan", @@ -10043,16 +10051,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.10.28", + "version": "1.10.32", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "e4545b55904ebef470423d3ddddb74fa7325497a" + "reference": "c47e47d3ab03137c0e121e77c4d2cb58672f6d44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e4545b55904ebef470423d3ddddb74fa7325497a", - "reference": "e4545b55904ebef470423d3ddddb74fa7325497a", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/c47e47d3ab03137c0e121e77c4d2cb58672f6d44", + "reference": "c47e47d3ab03137c0e121e77c4d2cb58672f6d44", "shasum": "" }, "require": { @@ -10101,7 +10109,7 @@ "type": "tidelift" } ], - "time": "2023-08-08T12:33:42+00:00" + "time": "2023-08-24T21:54:50+00:00" }, { "name": "phpstan/phpstan-deprecation-rules", @@ -10202,16 +10210,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "10.1.3", + "version": "10.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d" + "reference": "cd59bb34756a16ca8253ce9b2909039c227fff71" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be1fe461fdc917de2a29a452ccf2657d325b443d", - "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/cd59bb34756a16ca8253ce9b2909039c227fff71", + "reference": "cd59bb34756a16ca8253ce9b2909039c227fff71", "shasum": "" }, "require": { @@ -10268,7 +10276,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.4" }, "funding": [ { @@ -10276,20 +10284,20 @@ "type": "github" } ], - "time": "2023-07-26T13:45:28+00:00" + "time": "2023-08-31T14:04:38+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "4.0.2", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "5647d65443818959172645e7ed999217360654b6" + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6", - "reference": "5647d65443818959172645e7ed999217360654b6", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { @@ -10329,7 +10337,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2" + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -10337,7 +10345,7 @@ "type": "github" } ], - "time": "2023-05-07T09:13:23+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", @@ -10404,16 +10412,16 @@ }, { "name": "phpunit/php-text-template", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d" + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d", - "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { @@ -10451,7 +10459,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -10459,7 +10468,7 @@ "type": "github" } ], - "time": "2023-02-03T06:56:46+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", @@ -10522,16 +10531,16 @@ }, { "name": "phpunit/phpunit", - "version": "10.3.1", + "version": "10.3.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "d442ce7c4104d5683c12e67e4dcb5058159e9804" + "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d442ce7c4104d5683c12e67e4dcb5058159e9804", - "reference": "d442ce7c4104d5683c12e67e4dcb5058159e9804", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0dafb1175c366dd274eaa9a625e914451506bcd1", + "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1", "shasum": "" }, "require": { @@ -10603,7 +10612,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.1" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.2" }, "funding": [ { @@ -10619,7 +10628,7 @@ "type": "tidelift" } ], - "time": "2023-08-04T06:48:08+00:00" + "time": "2023-08-15T05:34:23+00:00" }, { "name": "sebastian/cli-parser", @@ -10790,16 +10799,16 @@ }, { "name": "sebastian/comparator", - "version": "5.0.0", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c" + "reference": "2db5010a484d53ebf536087a70b4a5423c102372" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/72f01e6586e0caf6af81297897bd112eb7e9627c", - "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372", "shasum": "" }, "require": { @@ -10810,7 +10819,7 @@ "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^10.0" + "phpunit/phpunit": "^10.3" }, "type": "library", "extra": { @@ -10854,7 +10863,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.0" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" }, "funding": [ { @@ -10862,20 +10872,20 @@ "type": "github" } ], - "time": "2023-02-03T07:07:16+00:00" + "time": "2023-08-14T13:18:12+00:00" }, { "name": "sebastian/complexity", - "version": "3.0.0", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6" + "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6", - "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/c70b73893e10757af9c6a48929fa6a333b56a97a", + "reference": "c70b73893e10757af9c6a48929fa6a333b56a97a", "shasum": "" }, "require": { @@ -10911,7 +10921,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.1" }, "funding": [ { @@ -10919,7 +10930,7 @@ "type": "github" } ], - "time": "2023-02-03T06:59:47+00:00" + "time": "2023-08-31T09:55:53+00:00" }, { "name": "sebastian/diff", @@ -11193,16 +11204,16 @@ }, { "name": "sebastian/lines-of-code", - "version": "2.0.0", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130" + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130", - "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/649e40d279e243d985aa8fb6e74dd5bb28dc185d", + "reference": "649e40d279e243d985aa8fb6e74dd5bb28dc185d", "shasum": "" }, "require": { @@ -11238,7 +11249,8 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.1" }, "funding": [ { @@ -11246,7 +11258,7 @@ "type": "github" } ], - "time": "2023-02-03T07:08:02+00:00" + "time": "2023-08-31T09:25:50+00:00" }, { "name": "sebastian/object-enumerator", diff --git a/config/firefly.php b/config/firefly.php index d30a170711..b77f4525a7 100644 --- a/config/firefly.php +++ b/config/firefly.php @@ -110,7 +110,7 @@ return [ 'handle_debts' => true, // see cer.php for exchange rates feature flag. ], - 'version' => '6.0.20', + 'version' => '6.0.21', 'api_version' => '2.0.6', 'db_version' => 20, @@ -148,7 +148,7 @@ return [ 'update_minimum_age' => 7, // notifications - 'available_notifications' => ['bill_reminder', 'new_access_token', 'transaction_creation', 'user_login'], + 'available_notifications' => ['bill_reminder', 'new_access_token', 'transaction_creation', 'user_login', 'rule_action_failures'], 'admin_notifications' => ['admin_new_reg', 'user_new_reg', 'new_version', 'invite_created', 'invite_redeemed'], // enabled languages diff --git a/config/logging.php b/config/logging.php index ced49af529..57d2601851 100644 --- a/config/logging.php +++ b/config/logging.php @@ -24,6 +24,30 @@ declare(strict_types=1); use FireflyIII\Support\Logging\AuditLogger; use Monolog\Handler\SyslogUdpHandler; +// standard config for both log things: +$defaultChannels = ['daily', 'stdout']; +$auditChannels = ['audit_daily', 'audit_stdout']; + + +// validChannels is missing 'stack' because we already check for that one. +$validChannels = ['single', 'papertrail', 'stdout', 'daily', 'syslog', 'errorlog']; +$validAuditChannels = ['audit_papertrail', 'audit_stdout', 'audit_stdout', 'audit_daily', 'audit_syslog', 'audit_errorlog']; + +// which settings did the user set, if any? +$defaultLogChannel = (string)envNonEmpty('LOG_CHANNEL', 'stack'); +$auditLogChannel = (string)envNonEmpty('AUDIT_LOG_CHANNEL', ''); + +if ('stack' === $defaultLogChannel) { + $defaultChannels = ['daily', 'stdout']; +} +if (in_array($defaultLogChannel, $validChannels, true)) { + $defaultChannels = [$defaultLogChannel]; +} + +if (in_array($auditLogChannel, $validAuditChannels, true)) { + $auditChannels = [$auditLogChannel]; +} + return [ /* |-------------------------------------------------------------------------- @@ -53,16 +77,27 @@ return [ */ 'channels' => [ - // default channels for 'stack' and audit logs: - 'stack' => [ + /* + * 'stack' and 'audit' are the two "generic" channels that + * are valid destinations for logs. + */ + 'stack' => [ 'driver' => 'stack', - 'channels' => ['daily', 'stdout'], + 'channels' => $defaultChannels, ], - 'audit' => [ + 'audit' => [ 'driver' => 'stack', - 'channels' => ['audit_daily', 'audit_stdout'], + 'channels' => $auditChannels, ], - 'papertrail' => [ + /* + * There are 6 valid destinations for the normal logs, listed below: + */ + 'single' => [ + 'driver' => 'single', + 'path' => storage_path('logs/laravel.log'), + 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), + ], + 'papertrail' => [ 'driver' => 'monolog', 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), 'handler' => SyslogUdpHandler::class, @@ -71,55 +106,65 @@ return [ 'port' => env('PAPERTRAIL_PORT'), ], ], - - // single laravel log file: - 'single' => [ - 'driver' => 'single', - 'path' => storage_path('logs/laravel.log'), - 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), - ], - - // stdout, used in stack 'stack' by default: - 'stdout' => [ + 'stdout' => [ 'driver' => 'single', 'path' => 'php://stdout', 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), ], - - // daily, used in stack 'stack' by default: - 'daily' => [ + 'daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/ff3-' . PHP_SAPI . '.log'), 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), 'days' => 7, ], + 'syslog' => [ + 'driver' => 'syslog', + 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), + ], + 'errorlog' => [ + 'driver' => 'errorlog', + 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), + ], - // the audit log destinations: - 'audit_daily' => [ + /* + * There are 5 valid destinations for the audit logs, listed below. + * The only one missing is "single". + */ + 'audit_papertrail' => [ + 'driver' => 'monolog', + 'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'), + 'handler' => SyslogUdpHandler::class, + 'tap' => [AuditLogger::class], + 'handler_with' => [ + 'host' => env('PAPERTRAIL_HOST'), + 'port' => env('PAPERTRAIL_PORT'), + ], + ], + 'audit_stdout' => [ + 'driver' => 'single', + 'path' => 'php://stdout', + 'tap' => [AuditLogger::class], + 'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'), + ], + 'audit_daily' => [ 'driver' => 'daily', 'path' => storage_path('logs/ff3-audit.log'), 'tap' => [AuditLogger::class], 'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'), 'days' => 90, ], - 'audit_stdout' => [ - 'driver' => 'single', - 'path' => 'php://stdout', + 'audit_syslog' => [ + 'driver' => 'syslog', + 'tap' => [AuditLogger::class], + 'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'), + ], + 'audit_errorlog' => [ + 'driver' => 'errorlog', 'tap' => [AuditLogger::class], 'level' => envNonEmpty('AUDIT_LOG_LEVEL', 'info'), ], - // syslog destination - 'syslog' => [ - 'driver' => 'syslog', - 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), - ], - // errorlog destination - 'errorlog' => [ - 'driver' => 'errorlog', - 'level' => envNonEmpty('APP_LOG_LEVEL', 'info'), - ], ], ]; diff --git a/frontend/src/i18n/ca_ES/index.js b/frontend/src/i18n/ca_ES/index.js index da9f0b64f1..bc2e907979 100644 --- a/frontend/src/i18n/ca_ES/index.js +++ b/frontend/src/i18n/ca_ES/index.js @@ -105,9 +105,9 @@ export default { "rule_trigger_destination_account_nr_contains_choice": "El n\u00famero \/ IBAN del compte de dest\u00ed cont\u00e9..", "rule_trigger_transaction_type_choice": "La transacci\u00f3 \u00e9s del tipus..", "rule_trigger_category_is_choice": "La categoria \u00e9s..", - "rule_trigger_amount_less_choice": "Amount is less than or equal to ..", + "rule_trigger_amount_less_choice": "La quantitat \u00e9s menor o igual a ..", "rule_trigger_amount_is_choice": "La quantitat \u00e9s..", - "rule_trigger_amount_more_choice": "Amount is more than or equal to..", + "rule_trigger_amount_more_choice": "La quantitat \u00e9s major o igual a..", "rule_trigger_description_starts_choice": "La descripci\u00f3 comen\u00e7a per..", "rule_trigger_description_ends_choice": "La descripci\u00f3 acaba amb..", "rule_trigger_description_contains_choice": "La descripci\u00f3 cont\u00e9..", @@ -140,7 +140,7 @@ export default { "rule_trigger_external_id_is_choice": "L'ID externa \u00e9s..", "rule_trigger_internal_reference_is_choice": "La refer\u00e8ncia interna \u00e9s..", "rule_trigger_journal_id_choice": "L'ID del llibre de transaccions \u00e9s..", - "rule_trigger_any_external_url_choice": "Transaction has an (any) external URL", + "rule_trigger_any_external_url_choice": "La transaci\u00f3 t\u00e9 (cap) URL externa", "rule_trigger_no_external_url_choice": "La transacci\u00f3 no t\u00e9 URL extern", "rule_trigger_id_choice": "L'ID de la transacci\u00f3 \u00e9s..", "rule_action_delete_transaction_choice": "ELIMINAR transacci\u00f3(!)", diff --git a/frontend/src/i18n/ko_KR/index.js b/frontend/src/i18n/ko_KR/index.js index 9f04a239c6..c8eff4e54b 100644 --- a/frontend/src/i18n/ko_KR/index.js +++ b/frontend/src/i18n/ko_KR/index.js @@ -105,9 +105,9 @@ export default { "rule_trigger_destination_account_nr_contains_choice": "\ub300\uc0c1 \uacc4\uc88c \ubc88\ud638 \/ IBAN\uc740...\ub97c \ud3ec\ud568\ud569\ub2c8\ub2e4", "rule_trigger_transaction_type_choice": "\uac70\ub798\ub294 .. \uc720\ud615\uc785\ub2c8\ub2e4", "rule_trigger_category_is_choice": "\uce74\ud14c\uace0\ub9ac\ub294 ..", - "rule_trigger_amount_less_choice": "Amount is less than or equal to ..", + "rule_trigger_amount_less_choice": "\uae08\uc561\uc774 .. \uc640 \uc791\uac70\ub098 \uac19\uc74c", "rule_trigger_amount_is_choice": "\uae08\uc561\uc740..", - "rule_trigger_amount_more_choice": "Amount is more than or equal to..", + "rule_trigger_amount_more_choice": "\uae08\uc561\uc774 .. \uc640 \ud06c\uac70\ub098 \uac19\uc74c", "rule_trigger_description_starts_choice": "\uc124\uba85\uc774 ..\ub85c \uc2dc\uc791\ud569\ub2c8\ub2e4", "rule_trigger_description_ends_choice": "\uc124\uba85\uc774 ..\ub85c \ub05d\ub0a9\ub2c8\ub2e4", "rule_trigger_description_contains_choice": "\uc124\uba85\uc740 ..\ub97c \ud3ec\ud568\ud569\ub2c8\ub2e4", @@ -140,7 +140,7 @@ export default { "rule_trigger_external_id_is_choice": "\uc678\ubd80 ID\ub294..", "rule_trigger_internal_reference_is_choice": "\ub0b4\ubd80 \ucc38\uc870\ub294..", "rule_trigger_journal_id_choice": "\uac70\ub798 \uc800\ub110 ID\ub294..", - "rule_trigger_any_external_url_choice": "Transaction has an (any) external URL", + "rule_trigger_any_external_url_choice": "\uac70\ub798\uc5d0 (\uc5b4\ub5a4) \uc678\ubd80 URL\uc774 \uc788\uc74c", "rule_trigger_no_external_url_choice": "\uac70\ub798\uc5d0 \uc678\ubd80 URL\uc774 \uc5c6\uc2b5\ub2c8\ub2e4", "rule_trigger_id_choice": "\uac70\ub798 ID\ub294..", "rule_action_delete_transaction_choice": "\uac70\ub798 \uc0ad\uc81c(!)", diff --git a/frontend/src/i18n/pl_PL/index.js b/frontend/src/i18n/pl_PL/index.js index ac3493ecab..97a56a93e5 100644 --- a/frontend/src/i18n/pl_PL/index.js +++ b/frontend/src/i18n/pl_PL/index.js @@ -105,9 +105,9 @@ export default { "rule_trigger_destination_account_nr_contains_choice": "Numer konta docelowego \/ IBAN zawiera..", "rule_trigger_transaction_type_choice": "Transakcja jest typu..", "rule_trigger_category_is_choice": "Kategoria to..", - "rule_trigger_amount_less_choice": "Amount is less than or equal to ..", + "rule_trigger_amount_less_choice": "Kwota jest mniejsza lub r\u00f3wna ..", "rule_trigger_amount_is_choice": "Kwota to..", - "rule_trigger_amount_more_choice": "Amount is more than or equal to..", + "rule_trigger_amount_more_choice": "Kwota jest wi\u0119ksza lub r\u00f3wna..", "rule_trigger_description_starts_choice": "Opis zaczyna si\u0119 od..", "rule_trigger_description_ends_choice": "Opis ko\u0144czy si\u0119 na..", "rule_trigger_description_contains_choice": "Opis zawiera..", @@ -140,7 +140,7 @@ export default { "rule_trigger_external_id_is_choice": "Zewn\u0119trzne ID to..", "rule_trigger_internal_reference_is_choice": "Wewn\u0119trzne odwo\u0142anie to..", "rule_trigger_journal_id_choice": "ID dziennika transakcji to..", - "rule_trigger_any_external_url_choice": "Transaction has an (any) external URL", + "rule_trigger_any_external_url_choice": "Transakcja ma (dowolny) zewn\u0119trzny adres URL", "rule_trigger_no_external_url_choice": "Transakcja nie ma zewn\u0119trznego adresu URL", "rule_trigger_id_choice": "Identyfikator transakcji to..", "rule_action_delete_transaction_choice": "USU\u0143 transakcj\u0119(!)", diff --git a/frontend/src/i18n/pt_BR/index.js b/frontend/src/i18n/pt_BR/index.js index a31046d9e5..b477d61600 100644 --- a/frontend/src/i18n/pt_BR/index.js +++ b/frontend/src/i18n/pt_BR/index.js @@ -105,9 +105,9 @@ export default { "rule_trigger_destination_account_nr_contains_choice": "N\u00famero da conta de destino (IBAN) cont\u00e9m..", "rule_trigger_transaction_type_choice": "Transa\u00e7\u00e3o \u00e9 do tipo..", "rule_trigger_category_is_choice": "A categoria \u00e9..", - "rule_trigger_amount_less_choice": "Amount is less than or equal to ..", + "rule_trigger_amount_less_choice": "Valor \u00e9 menor ou igual a ..", "rule_trigger_amount_is_choice": "Quantia \u00e9..", - "rule_trigger_amount_more_choice": "Amount is more than or equal to..", + "rule_trigger_amount_more_choice": "Valor \u00e9 maior ou igual a..", "rule_trigger_description_starts_choice": "Descri\u00e7\u00e3o come\u00e7a com..", "rule_trigger_description_ends_choice": "Descri\u00e7\u00e3o termina com..", "rule_trigger_description_contains_choice": "Descri\u00e7\u00e3o cont\u00e9m..", @@ -140,7 +140,7 @@ export default { "rule_trigger_external_id_is_choice": "ID externo \u00e9..", "rule_trigger_internal_reference_is_choice": "Refer\u00eancia interna \u00e9..", "rule_trigger_journal_id_choice": "ID do livro de transa\u00e7\u00e3o \u00e9..", - "rule_trigger_any_external_url_choice": "Transaction has an (any) external URL", + "rule_trigger_any_external_url_choice": "A transa\u00e7\u00e3o tem uma URL externa (qualquer)", "rule_trigger_no_external_url_choice": "A transa\u00e7\u00e3o n\u00e3o tem um link externo", "rule_trigger_id_choice": "O identificador da transa\u00e7\u00e3o \u00e9..", "rule_action_delete_transaction_choice": "EXCLUIR transa\u00e7\u00e3o(!)", diff --git a/frontend/src/i18n/sl_SI/index.js b/frontend/src/i18n/sl_SI/index.js index ad3cc68dd2..fbffaeb9cb 100644 --- a/frontend/src/i18n/sl_SI/index.js +++ b/frontend/src/i18n/sl_SI/index.js @@ -50,8 +50,8 @@ export default { "transactions": "Transakcije", "title_expenses": "Stro\u0161ki", "title_withdrawal": "Stro\u0161ki", - "title_revenue": "Dohodki \/ prihodki", - "title_deposit": "Dohodki \/ prihodki", + "title_revenue": "Dohodki prihodki", + "title_deposit": "Dohodki\/prihodki", "title_transfer": "Prenosi", "title_transfers": "Prenosi", "asset_accounts": "Premo\u017eenjski ra\u010duni", @@ -60,7 +60,7 @@ export default { "liabilities_accounts": "Obveznosti" }, "firefly": { - "administration_index": "Financial administration", + "administration_index": "Finan\u010dna administracija", "actions": "Dejanja", "edit": "uredi", "delete": "izbri\u0161i", @@ -81,87 +81,87 @@ export default { "budgeted": "Prora\u010dun", "spent": "Porabljeno", "no_bill": "(ni ra\u010duna)", - "rule_trigger_source_account_starts_choice": "Source account name starts with..", - "rule_trigger_source_account_ends_choice": "Source account name ends with..", - "rule_trigger_source_account_is_choice": "Source account name is..", - "rule_trigger_source_account_contains_choice": "Source account name contains..", - "rule_trigger_account_id_choice": "Either account ID is exactly..", - "rule_trigger_source_account_id_choice": "Source account ID is exactly..", - "rule_trigger_destination_account_id_choice": "Destination account ID is exactly..", - "rule_trigger_account_is_cash_choice": "Either account is cash", - "rule_trigger_source_is_cash_choice": "Source account is (cash) account", - "rule_trigger_destination_is_cash_choice": "Destination account is (cash) account", - "rule_trigger_source_account_nr_starts_choice": "Source account number \/ IBAN starts with..", - "rule_trigger_source_account_nr_ends_choice": "Source account number \/ IBAN ends with..", - "rule_trigger_source_account_nr_is_choice": "Source account number \/ IBAN is..", - "rule_trigger_source_account_nr_contains_choice": "Source account number \/ IBAN contains..", - "rule_trigger_destination_account_starts_choice": "Destination account name starts with..", - "rule_trigger_destination_account_ends_choice": "Destination account name ends with..", - "rule_trigger_destination_account_is_choice": "Destination account name is..", - "rule_trigger_destination_account_contains_choice": "Destination account name contains..", - "rule_trigger_destination_account_nr_starts_choice": "Destination account number \/ IBAN starts with..", - "rule_trigger_destination_account_nr_ends_choice": "Destination account number \/ IBAN ends with..", - "rule_trigger_destination_account_nr_is_choice": "Destination account number \/ IBAN is..", - "rule_trigger_destination_account_nr_contains_choice": "Destination account number \/ IBAN contains..", + "rule_trigger_source_account_starts_choice": "Ime izvornega ra\u010duna se za\u010dne z ...", + "rule_trigger_source_account_ends_choice": "Ime izvornega ra\u010duna se kon\u010da s\/z ...", + "rule_trigger_source_account_is_choice": "Ime izvornega ra\u010duna je ...", + "rule_trigger_source_account_contains_choice": "Ime izvornega ra\u010duna vsebuje ...", + "rule_trigger_account_id_choice": "ID ra\u010duna je natan\u010dno ...", + "rule_trigger_source_account_id_choice": "ID izvornega ra\u010duna je to\u010dno ...", + "rule_trigger_destination_account_id_choice": "ID ciljnega ra\u010duna je to\u010dno ...", + "rule_trigger_account_is_cash_choice": "Kateri koli ra\u010dun je gotovina", + "rule_trigger_source_is_cash_choice": "Izvorni ra\u010dun je gotovinski ra\u010dun", + "rule_trigger_destination_is_cash_choice": "Ciljni ra\u010dun je (gotovinski) ra\u010dun", + "rule_trigger_source_account_nr_starts_choice": "Izvorna \u0161tevilka ra\u010duna \/ IBAN se za\u010dne z ...", + "rule_trigger_source_account_nr_ends_choice": "Izvorna \u0161tevilka ra\u010duna \/ IBAN se kon\u010da z ...", + "rule_trigger_source_account_nr_is_choice": "Izvorna \u0161tevilka ra\u010duna \/ IBAN je ...", + "rule_trigger_source_account_nr_contains_choice": "Izvorna \u0161tevilka ra\u010duna \/ IBAN vsebuje ...", + "rule_trigger_destination_account_starts_choice": "Ime ciljnega ra\u010duna se za\u010dne z ...", + "rule_trigger_destination_account_ends_choice": "Ime ciljnega ra\u010duna se kon\u010da z ...", + "rule_trigger_destination_account_is_choice": "Ime ciljnega ra\u010duna je ...", + "rule_trigger_destination_account_contains_choice": "Ime ciljnega ra\u010duna vsebuje ...", + "rule_trigger_destination_account_nr_starts_choice": "\u0160tevilka ciljnega ra\u010duna \/ IBAN se za\u010dne s\/z ...", + "rule_trigger_destination_account_nr_ends_choice": "\u0160tevilka ciljnega ra\u010duna \/ IBAN se kon\u010da s\/z ...", + "rule_trigger_destination_account_nr_is_choice": "\u0160tevilka ciljnega ra\u010duna \/ IBAN je ...", + "rule_trigger_destination_account_nr_contains_choice": "\u0160tevilka ciljnega ra\u010duna \/ IBAN vsebuje ...", "rule_trigger_transaction_type_choice": "Tip transakcije je..", "rule_trigger_category_is_choice": "Kategorija je..", - "rule_trigger_amount_less_choice": "Amount is less than or equal to ..", + "rule_trigger_amount_less_choice": "Znesek je manj\u0161i ali enak ...", "rule_trigger_amount_is_choice": "Znesek je..", - "rule_trigger_amount_more_choice": "Amount is more than or equal to..", + "rule_trigger_amount_more_choice": "Znesek je ve\u010dji ali enak ...", "rule_trigger_description_starts_choice": "Opis se za\u010dne s\/z..", "rule_trigger_description_ends_choice": "Opis se kon\u010da z..", "rule_trigger_description_contains_choice": "Opis vsebuje..", "rule_trigger_description_is_choice": "Opis je..", - "rule_trigger_date_on_choice": "Transaction date is..", - "rule_trigger_date_before_choice": "Transaction date is before..", - "rule_trigger_date_after_choice": "Transaction date is after..", - "rule_trigger_created_at_on_choice": "Transaction was made on..", - "rule_trigger_updated_at_on_choice": "Transaction was last edited on..", + "rule_trigger_date_on_choice": "Datum transakcije je ...", + "rule_trigger_date_before_choice": "Datum transakcije je pred ...", + "rule_trigger_date_after_choice": "Datum transakcije je po ...", + "rule_trigger_created_at_on_choice": "Transakcija je bila izvedena dne ...", + "rule_trigger_updated_at_on_choice": "Transakcija je bila nazadnje urejena ...", "rule_trigger_budget_is_choice": "Prora\u010dun je..", - "rule_trigger_tag_is_choice": "Any tag is..", + "rule_trigger_tag_is_choice": "Vsaka oznaka je ...", "rule_trigger_currency_is_choice": "Valuta transakcije je..", - "rule_trigger_foreign_currency_is_choice": "Transaction foreign currency is..", + "rule_trigger_foreign_currency_is_choice": "Tuja valuta transakcije je ...", "rule_trigger_has_attachments_choice": "Ima vsaj toliko priponk", "rule_trigger_has_no_category_choice": "Nima kategorije", "rule_trigger_has_any_category_choice": "Ima kategorijo", "rule_trigger_has_no_budget_choice": "Nima prora\u010duna", "rule_trigger_has_any_budget_choice": "Ima (katerikoli) prora\u010dun", "rule_trigger_has_no_bill_choice": "Nima ra\u010duna", - "rule_trigger_has_any_bill_choice": "Has a (any) bill", + "rule_trigger_has_any_bill_choice": "Ima (kateri koli) trajnik", "rule_trigger_has_no_tag_choice": "Nima oznak", "rule_trigger_has_any_tag_choice": "Ima eno ali ve\u010d oznak", "rule_trigger_any_notes_choice": "Ima zaznamke", "rule_trigger_no_notes_choice": "Nima zaznamkov", "rule_trigger_notes_is_choice": "Opombe so..", - "rule_trigger_notes_contains_choice": "Notes contain..", - "rule_trigger_notes_starts_choice": "Notes start with..", - "rule_trigger_notes_ends_choice": "Notes end with..", + "rule_trigger_notes_contains_choice": "Opombe vsebujejo ...", + "rule_trigger_notes_starts_choice": "Opombe se za\u010dnejo s\/z ...", + "rule_trigger_notes_ends_choice": "Opombe se kon\u010dajo s\/z ...", "rule_trigger_bill_is_choice": "Ra\u010dun je..", - "rule_trigger_external_id_is_choice": "External ID is..", - "rule_trigger_internal_reference_is_choice": "Internal reference is..", - "rule_trigger_journal_id_choice": "Transaction journal ID is..", - "rule_trigger_any_external_url_choice": "Transaction has an (any) external URL", - "rule_trigger_no_external_url_choice": "Transaction has no external URL", - "rule_trigger_id_choice": "Transaction ID is..", - "rule_action_delete_transaction_choice": "DELETE transaction(!)", - "rule_action_set_category_choice": "Set category to ..", + "rule_trigger_external_id_is_choice": "Zunanji ID je ...", + "rule_trigger_internal_reference_is_choice": "Notranja referenca je ..", + "rule_trigger_journal_id_choice": "ID dnevnika transakcij je ...", + "rule_trigger_any_external_url_choice": "Transakcija ima (kateri koli) zunanji URL", + "rule_trigger_no_external_url_choice": "Transakcija nima zunanjega URL-ja", + "rule_trigger_id_choice": "ID transakcije je ...", + "rule_action_delete_transaction_choice": "IZBRI\u0160ITE transakcijo (!)", + "rule_action_set_category_choice": "Nastavi kategorijo na ...", "rule_action_clear_category_choice": "Po\u010disti kategorijo", - "rule_action_set_budget_choice": "Set budget to ..", + "rule_action_set_budget_choice": "Nastavi prora\u010dun na ...", "rule_action_clear_budget_choice": "Po\u010disti prora\u010dun", "rule_action_add_tag_choice": "Dodaj oznako ..", - "rule_action_remove_tag_choice": "Remove tag ..", + "rule_action_remove_tag_choice": "Odstrani oznako ...", "rule_action_remove_all_tags_choice": "Odstrani vse oznake", - "rule_action_set_description_choice": "Set description to ..", + "rule_action_set_description_choice": "Nastavi opis na ...", "rule_action_update_piggy_choice": "Add \/ remove transaction amount in piggy bank ..", - "rule_action_append_description_choice": "Append description with ..", - "rule_action_prepend_description_choice": "Prepend description with ..", - "rule_action_set_source_account_choice": "Set source account to ..", - "rule_action_set_destination_account_choice": "Set destination account to ..", - "rule_action_append_notes_choice": "Append notes with ..", - "rule_action_prepend_notes_choice": "Prepend notes with ..", + "rule_action_append_description_choice": "Za opis dodaj ...", + "rule_action_prepend_description_choice": "Pred opis dodaj ...", + "rule_action_set_source_account_choice": "Nastavi izvorni ra\u010dun na ...", + "rule_action_set_destination_account_choice": "Nastavi ciljni ra\u010dun na ...", + "rule_action_append_notes_choice": "Za opombo dodaj ...", + "rule_action_prepend_notes_choice": "Pred opombo dodaj ...", "rule_action_clear_notes_choice": "Odstrani opombe", - "rule_action_set_notes_choice": "Set notes to ..", - "rule_action_link_to_bill_choice": "Link to a bill ..", + "rule_action_set_notes_choice": "Nastavi opombe na ...", + "rule_action_link_to_bill_choice": "Pove\u017ei s trajnikom ...", "rule_action_convert_deposit_choice": "Pretvori transakcijo v polog", "rule_action_convert_withdrawal_choice": "Pretvori transakcijo v odliv", "rule_action_convert_transfer_choice": "Pretvori transakcijo v prenos", @@ -185,7 +185,7 @@ export default { "asset_accounts": "premo\u017eenjski ra\u010duni", "expense_accounts": "Ra\u010duni stro\u0161kov", "liabilities_accounts": "Obveznosti", - "undefined_accounts": "Accounts", + "undefined_accounts": "Ra\u010duni", "name": "Ime", "revenue_accounts": "Ra\u010dun prihodkov", "description": "Opis", @@ -213,13 +213,13 @@ export default { "transactions": "Transakcije", "balance": "Stanje", "budgets": "Prora\u010duni", - "subscriptions": "Subscriptions", + "subscriptions": "Naro\u010dnine", "welcome_back": "Kaj dogaja?", "bills_to_pay": "Trajnik za pla\u010dilo", "net_worth": "Neto vrednost", "pref_last365": "Zadnje leto", - "pref_last90": "Last 90 days", - "pref_last30": "Last 30 days", + "pref_last90": "Zadnjih 90 dni", + "pref_last30": "Zadnjih 30 dni", "pref_last7": "Zadnjih 7 dni", "pref_YTD": "Leto do datuma", "pref_QTD": "Quarter to date", diff --git a/frontend/src/layouts/MainLayout.vue b/frontend/src/layouts/MainLayout.vue index 31432a3fe3..a09beb3158 100644 --- a/frontend/src/layouts/MainLayout.vue +++ b/frontend/src/layouts/MainLayout.vue @@ -338,7 +338,7 @@ page container: q-ma-xs (margin all, xs) AND q-mb-md to give the page content so
- Firefly III v v6.0.19 © James Cole, AGPL-3.0-or-later. + Firefly III v v6.0.21 © James Cole, AGPL-3.0-or-later.
diff --git a/package-lock.json b/package-lock.json index e9e9f42d92..15c744d27c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,9 +7,10 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.4.0", "@popperjs/core": "^2.11.8", - "alpinejs": "^3.12.3", + "alpinejs": "^3.13.0", "bootstrap": "^5.3.0", - "chart.js": "^4.3.3", + "bootstrap5-autocomplete": "^1.1.20", + "chart.js": "^4.4.0", "chartjs-adapter-date-fns": "^3.0.0", "chartjs-chart-sankey": "^0.12.0", "date-fns": "^2.30.0", @@ -17,17 +18,17 @@ "store": "^2.0.12" }, "devDependencies": { - "axios": "^1.1.2", - "laravel-vite-plugin": "^0.7.5", - "sass": "^1.64.2", + "axios": "^1.5.0", + "laravel-vite-plugin": "^0.8.0", + "sass": "^1.66.1", "vite": "^4.0.0", "vite-plugin-manifest-sri": "^0.1.0" } }, "node_modules/@babel/runtime": { - "version": "7.22.10", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.10.tgz", - "integrity": "sha512-21t/fkKLMZI4pqP2wlmsQAWnYW1PDyKyyUV4vCi+B25ydmdaYTKXPwCj0BzSUnZf4seIiYvSA3jcZ3gdsMFkLQ==", + "version": "7.22.11", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz", + "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -424,9 +425,9 @@ "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==" }, "node_modules/alpinejs": { - "version": "3.12.3", - "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.12.3.tgz", - "integrity": "sha512-fLz2dfYQ3xCk7Ip8LiIpV2W+9brUyex2TAE7Z0BCvZdUDklJE+n+a8gCgLWzfZ0GzZNZu7HUP8Z0z6Xbm6fsSA==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.0.tgz", + "integrity": "sha512-7FYR1Yz3evIjlJD1mZ3SYWSw+jlOmQGeQ1QiSufSQ6J84XMQFkzxm6OobiZ928SfqhGdoIp2SsABNsS4rXMMJw==", "dependencies": { "@vue/reactivity": "~3.1.1" } @@ -451,9 +452,9 @@ "dev": true }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", + "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -462,9 +463,9 @@ } }, "node_modules/bignumber.js": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz", - "integrity": "sha512-pHm4LsMJ6lzgNGVfZHjMoO8sdoRhOzOH4MLmY65Jg70bpxCKu5iOHNJyfF6OyvYw7t8Fpf35RuzUyqnQsj8Vig==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", + "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", "engines": { "node": "*" } @@ -496,6 +497,11 @@ "@popperjs/core": "^2.11.8" } }, + "node_modules/bootstrap5-autocomplete": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/bootstrap5-autocomplete/-/bootstrap5-autocomplete-1.1.20.tgz", + "integrity": "sha512-lvX/Za+GnZ7fC1NqVXQr4DWA0eQMR+/uyFjTasdfNSwAMTFhBTIexCsEM+0pXiKdJJnZUXbfcxaNxW1I0rAwLw==" + }, "node_modules/braces": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", @@ -509,9 +515,9 @@ } }, "node_modules/chart.js": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.3.tgz", - "integrity": "sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz", + "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -683,9 +689,9 @@ } }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -718,9 +724,9 @@ } }, "node_modules/immutable": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.2.tgz", - "integrity": "sha512-oGXzbEDem9OOpDWZu88jGiYCvIsLHMvGw+8OXlpsvTFvIQplQbjg1B1cvKg8f7Hoch6+NGjpPsH1Fr+Mc2D1aA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.4.tgz", + "integrity": "sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA==", "dev": true }, "node_modules/is-binary-path": { @@ -766,9 +772,9 @@ } }, "node_modules/laravel-vite-plugin": { - "version": "0.7.8", - "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-0.7.8.tgz", - "integrity": "sha512-HWYqpQYHR3kEQ1LsHX7gHJoNNf0bz5z5mDaHBLzS+PGLCTmYqlU5/SZyeEgObV7z7bC/cnStYcY9H1DI1D5Udg==", + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/laravel-vite-plugin/-/laravel-vite-plugin-0.8.0.tgz", + "integrity": "sha512-6VjLI+azBpeK6rWBiKcb/En5GnTdYpL0U4zS8gXYvb2/VSq4mlau5H3NWpSktUDBMM1b97LLgICx5zevi8IY0w==", "dev": true, "dependencies": { "picocolors": "^1.0.0", @@ -853,9 +859,9 @@ } }, "node_modules/postcss": { - "version": "8.4.27", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.27.tgz", - "integrity": "sha512-gY/ACJtJPSmUFPDCHtX78+01fHa64FaU4zaaWfuh1MhGJISufJAH4cun6k/8fwsHYeK4UQmENQK+tRLCFJE8JQ==", + "version": "8.4.29", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz", + "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==", "dev": true, "funding": [ { @@ -904,9 +910,9 @@ "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, "node_modules/rollup": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz", - "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==", + "version": "3.28.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz", + "integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==", "dev": true, "bin": { "rollup": "dist/bin/rollup" @@ -920,9 +926,9 @@ } }, "node_modules/sass": { - "version": "1.65.1", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.65.1.tgz", - "integrity": "sha512-9DINwtHmA41SEd36eVPQ9BJKpn7eKDQmUHmpI0y5Zv2Rcorrh0zS+cFrt050hdNbmmCNKTW3hV5mWfuegNRsEA==", + "version": "1.66.1", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.66.1.tgz", + "integrity": "sha512-50c+zTsZOJVgFfTgwwEzkjA3/QACgdNsKueWPyAR0mRINIvLAStVQBbPg14iuqEQ74NPDbXzJARJ/O4SI1zftA==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", diff --git a/package.json b/package.json index 2861740e15..10d2a3157f 100644 --- a/package.json +++ b/package.json @@ -6,18 +6,19 @@ "build": "vite build" }, "devDependencies": { - "axios": "^1.1.2", - "laravel-vite-plugin": "^0.7.5", - "sass": "^1.64.2", + "axios": "^1.5.0", + "laravel-vite-plugin": "^0.8.0", + "sass": "^1.66.1", "vite": "^4.0.0", "vite-plugin-manifest-sri": "^0.1.0" }, "dependencies": { "@fortawesome/fontawesome-free": "^6.4.0", "@popperjs/core": "^2.11.8", - "alpinejs": "^3.12.3", + "alpinejs": "^3.13.0", "bootstrap": "^5.3.0", - "chart.js": "^4.3.3", + "bootstrap5-autocomplete": "^1.1.20", + "chart.js": "^4.4.0", "chartjs-adapter-date-fns": "^3.0.0", "chartjs-chart-sankey": "^0.12.0", "date-fns": "^2.30.0", diff --git a/public/build/assets/dashboard-40253f13.js b/public/build/assets/dashboard-3bf5d492.js similarity index 63% rename from public/build/assets/dashboard-40253f13.js rename to public/build/assets/dashboard-3bf5d492.js index a55321e08f..29cafa1c44 100644 --- a/public/build/assets/dashboard-40253f13.js +++ b/public/build/assets/dashboard-3bf5d492.js @@ -1,46 +1,46 @@ -var ve=Object.defineProperty;var be=(t,e,a)=>e in t?ve(t,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[e]=a;var R=(t,e,a)=>(be(t,typeof e!="symbol"?e+"":e,a),a);function bind$4(t,e){return function(){return t.apply(e,arguments)}}const{toString:toString$7}=Object.prototype,{getPrototypeOf}=Object,kindOf=(t=>e=>{const a=toString$7.call(e);return t[a]||(t[a]=a.slice(8,-1).toLowerCase())})(Object.create(null)),kindOfTest=t=>(t=t.toLowerCase(),e=>kindOf(e)===t),typeOfTest=t=>e=>typeof e===t,{isArray:isArray$e}=Array,isUndefined=typeOfTest("undefined");function isBuffer$3(t){return t!==null&&!isUndefined(t)&&t.constructor!==null&&!isUndefined(t.constructor)&&isFunction$6(t.constructor.isBuffer)&&t.constructor.isBuffer(t)}const isArrayBuffer=kindOfTest("ArrayBuffer");function isArrayBufferView(t){let e;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?e=ArrayBuffer.isView(t):e=t&&t.buffer&&isArrayBuffer(t.buffer),e}const isString$1=typeOfTest("string"),isFunction$6=typeOfTest("function"),isNumber$1=typeOfTest("number"),isObject$c=t=>t!==null&&typeof t=="object",isBoolean=t=>t===!0||t===!1,isPlainObject=t=>{if(kindOf(t)!=="object")return!1;const e=getPrototypeOf(t);return(e===null||e===Object.prototype||Object.getPrototypeOf(e)===null)&&!(Symbol.toStringTag in t)&&!(Symbol.iterator in t)},isDate$1=kindOfTest("Date"),isFile=kindOfTest("File"),isBlob=kindOfTest("Blob"),isFileList=kindOfTest("FileList"),isStream=t=>isObject$c(t)&&isFunction$6(t.pipe),isFormData=t=>{let e;return t&&(typeof FormData=="function"&&t instanceof FormData||isFunction$6(t.append)&&((e=kindOf(t))==="formdata"||e==="object"&&isFunction$6(t.toString)&&t.toString()==="[object FormData]"))},isURLSearchParams=kindOfTest("URLSearchParams"),trim$2=t=>t.trim?t.trim():t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function forEach(t,e,{allOwnKeys:a=!1}={}){if(t===null||typeof t>"u")return;let n,r;if(typeof t!="object"&&(t=[t]),isArray$e(t))for(n=0,r=t.length;n0;)if(r=a[n],e===r.toLowerCase())return r;return null}const _global=(()=>typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global)(),isContextDefined=t=>!isUndefined(t)&&t!==_global;function merge$1(){const{caseless:t}=isContextDefined(this)&&this||{},e={},a=(n,r)=>{const i=t&&findKey$1(e,r)||r;isPlainObject(e[i])&&isPlainObject(n)?e[i]=merge$1(e[i],n):isPlainObject(n)?e[i]=merge$1({},n):isArray$e(n)?e[i]=n.slice():e[i]=n};for(let n=0,r=arguments.length;n(forEach(e,(r,i)=>{a&&isFunction$6(r)?t[i]=bind$4(r,a):t[i]=r},{allOwnKeys:n}),t),stripBOM=t=>(t.charCodeAt(0)===65279&&(t=t.slice(1)),t),inherits=(t,e,a,n)=>{t.prototype=Object.create(e.prototype,n),t.prototype.constructor=t,Object.defineProperty(t,"super",{value:e.prototype}),a&&Object.assign(t.prototype,a)},toFlatObject=(t,e,a,n)=>{let r,i,o;const s={};if(e=e||{},t==null)return e;do{for(r=Object.getOwnPropertyNames(t),i=r.length;i-- >0;)o=r[i],(!n||n(o,t,e))&&!s[o]&&(e[o]=t[o],s[o]=!0);t=a!==!1&&getPrototypeOf(t)}while(t&&(!a||a(t,e))&&t!==Object.prototype);return e},endsWith=(t,e,a)=>{t=String(t),(a===void 0||a>t.length)&&(a=t.length),a-=e.length;const n=t.indexOf(e,a);return n!==-1&&n===a},toArray=t=>{if(!t)return null;if(isArray$e(t))return t;let e=t.length;if(!isNumber$1(e))return null;const a=new Array(e);for(;e-- >0;)a[e]=t[e];return a},isTypedArray$3=(t=>e=>t&&e instanceof t)(typeof Uint8Array<"u"&&getPrototypeOf(Uint8Array)),forEachEntry=(t,e)=>{const n=(t&&t[Symbol.iterator]).call(t);let r;for(;(r=n.next())&&!r.done;){const i=r.value;e.call(t,i[0],i[1])}},matchAll=(t,e)=>{let a;const n=[];for(;(a=t.exec(e))!==null;)n.push(a);return n},isHTMLForm=kindOfTest("HTMLFormElement"),toCamelCase=t=>t.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(a,n,r){return n.toUpperCase()+r}),hasOwnProperty$c=(({hasOwnProperty:t})=>(e,a)=>t.call(e,a))(Object.prototype),isRegExp=kindOfTest("RegExp"),reduceDescriptors=(t,e)=>{const a=Object.getOwnPropertyDescriptors(t),n={};forEach(a,(r,i)=>{e(r,i,t)!==!1&&(n[i]=r)}),Object.defineProperties(t,n)},freezeMethods=t=>{reduceDescriptors(t,(e,a)=>{if(isFunction$6(t)&&["arguments","caller","callee"].indexOf(a)!==-1)return!1;const n=t[a];if(isFunction$6(n)){if(e.enumerable=!1,"writable"in e){e.writable=!1;return}e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+a+"'")})}})},toObjectSet=(t,e)=>{const a={},n=r=>{r.forEach(i=>{a[i]=!0})};return isArray$e(t)?n(t):n(String(t).split(e)),a},noop$4=()=>{},toFiniteNumber=(t,e)=>(t=+t,Number.isFinite(t)?t:e),ALPHA="abcdefghijklmnopqrstuvwxyz",DIGIT="0123456789",ALPHABET={DIGIT,ALPHA,ALPHA_DIGIT:ALPHA+ALPHA.toUpperCase()+DIGIT},generateString=(t=16,e=ALPHABET.ALPHA_DIGIT)=>{let a="";const{length:n}=e;for(;t--;)a+=e[Math.random()*n|0];return a};function isSpecCompliantForm(t){return!!(t&&isFunction$6(t.append)&&t[Symbol.toStringTag]==="FormData"&&t[Symbol.iterator])}const toJSONObject=t=>{const e=new Array(10),a=(n,r)=>{if(isObject$c(n)){if(e.indexOf(n)>=0)return;if(!("toJSON"in n)){e[r]=n;const i=isArray$e(n)?[]:{};return forEach(n,(o,s)=>{const l=a(o,r+1);!isUndefined(l)&&(i[s]=l)}),e[r]=void 0,i}}return n};return a(t,0)},isAsyncFn=kindOfTest("AsyncFunction"),isThenable=t=>t&&(isObject$c(t)||isFunction$6(t))&&isFunction$6(t.then)&&isFunction$6(t.catch),utils={isArray:isArray$e,isArrayBuffer,isBuffer:isBuffer$3,isFormData,isArrayBufferView,isString:isString$1,isNumber:isNumber$1,isBoolean,isObject:isObject$c,isPlainObject,isUndefined,isDate:isDate$1,isFile,isBlob,isRegExp,isFunction:isFunction$6,isStream,isURLSearchParams,isTypedArray:isTypedArray$3,isFileList,forEach,merge:merge$1,extend:extend$1,trim:trim$2,stripBOM,inherits,toFlatObject,kindOf,kindOfTest,endsWith,toArray,forEachEntry,matchAll,isHTMLForm,hasOwnProperty:hasOwnProperty$c,hasOwnProp:hasOwnProperty$c,reduceDescriptors,freezeMethods,toObjectSet,toCamelCase,noop:noop$4,toFiniteNumber,findKey:findKey$1,global:_global,isContextDefined,ALPHABET,generateString,isSpecCompliantForm,toJSONObject,isAsyncFn,isThenable};function AxiosError(t,e,a,n,r){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack,this.message=t,this.name="AxiosError",e&&(this.code=e),a&&(this.config=a),n&&(this.request=n),r&&(this.response=r)}utils.inherits(AxiosError,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:utils.toJSONObject(this.config),code:this.code,status:this.response&&this.response.status?this.response.status:null}}});const prototype$1=AxiosError.prototype,descriptors$1={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach(t=>{descriptors$1[t]={value:t}});Object.defineProperties(AxiosError,descriptors$1);Object.defineProperty(prototype$1,"isAxiosError",{value:!0});AxiosError.from=(t,e,a,n,r,i)=>{const o=Object.create(prototype$1);return utils.toFlatObject(t,o,function(l){return l!==Error.prototype},s=>s!=="isAxiosError"),AxiosError.call(o,t.message,e,a,n,r),o.cause=t,o.name=t.name,i&&Object.assign(o,i),o};const httpAdapter=null;function isVisitable(t){return utils.isPlainObject(t)||utils.isArray(t)}function removeBrackets(t){return utils.endsWith(t,"[]")?t.slice(0,-2):t}function renderKey(t,e,a){return t?t.concat(e).map(function(r,i){return r=removeBrackets(r),!a&&i?"["+r+"]":r}).join(a?".":""):e}function isFlatArray(t){return utils.isArray(t)&&!t.some(isVisitable)}const predicates=utils.toFlatObject(utils,{},null,function(e){return/^is[A-Z]/.test(e)});function toFormData(t,e,a){if(!utils.isObject(t))throw new TypeError("target must be an object");e=e||new FormData,a=utils.toFlatObject(a,{metaTokens:!0,dots:!1,indexes:!1},!1,function(v,y){return!utils.isUndefined(y[v])});const n=a.metaTokens,r=a.visitor||c,i=a.dots,o=a.indexes,l=(a.Blob||typeof Blob<"u"&&Blob)&&utils.isSpecCompliantForm(e);if(!utils.isFunction(r))throw new TypeError("visitor must be a function");function u(p){if(p===null)return"";if(utils.isDate(p))return p.toISOString();if(!l&&utils.isBlob(p))throw new AxiosError("Blob is not supported. Use a Buffer instead.");return utils.isArrayBuffer(p)||utils.isTypedArray(p)?l&&typeof Blob=="function"?new Blob([p]):Buffer.from(p):p}function c(p,v,y){let w=p;if(p&&!y&&typeof p=="object"){if(utils.endsWith(v,"{}"))v=n?v:v.slice(0,-2),p=JSON.stringify(p);else if(utils.isArray(p)&&isFlatArray(p)||(utils.isFileList(p)||utils.endsWith(v,"[]"))&&(w=utils.toArray(p)))return v=removeBrackets(v),w.forEach(function(D,C){!(utils.isUndefined(D)||D===null)&&e.append(o===!0?renderKey([v],C,i):o===null?v:v+"[]",u(D))}),!1}return isVisitable(p)?!0:(e.append(renderKey(y,v,i),u(p)),!1)}const d=[],h=Object.assign(predicates,{defaultVisitor:c,convertValue:u,isVisitable});function m(p,v){if(!utils.isUndefined(p)){if(d.indexOf(p)!==-1)throw Error("Circular reference detected in "+v.join("."));d.push(p),utils.forEach(p,function(w,_){(!(utils.isUndefined(w)||w===null)&&r.call(e,w,utils.isString(_)?_.trim():_,v,h))===!0&&m(w,v?v.concat(_):[_])}),d.pop()}}if(!utils.isObject(t))throw new TypeError("data must be an object");return m(t),e}function encode$1(t){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(t).replace(/[!'()~]|%20|%00/g,function(n){return e[n]})}function AxiosURLSearchParams(t,e){this._pairs=[],t&&toFormData(t,this,e)}const prototype=AxiosURLSearchParams.prototype;prototype.append=function(e,a){this._pairs.push([e,a])};prototype.toString=function(e){const a=e?function(n){return e.call(this,n,encode$1)}:encode$1;return this._pairs.map(function(r){return a(r[0])+"="+a(r[1])},"").join("&")};function encode(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function buildURL(t,e,a){if(!e)return t;const n=a&&a.encode||encode,r=a&&a.serialize;let i;if(r?i=r(e,a):i=utils.isURLSearchParams(e)?e.toString():new AxiosURLSearchParams(e,a).toString(n),i){const o=t.indexOf("#");o!==-1&&(t=t.slice(0,o)),t+=(t.indexOf("?")===-1?"?":"&")+i}return t}class InterceptorManager{constructor(){this.handlers=[]}use(e,a,n){return this.handlers.push({fulfilled:e,rejected:a,synchronous:n?n.synchronous:!1,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){utils.forEach(this.handlers,function(n){n!==null&&e(n)})}}const InterceptorManager$1=InterceptorManager,transitionalDefaults={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},URLSearchParams$1=typeof URLSearchParams<"u"?URLSearchParams:AxiosURLSearchParams,FormData$1=typeof FormData<"u"?FormData:null,Blob$1=typeof Blob<"u"?Blob:null,isStandardBrowserEnv=(()=>{let t;return typeof navigator<"u"&&((t=navigator.product)==="ReactNative"||t==="NativeScript"||t==="NS")?!1:typeof window<"u"&&typeof document<"u"})(),isStandardBrowserWebWorkerEnv=(()=>typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function")(),platform={isBrowser:!0,classes:{URLSearchParams:URLSearchParams$1,FormData:FormData$1,Blob:Blob$1},isStandardBrowserEnv,isStandardBrowserWebWorkerEnv,protocols:["http","https","file","blob","url","data"]};function toURLEncodedForm(t,e){return toFormData(t,new platform.classes.URLSearchParams,Object.assign({visitor:function(a,n,r,i){return platform.isNode&&utils.isBuffer(a)?(this.append(n,a.toString("base64")),!1):i.defaultVisitor.apply(this,arguments)}},e))}function parsePropPath(t){return utils.matchAll(/\w+|\[(\w*)]/g,t).map(e=>e[0]==="[]"?"":e[1]||e[0])}function arrayToObject(t){const e={},a=Object.keys(t);let n;const r=a.length;let i;for(n=0;n=a.length;return o=!o&&utils.isArray(r)?r.length:o,l?(utils.hasOwnProp(r,o)?r[o]=[r[o],n]:r[o]=n,!s):((!r[o]||!utils.isObject(r[o]))&&(r[o]=[]),e(a,n,r[o],i)&&utils.isArray(r[o])&&(r[o]=arrayToObject(r[o])),!s)}if(utils.isFormData(t)&&utils.isFunction(t.entries)){const a={};return utils.forEachEntry(t,(n,r)=>{e(parsePropPath(n),r,a,0)}),a}return null}const DEFAULT_CONTENT_TYPE={"Content-Type":void 0};function stringifySafely(t,e,a){if(utils.isString(t))try{return(e||JSON.parse)(t),utils.trim(t)}catch(n){if(n.name!=="SyntaxError")throw n}return(a||JSON.stringify)(t)}const defaults$1={transitional:transitionalDefaults,adapter:["xhr","http"],transformRequest:[function(e,a){const n=a.getContentType()||"",r=n.indexOf("application/json")>-1,i=utils.isObject(e);if(i&&utils.isHTMLForm(e)&&(e=new FormData(e)),utils.isFormData(e))return r&&r?JSON.stringify(formDataToJSON(e)):e;if(utils.isArrayBuffer(e)||utils.isBuffer(e)||utils.isStream(e)||utils.isFile(e)||utils.isBlob(e))return e;if(utils.isArrayBufferView(e))return e.buffer;if(utils.isURLSearchParams(e))return a.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let s;if(i){if(n.indexOf("application/x-www-form-urlencoded")>-1)return toURLEncodedForm(e,this.formSerializer).toString();if((s=utils.isFileList(e))||n.indexOf("multipart/form-data")>-1){const l=this.env&&this.env.FormData;return toFormData(s?{"files[]":e}:e,l&&new l,this.formSerializer)}}return i||r?(a.setContentType("application/json",!1),stringifySafely(e)):e}],transformResponse:[function(e){const a=this.transitional||defaults$1.transitional,n=a&&a.forcedJSONParsing,r=this.responseType==="json";if(e&&utils.isString(e)&&(n&&!this.responseType||r)){const o=!(a&&a.silentJSONParsing)&&r;try{return JSON.parse(e)}catch(s){if(o)throw s.name==="SyntaxError"?AxiosError.from(s,AxiosError.ERR_BAD_RESPONSE,this,null,this.response):s}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:platform.classes.FormData,Blob:platform.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*"}}};utils.forEach(["delete","get","head"],function(e){defaults$1.headers[e]={}});utils.forEach(["post","put","patch"],function(e){defaults$1.headers[e]=utils.merge(DEFAULT_CONTENT_TYPE)});const defaults$2=defaults$1,ignoreDuplicateOf=utils.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),parseHeaders=t=>{const e={};let a,n,r;return t&&t.split(` +var ve=Object.defineProperty;var be=(t,e,a)=>e in t?ve(t,e,{enumerable:!0,configurable:!0,writable:!0,value:a}):t[e]=a;var R=(t,e,a)=>(be(t,typeof e!="symbol"?e+"":e,a),a);function bind$4(t,e){return function(){return t.apply(e,arguments)}}const{toString:toString$7}=Object.prototype,{getPrototypeOf}=Object,kindOf=(t=>e=>{const a=toString$7.call(e);return t[a]||(t[a]=a.slice(8,-1).toLowerCase())})(Object.create(null)),kindOfTest=t=>(t=t.toLowerCase(),e=>kindOf(e)===t),typeOfTest=t=>e=>typeof e===t,{isArray:isArray$e}=Array,isUndefined=typeOfTest("undefined");function isBuffer$3(t){return t!==null&&!isUndefined(t)&&t.constructor!==null&&!isUndefined(t.constructor)&&isFunction$6(t.constructor.isBuffer)&&t.constructor.isBuffer(t)}const isArrayBuffer=kindOfTest("ArrayBuffer");function isArrayBufferView(t){let e;return typeof ArrayBuffer<"u"&&ArrayBuffer.isView?e=ArrayBuffer.isView(t):e=t&&t.buffer&&isArrayBuffer(t.buffer),e}const isString$1=typeOfTest("string"),isFunction$6=typeOfTest("function"),isNumber$1=typeOfTest("number"),isObject$c=t=>t!==null&&typeof t=="object",isBoolean=t=>t===!0||t===!1,isPlainObject=t=>{if(kindOf(t)!=="object")return!1;const e=getPrototypeOf(t);return(e===null||e===Object.prototype||Object.getPrototypeOf(e)===null)&&!(Symbol.toStringTag in t)&&!(Symbol.iterator in t)},isDate$1=kindOfTest("Date"),isFile=kindOfTest("File"),isBlob=kindOfTest("Blob"),isFileList=kindOfTest("FileList"),isStream=t=>isObject$c(t)&&isFunction$6(t.pipe),isFormData=t=>{let e;return t&&(typeof FormData=="function"&&t instanceof FormData||isFunction$6(t.append)&&((e=kindOf(t))==="formdata"||e==="object"&&isFunction$6(t.toString)&&t.toString()==="[object FormData]"))},isURLSearchParams=kindOfTest("URLSearchParams"),trim$2=t=>t.trim?t.trim():t.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,"");function forEach(t,e,{allOwnKeys:a=!1}={}){if(t===null||typeof t>"u")return;let n,r;if(typeof t!="object"&&(t=[t]),isArray$e(t))for(n=0,r=t.length;n0;)if(r=a[n],e===r.toLowerCase())return r;return null}const _global=(()=>typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global)(),isContextDefined=t=>!isUndefined(t)&&t!==_global;function merge$1(){const{caseless:t}=isContextDefined(this)&&this||{},e={},a=(n,r)=>{const i=t&&findKey$1(e,r)||r;isPlainObject(e[i])&&isPlainObject(n)?e[i]=merge$1(e[i],n):isPlainObject(n)?e[i]=merge$1({},n):isArray$e(n)?e[i]=n.slice():e[i]=n};for(let n=0,r=arguments.length;n(forEach(e,(r,i)=>{a&&isFunction$6(r)?t[i]=bind$4(r,a):t[i]=r},{allOwnKeys:n}),t),stripBOM=t=>(t.charCodeAt(0)===65279&&(t=t.slice(1)),t),inherits=(t,e,a,n)=>{t.prototype=Object.create(e.prototype,n),t.prototype.constructor=t,Object.defineProperty(t,"super",{value:e.prototype}),a&&Object.assign(t.prototype,a)},toFlatObject=(t,e,a,n)=>{let r,i,o;const s={};if(e=e||{},t==null)return e;do{for(r=Object.getOwnPropertyNames(t),i=r.length;i-- >0;)o=r[i],(!n||n(o,t,e))&&!s[o]&&(e[o]=t[o],s[o]=!0);t=a!==!1&&getPrototypeOf(t)}while(t&&(!a||a(t,e))&&t!==Object.prototype);return e},endsWith=(t,e,a)=>{t=String(t),(a===void 0||a>t.length)&&(a=t.length),a-=e.length;const n=t.indexOf(e,a);return n!==-1&&n===a},toArray=t=>{if(!t)return null;if(isArray$e(t))return t;let e=t.length;if(!isNumber$1(e))return null;const a=new Array(e);for(;e-- >0;)a[e]=t[e];return a},isTypedArray$3=(t=>e=>t&&e instanceof t)(typeof Uint8Array<"u"&&getPrototypeOf(Uint8Array)),forEachEntry=(t,e)=>{const n=(t&&t[Symbol.iterator]).call(t);let r;for(;(r=n.next())&&!r.done;){const i=r.value;e.call(t,i[0],i[1])}},matchAll=(t,e)=>{let a;const n=[];for(;(a=t.exec(e))!==null;)n.push(a);return n},isHTMLForm=kindOfTest("HTMLFormElement"),toCamelCase=t=>t.toLowerCase().replace(/[-_\s]([a-z\d])(\w*)/g,function(a,n,r){return n.toUpperCase()+r}),hasOwnProperty$c=(({hasOwnProperty:t})=>(e,a)=>t.call(e,a))(Object.prototype),isRegExp=kindOfTest("RegExp"),reduceDescriptors=(t,e)=>{const a=Object.getOwnPropertyDescriptors(t),n={};forEach(a,(r,i)=>{let o;(o=e(r,i,t))!==!1&&(n[i]=o||r)}),Object.defineProperties(t,n)},freezeMethods=t=>{reduceDescriptors(t,(e,a)=>{if(isFunction$6(t)&&["arguments","caller","callee"].indexOf(a)!==-1)return!1;const n=t[a];if(isFunction$6(n)){if(e.enumerable=!1,"writable"in e){e.writable=!1;return}e.set||(e.set=()=>{throw Error("Can not rewrite read-only method '"+a+"'")})}})},toObjectSet=(t,e)=>{const a={},n=r=>{r.forEach(i=>{a[i]=!0})};return isArray$e(t)?n(t):n(String(t).split(e)),a},noop$4=()=>{},toFiniteNumber=(t,e)=>(t=+t,Number.isFinite(t)?t:e),ALPHA="abcdefghijklmnopqrstuvwxyz",DIGIT="0123456789",ALPHABET={DIGIT,ALPHA,ALPHA_DIGIT:ALPHA+ALPHA.toUpperCase()+DIGIT},generateString=(t=16,e=ALPHABET.ALPHA_DIGIT)=>{let a="";const{length:n}=e;for(;t--;)a+=e[Math.random()*n|0];return a};function isSpecCompliantForm(t){return!!(t&&isFunction$6(t.append)&&t[Symbol.toStringTag]==="FormData"&&t[Symbol.iterator])}const toJSONObject=t=>{const e=new Array(10),a=(n,r)=>{if(isObject$c(n)){if(e.indexOf(n)>=0)return;if(!("toJSON"in n)){e[r]=n;const i=isArray$e(n)?[]:{};return forEach(n,(o,s)=>{const l=a(o,r+1);!isUndefined(l)&&(i[s]=l)}),e[r]=void 0,i}}return n};return a(t,0)},isAsyncFn=kindOfTest("AsyncFunction"),isThenable=t=>t&&(isObject$c(t)||isFunction$6(t))&&isFunction$6(t.then)&&isFunction$6(t.catch),utils={isArray:isArray$e,isArrayBuffer,isBuffer:isBuffer$3,isFormData,isArrayBufferView,isString:isString$1,isNumber:isNumber$1,isBoolean,isObject:isObject$c,isPlainObject,isUndefined,isDate:isDate$1,isFile,isBlob,isRegExp,isFunction:isFunction$6,isStream,isURLSearchParams,isTypedArray:isTypedArray$3,isFileList,forEach,merge:merge$1,extend,trim:trim$2,stripBOM,inherits,toFlatObject,kindOf,kindOfTest,endsWith,toArray,forEachEntry,matchAll,isHTMLForm,hasOwnProperty:hasOwnProperty$c,hasOwnProp:hasOwnProperty$c,reduceDescriptors,freezeMethods,toObjectSet,toCamelCase,noop:noop$4,toFiniteNumber,findKey:findKey$1,global:_global,isContextDefined,ALPHABET,generateString,isSpecCompliantForm,toJSONObject,isAsyncFn,isThenable};function AxiosError(t,e,a,n,r){Error.call(this),Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):this.stack=new Error().stack,this.message=t,this.name="AxiosError",e&&(this.code=e),a&&(this.config=a),n&&(this.request=n),r&&(this.response=r)}utils.inherits(AxiosError,Error,{toJSON:function(){return{message:this.message,name:this.name,description:this.description,number:this.number,fileName:this.fileName,lineNumber:this.lineNumber,columnNumber:this.columnNumber,stack:this.stack,config:utils.toJSONObject(this.config),code:this.code,status:this.response&&this.response.status?this.response.status:null}}});const prototype$1=AxiosError.prototype,descriptors$1={};["ERR_BAD_OPTION_VALUE","ERR_BAD_OPTION","ECONNABORTED","ETIMEDOUT","ERR_NETWORK","ERR_FR_TOO_MANY_REDIRECTS","ERR_DEPRECATED","ERR_BAD_RESPONSE","ERR_BAD_REQUEST","ERR_CANCELED","ERR_NOT_SUPPORT","ERR_INVALID_URL"].forEach(t=>{descriptors$1[t]={value:t}});Object.defineProperties(AxiosError,descriptors$1);Object.defineProperty(prototype$1,"isAxiosError",{value:!0});AxiosError.from=(t,e,a,n,r,i)=>{const o=Object.create(prototype$1);return utils.toFlatObject(t,o,function(l){return l!==Error.prototype},s=>s!=="isAxiosError"),AxiosError.call(o,t.message,e,a,n,r),o.cause=t,o.name=t.name,i&&Object.assign(o,i),o};const httpAdapter=null;function isVisitable(t){return utils.isPlainObject(t)||utils.isArray(t)}function removeBrackets(t){return utils.endsWith(t,"[]")?t.slice(0,-2):t}function renderKey(t,e,a){return t?t.concat(e).map(function(r,i){return r=removeBrackets(r),!a&&i?"["+r+"]":r}).join(a?".":""):e}function isFlatArray(t){return utils.isArray(t)&&!t.some(isVisitable)}const predicates=utils.toFlatObject(utils,{},null,function(e){return/^is[A-Z]/.test(e)});function toFormData(t,e,a){if(!utils.isObject(t))throw new TypeError("target must be an object");e=e||new FormData,a=utils.toFlatObject(a,{metaTokens:!0,dots:!1,indexes:!1},!1,function(v,y){return!utils.isUndefined(y[v])});const n=a.metaTokens,r=a.visitor||c,i=a.dots,o=a.indexes,l=(a.Blob||typeof Blob<"u"&&Blob)&&utils.isSpecCompliantForm(e);if(!utils.isFunction(r))throw new TypeError("visitor must be a function");function u(p){if(p===null)return"";if(utils.isDate(p))return p.toISOString();if(!l&&utils.isBlob(p))throw new AxiosError("Blob is not supported. Use a Buffer instead.");return utils.isArrayBuffer(p)||utils.isTypedArray(p)?l&&typeof Blob=="function"?new Blob([p]):Buffer.from(p):p}function c(p,v,y){let w=p;if(p&&!y&&typeof p=="object"){if(utils.endsWith(v,"{}"))v=n?v:v.slice(0,-2),p=JSON.stringify(p);else if(utils.isArray(p)&&isFlatArray(p)||(utils.isFileList(p)||utils.endsWith(v,"[]"))&&(w=utils.toArray(p)))return v=removeBrackets(v),w.forEach(function(D,k){!(utils.isUndefined(D)||D===null)&&e.append(o===!0?renderKey([v],k,i):o===null?v:v+"[]",u(D))}),!1}return isVisitable(p)?!0:(e.append(renderKey(y,v,i),u(p)),!1)}const d=[],h=Object.assign(predicates,{defaultVisitor:c,convertValue:u,isVisitable});function m(p,v){if(!utils.isUndefined(p)){if(d.indexOf(p)!==-1)throw Error("Circular reference detected in "+v.join("."));d.push(p),utils.forEach(p,function(w,_){(!(utils.isUndefined(w)||w===null)&&r.call(e,w,utils.isString(_)?_.trim():_,v,h))===!0&&m(w,v?v.concat(_):[_])}),d.pop()}}if(!utils.isObject(t))throw new TypeError("data must be an object");return m(t),e}function encode$1(t){const e={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+","%00":"\0"};return encodeURIComponent(t).replace(/[!'()~]|%20|%00/g,function(n){return e[n]})}function AxiosURLSearchParams(t,e){this._pairs=[],t&&toFormData(t,this,e)}const prototype=AxiosURLSearchParams.prototype;prototype.append=function(e,a){this._pairs.push([e,a])};prototype.toString=function(e){const a=e?function(n){return e.call(this,n,encode$1)}:encode$1;return this._pairs.map(function(r){return a(r[0])+"="+a(r[1])},"").join("&")};function encode(t){return encodeURIComponent(t).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}function buildURL(t,e,a){if(!e)return t;const n=a&&a.encode||encode,r=a&&a.serialize;let i;if(r?i=r(e,a):i=utils.isURLSearchParams(e)?e.toString():new AxiosURLSearchParams(e,a).toString(n),i){const o=t.indexOf("#");o!==-1&&(t=t.slice(0,o)),t+=(t.indexOf("?")===-1?"?":"&")+i}return t}class InterceptorManager{constructor(){this.handlers=[]}use(e,a,n){return this.handlers.push({fulfilled:e,rejected:a,synchronous:n?n.synchronous:!1,runWhen:n?n.runWhen:null}),this.handlers.length-1}eject(e){this.handlers[e]&&(this.handlers[e]=null)}clear(){this.handlers&&(this.handlers=[])}forEach(e){utils.forEach(this.handlers,function(n){n!==null&&e(n)})}}const InterceptorManager$1=InterceptorManager,transitionalDefaults={silentJSONParsing:!0,forcedJSONParsing:!0,clarifyTimeoutError:!1},URLSearchParams$1=typeof URLSearchParams<"u"?URLSearchParams:AxiosURLSearchParams,FormData$1=typeof FormData<"u"?FormData:null,Blob$1=typeof Blob<"u"?Blob:null,isStandardBrowserEnv=(()=>{let t;return typeof navigator<"u"&&((t=navigator.product)==="ReactNative"||t==="NativeScript"||t==="NS")?!1:typeof window<"u"&&typeof document<"u"})(),isStandardBrowserWebWorkerEnv=(()=>typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope&&typeof self.importScripts=="function")(),platform={isBrowser:!0,classes:{URLSearchParams:URLSearchParams$1,FormData:FormData$1,Blob:Blob$1},isStandardBrowserEnv,isStandardBrowserWebWorkerEnv,protocols:["http","https","file","blob","url","data"]};function toURLEncodedForm(t,e){return toFormData(t,new platform.classes.URLSearchParams,Object.assign({visitor:function(a,n,r,i){return platform.isNode&&utils.isBuffer(a)?(this.append(n,a.toString("base64")),!1):i.defaultVisitor.apply(this,arguments)}},e))}function parsePropPath(t){return utils.matchAll(/\w+|\[(\w*)]/g,t).map(e=>e[0]==="[]"?"":e[1]||e[0])}function arrayToObject(t){const e={},a=Object.keys(t);let n;const r=a.length;let i;for(n=0;n=a.length;return o=!o&&utils.isArray(r)?r.length:o,l?(utils.hasOwnProp(r,o)?r[o]=[r[o],n]:r[o]=n,!s):((!r[o]||!utils.isObject(r[o]))&&(r[o]=[]),e(a,n,r[o],i)&&utils.isArray(r[o])&&(r[o]=arrayToObject(r[o])),!s)}if(utils.isFormData(t)&&utils.isFunction(t.entries)){const a={};return utils.forEachEntry(t,(n,r)=>{e(parsePropPath(n),r,a,0)}),a}return null}function stringifySafely(t,e,a){if(utils.isString(t))try{return(e||JSON.parse)(t),utils.trim(t)}catch(n){if(n.name!=="SyntaxError")throw n}return(a||JSON.stringify)(t)}const defaults$1={transitional:transitionalDefaults,adapter:platform.isNode?"http":"xhr",transformRequest:[function(e,a){const n=a.getContentType()||"",r=n.indexOf("application/json")>-1,i=utils.isObject(e);if(i&&utils.isHTMLForm(e)&&(e=new FormData(e)),utils.isFormData(e))return r&&r?JSON.stringify(formDataToJSON(e)):e;if(utils.isArrayBuffer(e)||utils.isBuffer(e)||utils.isStream(e)||utils.isFile(e)||utils.isBlob(e))return e;if(utils.isArrayBufferView(e))return e.buffer;if(utils.isURLSearchParams(e))return a.setContentType("application/x-www-form-urlencoded;charset=utf-8",!1),e.toString();let s;if(i){if(n.indexOf("application/x-www-form-urlencoded")>-1)return toURLEncodedForm(e,this.formSerializer).toString();if((s=utils.isFileList(e))||n.indexOf("multipart/form-data")>-1){const l=this.env&&this.env.FormData;return toFormData(s?{"files[]":e}:e,l&&new l,this.formSerializer)}}return i||r?(a.setContentType("application/json",!1),stringifySafely(e)):e}],transformResponse:[function(e){const a=this.transitional||defaults$1.transitional,n=a&&a.forcedJSONParsing,r=this.responseType==="json";if(e&&utils.isString(e)&&(n&&!this.responseType||r)){const o=!(a&&a.silentJSONParsing)&&r;try{return JSON.parse(e)}catch(s){if(o)throw s.name==="SyntaxError"?AxiosError.from(s,AxiosError.ERR_BAD_RESPONSE,this,null,this.response):s}}return e}],timeout:0,xsrfCookieName:"XSRF-TOKEN",xsrfHeaderName:"X-XSRF-TOKEN",maxContentLength:-1,maxBodyLength:-1,env:{FormData:platform.classes.FormData,Blob:platform.classes.Blob},validateStatus:function(e){return e>=200&&e<300},headers:{common:{Accept:"application/json, text/plain, */*","Content-Type":void 0}}};utils.forEach(["delete","get","head","post","put","patch"],t=>{defaults$1.headers[t]={}});const defaults$2=defaults$1,ignoreDuplicateOf=utils.toObjectSet(["age","authorization","content-length","content-type","etag","expires","from","host","if-modified-since","if-unmodified-since","last-modified","location","max-forwards","proxy-authorization","referer","retry-after","user-agent"]),parseHeaders=t=>{const e={};let a,n,r;return t&&t.split(` `).forEach(function(o){r=o.indexOf(":"),a=o.substring(0,r).trim().toLowerCase(),n=o.substring(r+1).trim(),!(!a||e[a]&&ignoreDuplicateOf[a])&&(a==="set-cookie"?e[a]?e[a].push(n):e[a]=[n]:e[a]=e[a]?e[a]+", "+n:n)}),e},$internals=Symbol("internals");function normalizeHeader(t){return t&&String(t).trim().toLowerCase()}function normalizeValue(t){return t===!1||t==null?t:utils.isArray(t)?t.map(normalizeValue):String(t)}function parseTokens(t){const e=Object.create(null),a=/([^\s,;=]+)\s*(?:=\s*([^,;]+))?/g;let n;for(;n=a.exec(t);)e[n[1]]=n[2];return e}const isValidHeaderName=t=>/^[-_a-zA-Z0-9^`|~,!#$%&'*+.]+$/.test(t.trim());function matchHeaderValue(t,e,a,n,r){if(utils.isFunction(n))return n.call(this,e,a);if(r&&(e=a),!!utils.isString(e)){if(utils.isString(n))return e.indexOf(n)!==-1;if(utils.isRegExp(n))return n.test(e)}}function formatHeader(t){return t.trim().toLowerCase().replace(/([a-z\d])(\w*)/g,(e,a,n)=>a.toUpperCase()+n)}function buildAccessors(t,e){const a=utils.toCamelCase(" "+e);["get","set","has"].forEach(n=>{Object.defineProperty(t,n+a,{value:function(r,i,o){return this[n].call(this,e,r,i,o)},configurable:!0})})}class AxiosHeaders{constructor(e){e&&this.set(e)}set(e,a,n){const r=this;function i(s,l,u){const c=normalizeHeader(l);if(!c)throw new Error("header name must be a non-empty string");const d=utils.findKey(r,c);(!d||r[d]===void 0||u===!0||u===void 0&&r[d]!==!1)&&(r[d||l]=normalizeValue(s))}const o=(s,l)=>utils.forEach(s,(u,c)=>i(u,c,l));return utils.isPlainObject(e)||e instanceof this.constructor?o(e,a):utils.isString(e)&&(e=e.trim())&&!isValidHeaderName(e)?o(parseHeaders(e),a):e!=null&&i(a,e,n),this}get(e,a){if(e=normalizeHeader(e),e){const n=utils.findKey(this,e);if(n){const r=this[n];if(!a)return r;if(a===!0)return parseTokens(r);if(utils.isFunction(a))return a.call(this,r,n);if(utils.isRegExp(a))return a.exec(r);throw new TypeError("parser must be boolean|regexp|function")}}}has(e,a){if(e=normalizeHeader(e),e){const n=utils.findKey(this,e);return!!(n&&this[n]!==void 0&&(!a||matchHeaderValue(this,this[n],n,a)))}return!1}delete(e,a){const n=this;let r=!1;function i(o){if(o=normalizeHeader(o),o){const s=utils.findKey(n,o);s&&(!a||matchHeaderValue(n,n[s],s,a))&&(delete n[s],r=!0)}}return utils.isArray(e)?e.forEach(i):i(e),r}clear(e){const a=Object.keys(this);let n=a.length,r=!1;for(;n--;){const i=a[n];(!e||matchHeaderValue(this,this[i],i,e,!0))&&(delete this[i],r=!0)}return r}normalize(e){const a=this,n={};return utils.forEach(this,(r,i)=>{const o=utils.findKey(n,i);if(o){a[o]=normalizeValue(r),delete a[i];return}const s=e?formatHeader(i):String(i).trim();s!==i&&delete a[i],a[s]=normalizeValue(r),n[s]=!0}),this}concat(...e){return this.constructor.concat(this,...e)}toJSON(e){const a=Object.create(null);return utils.forEach(this,(n,r)=>{n!=null&&n!==!1&&(a[r]=e&&utils.isArray(n)?n.join(", "):n)}),a}[Symbol.iterator](){return Object.entries(this.toJSON())[Symbol.iterator]()}toString(){return Object.entries(this.toJSON()).map(([e,a])=>e+": "+a).join(` -`)}get[Symbol.toStringTag](){return"AxiosHeaders"}static from(e){return e instanceof this?e:new this(e)}static concat(e,...a){const n=new this(e);return a.forEach(r=>n.set(r)),n}static accessor(e){const n=(this[$internals]=this[$internals]={accessors:{}}).accessors,r=this.prototype;function i(o){const s=normalizeHeader(o);n[s]||(buildAccessors(r,o),n[s]=!0)}return utils.isArray(e)?e.forEach(i):i(e),this}}AxiosHeaders.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);utils.freezeMethods(AxiosHeaders.prototype);utils.freezeMethods(AxiosHeaders);const AxiosHeaders$1=AxiosHeaders;function transformData(t,e){const a=this||defaults$2,n=e||a,r=AxiosHeaders$1.from(n.headers);let i=n.data;return utils.forEach(t,function(s){i=s.call(a,i,r.normalize(),e?e.status:void 0)}),r.normalize(),i}function isCancel(t){return!!(t&&t.__CANCEL__)}function CanceledError(t,e,a){AxiosError.call(this,t??"canceled",AxiosError.ERR_CANCELED,e,a),this.name="CanceledError"}utils.inherits(CanceledError,AxiosError,{__CANCEL__:!0});function settle(t,e,a){const n=a.config.validateStatus;!a.status||!n||n(a.status)?t(a):e(new AxiosError("Request failed with status code "+a.status,[AxiosError.ERR_BAD_REQUEST,AxiosError.ERR_BAD_RESPONSE][Math.floor(a.status/100)-4],a.config,a.request,a))}const cookies=platform.isStandardBrowserEnv?function(){return{write:function(a,n,r,i,o,s){const l=[];l.push(a+"="+encodeURIComponent(n)),utils.isNumber(r)&&l.push("expires="+new Date(r).toGMTString()),utils.isString(i)&&l.push("path="+i),utils.isString(o)&&l.push("domain="+o),s===!0&&l.push("secure"),document.cookie=l.join("; ")},read:function(a){const n=document.cookie.match(new RegExp("(^|;\\s*)("+a+")=([^;]*)"));return n?decodeURIComponent(n[3]):null},remove:function(a){this.write(a,"",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}();function isAbsoluteURL(t){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t)}function combineURLs(t,e){return e?t.replace(/\/+$/,"")+"/"+e.replace(/^\/+/,""):t}function buildFullPath(t,e){return t&&!isAbsoluteURL(e)?combineURLs(t,e):e}const isURLSameOrigin=platform.isStandardBrowserEnv?function(){const e=/(msie|trident)/i.test(navigator.userAgent),a=document.createElement("a");let n;function r(i){let o=i;return e&&(a.setAttribute("href",o),o=a.href),a.setAttribute("href",o),{href:a.href,protocol:a.protocol?a.protocol.replace(/:$/,""):"",host:a.host,search:a.search?a.search.replace(/^\?/,""):"",hash:a.hash?a.hash.replace(/^#/,""):"",hostname:a.hostname,port:a.port,pathname:a.pathname.charAt(0)==="/"?a.pathname:"/"+a.pathname}}return n=r(window.location.href),function(o){const s=utils.isString(o)?r(o):o;return s.protocol===n.protocol&&s.host===n.host}}():function(){return function(){return!0}}();function parseProtocol(t){const e=/^([-+\w]{1,25})(:?\/\/|:)/.exec(t);return e&&e[1]||""}function speedometer(t,e){t=t||10;const a=new Array(t),n=new Array(t);let r=0,i=0,o;return e=e!==void 0?e:1e3,function(l){const u=Date.now(),c=n[i];o||(o=u),a[r]=l,n[r]=u;let d=i,h=0;for(;d!==r;)h+=a[d++],d=d%t;if(r=(r+1)%t,r===i&&(i=(i+1)%t),u-o{const i=r.loaded,o=r.lengthComputable?r.total:void 0,s=i-a,l=n(s),u=i<=o;a=i;const c={loaded:i,total:o,progress:o?i/o:void 0,bytes:s,rate:l||void 0,estimated:l&&o&&u?(o-i)/l:void 0,event:r};c[e?"download":"upload"]=!0,t(c)}}const isXHRAdapterSupported=typeof XMLHttpRequest<"u",xhrAdapter=isXHRAdapterSupported&&function(t){return new Promise(function(a,n){let r=t.data;const i=AxiosHeaders$1.from(t.headers).normalize(),o=t.responseType;let s;function l(){t.cancelToken&&t.cancelToken.unsubscribe(s),t.signal&&t.signal.removeEventListener("abort",s)}utils.isFormData(r)&&(platform.isStandardBrowserEnv||platform.isStandardBrowserWebWorkerEnv?i.setContentType(!1):i.setContentType("multipart/form-data;",!1));let u=new XMLHttpRequest;if(t.auth){const m=t.auth.username||"",p=t.auth.password?unescape(encodeURIComponent(t.auth.password)):"";i.set("Authorization","Basic "+btoa(m+":"+p))}const c=buildFullPath(t.baseURL,t.url);u.open(t.method.toUpperCase(),buildURL(c,t.params,t.paramsSerializer),!0),u.timeout=t.timeout;function d(){if(!u)return;const m=AxiosHeaders$1.from("getAllResponseHeaders"in u&&u.getAllResponseHeaders()),v={data:!o||o==="text"||o==="json"?u.responseText:u.response,status:u.status,statusText:u.statusText,headers:m,config:t,request:u};settle(function(w){a(w),l()},function(w){n(w),l()},v),u=null}if("onloadend"in u?u.onloadend=d:u.onreadystatechange=function(){!u||u.readyState!==4||u.status===0&&!(u.responseURL&&u.responseURL.indexOf("file:")===0)||setTimeout(d)},u.onabort=function(){u&&(n(new AxiosError("Request aborted",AxiosError.ECONNABORTED,t,u)),u=null)},u.onerror=function(){n(new AxiosError("Network Error",AxiosError.ERR_NETWORK,t,u)),u=null},u.ontimeout=function(){let p=t.timeout?"timeout of "+t.timeout+"ms exceeded":"timeout exceeded";const v=t.transitional||transitionalDefaults;t.timeoutErrorMessage&&(p=t.timeoutErrorMessage),n(new AxiosError(p,v.clarifyTimeoutError?AxiosError.ETIMEDOUT:AxiosError.ECONNABORTED,t,u)),u=null},platform.isStandardBrowserEnv){const m=(t.withCredentials||isURLSameOrigin(c))&&t.xsrfCookieName&&cookies.read(t.xsrfCookieName);m&&i.set(t.xsrfHeaderName,m)}r===void 0&&i.setContentType(null),"setRequestHeader"in u&&utils.forEach(i.toJSON(),function(p,v){u.setRequestHeader(v,p)}),utils.isUndefined(t.withCredentials)||(u.withCredentials=!!t.withCredentials),o&&o!=="json"&&(u.responseType=t.responseType),typeof t.onDownloadProgress=="function"&&u.addEventListener("progress",progressEventReducer(t.onDownloadProgress,!0)),typeof t.onUploadProgress=="function"&&u.upload&&u.upload.addEventListener("progress",progressEventReducer(t.onUploadProgress)),(t.cancelToken||t.signal)&&(s=m=>{u&&(n(!m||m.type?new CanceledError(null,t,u):m),u.abort(),u=null)},t.cancelToken&&t.cancelToken.subscribe(s),t.signal&&(t.signal.aborted?s():t.signal.addEventListener("abort",s)));const h=parseProtocol(c);if(h&&platform.protocols.indexOf(h)===-1){n(new AxiosError("Unsupported protocol "+h+":",AxiosError.ERR_BAD_REQUEST,t));return}u.send(r||null)})},knownAdapters={http:httpAdapter,xhr:xhrAdapter};utils.forEach(knownAdapters,(t,e)=>{if(t){try{Object.defineProperty(t,"name",{value:e})}catch{}Object.defineProperty(t,"adapterName",{value:e})}});const adapters$1={getAdapter:t=>{t=utils.isArray(t)?t:[t];const{length:e}=t;let a,n;for(let r=0;rt instanceof AxiosHeaders$1?t.toJSON():t;function mergeConfig(t,e){e=e||{};const a={};function n(u,c,d){return utils.isPlainObject(u)&&utils.isPlainObject(c)?utils.merge.call({caseless:d},u,c):utils.isPlainObject(c)?utils.merge({},c):utils.isArray(c)?c.slice():c}function r(u,c,d){if(utils.isUndefined(c)){if(!utils.isUndefined(u))return n(void 0,u,d)}else return n(u,c,d)}function i(u,c){if(!utils.isUndefined(c))return n(void 0,c)}function o(u,c){if(utils.isUndefined(c)){if(!utils.isUndefined(u))return n(void 0,u)}else return n(void 0,c)}function s(u,c,d){if(d in e)return n(u,c);if(d in t)return n(void 0,u)}const l={url:i,method:i,data:i,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,onDownloadProgress:o,decompress:o,maxContentLength:o,maxBodyLength:o,beforeRedirect:o,transport:o,httpAgent:o,httpsAgent:o,cancelToken:o,socketPath:o,responseEncoding:o,validateStatus:s,headers:(u,c)=>r(headersToObject(u),headersToObject(c),!0)};return utils.forEach(Object.keys(Object.assign({},t,e)),function(c){const d=l[c]||r,h=d(t[c],e[c],c);utils.isUndefined(h)&&d!==s||(a[c]=h)}),a}const VERSION$1="1.4.0",validators$1={};["object","boolean","number","function","string","symbol"].forEach((t,e)=>{validators$1[t]=function(n){return typeof n===t||"a"+(e<1?"n ":" ")+t}});const deprecatedWarnings={};validators$1.transitional=function(e,a,n){function r(i,o){return"[Axios v"+VERSION$1+"] Transitional option '"+i+"'"+o+(n?". "+n:"")}return(i,o,s)=>{if(e===!1)throw new AxiosError(r(o," has been removed"+(a?" in "+a:"")),AxiosError.ERR_DEPRECATED);return a&&!deprecatedWarnings[o]&&(deprecatedWarnings[o]=!0,console.warn(r(o," has been deprecated since v"+a+" and will be removed in the near future"))),e?e(i,o,s):!0}};function assertOptions(t,e,a){if(typeof t!="object")throw new AxiosError("options must be an object",AxiosError.ERR_BAD_OPTION_VALUE);const n=Object.keys(t);let r=n.length;for(;r-- >0;){const i=n[r],o=e[i];if(o){const s=t[i],l=s===void 0||o(s,i,t);if(l!==!0)throw new AxiosError("option "+i+" must be "+l,AxiosError.ERR_BAD_OPTION_VALUE);continue}if(a!==!0)throw new AxiosError("Unknown option "+i,AxiosError.ERR_BAD_OPTION)}}const validator={assertOptions,validators:validators$1},validators=validator.validators;class Axios{constructor(e){this.defaults=e,this.interceptors={request:new InterceptorManager$1,response:new InterceptorManager$1}}request(e,a){typeof e=="string"?(a=a||{},a.url=e):a=e||{},a=mergeConfig(this.defaults,a);const{transitional:n,paramsSerializer:r,headers:i}=a;n!==void 0&&validator.assertOptions(n,{silentJSONParsing:validators.transitional(validators.boolean),forcedJSONParsing:validators.transitional(validators.boolean),clarifyTimeoutError:validators.transitional(validators.boolean)},!1),r!=null&&(utils.isFunction(r)?a.paramsSerializer={serialize:r}:validator.assertOptions(r,{encode:validators.function,serialize:validators.function},!0)),a.method=(a.method||this.defaults.method||"get").toLowerCase();let o;o=i&&utils.merge(i.common,i[a.method]),o&&utils.forEach(["delete","get","head","post","put","patch","common"],p=>{delete i[p]}),a.headers=AxiosHeaders$1.concat(o,i);const s=[];let l=!0;this.interceptors.request.forEach(function(v){typeof v.runWhen=="function"&&v.runWhen(a)===!1||(l=l&&v.synchronous,s.unshift(v.fulfilled,v.rejected))});const u=[];this.interceptors.response.forEach(function(v){u.push(v.fulfilled,v.rejected)});let c,d=0,h;if(!l){const p=[dispatchRequest.bind(this),void 0];for(p.unshift.apply(p,s),p.push.apply(p,u),h=p.length,c=Promise.resolve(a);d{if(!n._listeners)return;let i=n._listeners.length;for(;i-- >0;)n._listeners[i](r);n._listeners=null}),this.promise.then=r=>{let i;const o=new Promise(s=>{n.subscribe(s),i=s}).then(r);return o.cancel=function(){n.unsubscribe(i)},o},e(function(i,o,s){n.reason||(n.reason=new CanceledError(i,o,s),a(n.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){if(this.reason){e(this.reason);return}this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const a=this._listeners.indexOf(e);a!==-1&&this._listeners.splice(a,1)}static source(){let e;return{token:new CancelToken(function(r){e=r}),cancel:e}}}const CancelToken$1=CancelToken;function spread(t){return function(a){return t.apply(null,a)}}function isAxiosError(t){return utils.isObject(t)&&t.isAxiosError===!0}const HttpStatusCode={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(HttpStatusCode).forEach(([t,e])=>{HttpStatusCode[e]=t});const HttpStatusCode$1=HttpStatusCode;function createInstance(t){const e=new Axios$1(t),a=bind$4(Axios$1.prototype.request,e);return utils.extend(a,Axios$1.prototype,e,{allOwnKeys:!0}),utils.extend(a,e,null,{allOwnKeys:!0}),a.create=function(r){return createInstance(mergeConfig(t,r))},a}const axios=createInstance(defaults$2);axios.Axios=Axios$1;axios.CanceledError=CanceledError;axios.CancelToken=CancelToken$1;axios.isCancel=isCancel;axios.VERSION=VERSION$1;axios.toFormData=toFormData;axios.AxiosError=AxiosError;axios.Cancel=axios.CanceledError;axios.all=function(e){return Promise.all(e)};axios.spread=spread;axios.isAxiosError=isAxiosError;axios.mergeConfig=mergeConfig;axios.AxiosHeaders=AxiosHeaders$1;axios.formToJSON=t=>formDataToJSON(utils.isHTMLForm(t)?new FormData(t):t);axios.HttpStatusCode=HttpStatusCode$1;axios.default=axios;const axios$1=axios;var commonjsGlobal=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function getDefaultExportFromCjs(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var assign$1=make_assign(),create$2=make_create(),trim$1=make_trim(),Global$5=typeof window<"u"?window:commonjsGlobal,util$7={assign:assign$1,create:create$2,trim:trim$1,bind:bind$3,slice:slice$2,each:each$9,map:map$2,pluck:pluck$1,isList:isList$1,isFunction:isFunction$5,isObject:isObject$b,Global:Global$5};function make_assign(){return Object.assign?Object.assign:function(e,a,n,r){for(var i=1;i"u"?null:console;if(t){var e=t.warn?t.warn:t.log;e.apply(t,arguments)}}function createStore(t,e,a){a||(a=""),t&&!isList(t)&&(t=[t]),e&&!isList(e)&&(e=[e]);var n=a?"__storejs_"+a+"_":"",r=a?new RegExp("^"+n):null,i=/^[a-zA-Z0-9_\-]*$/;if(!i.test(a))throw new Error("store.js namespaces can only have alphanumerics + underscores and dashes");var o={_namespacePrefix:n,_namespaceRegexp:r,_testStorage:function(l){try{var u="__storejs__test__";l.write(u,u);var c=l.read(u)===u;return l.remove(u),c}catch{return!1}},_assignPluginFnProp:function(l,u){var c=this[u];this[u]=function(){var h=slice$1(arguments,0),m=this;function p(){if(c)return each$8(arguments,function(y,w){h[w]=y}),c.apply(m,h)}var v=[p].concat(h);return l.apply(m,v)}},_serialize:function(l){return JSON.stringify(l)},_deserialize:function(l,u){if(!l)return u;var c="";try{c=JSON.parse(l)}catch{c=l}return c!==void 0?c:u},_addStorage:function(l){this.enabled||this._testStorage(l)&&(this.storage=l,this.enabled=!0)},_addPlugin:function(l){var u=this;if(isList(l)){each$8(l,function(h){u._addPlugin(h)});return}var c=pluck(this.plugins,function(h){return l===h});if(!c){if(this.plugins.push(l),!isFunction$4(l))throw new Error("Plugins must be function values that return objects");var d=l.call(this);if(!isObject$a(d))throw new Error("Plugins must return an object of function properties");each$8(d,function(h,m){if(!isFunction$4(h))throw new Error("Bad plugin property: "+m+" from plugin "+l.name+". Plugins should only return functions.");u._assignPluginFnProp(h,m)})}},addStorage:function(l){_warn("store.addStorage(storage) is deprecated. Use createStore([storages])"),this._addStorage(l)}},s=create$1(o,storeAPI,{plugins:[]});return s.raw={},each$8(s,function(l,u){isFunction$4(l)&&(s.raw[u]=bind$2(s,l))}),each$8(t,function(l){s._addStorage(l)}),each$8(e,function(l){s._addPlugin(l)}),s}var util$5=util$7,Global$4=util$5.Global,localStorage_1={name:"localStorage",read:read$6,write:write$6,each:each$7,remove:remove$5,clearAll:clearAll$5};function localStorage(){return Global$4.localStorage}function read$6(t){return localStorage().getItem(t)}function write$6(t,e){return localStorage().setItem(t,e)}function each$7(t){for(var e=localStorage().length-1;e>=0;e--){var a=localStorage().key(e);t(read$6(a),a)}}function remove$5(t){return localStorage().removeItem(t)}function clearAll$5(){return localStorage().clear()}var util$4=util$7,Global$3=util$4.Global,oldFFGlobalStorage={name:"oldFF-globalStorage",read:read$5,write:write$5,each:each$6,remove:remove$4,clearAll:clearAll$4},globalStorage=Global$3.globalStorage;function read$5(t){return globalStorage[t]}function write$5(t,e){globalStorage[t]=e}function each$6(t){for(var e=globalStorage.length-1;e>=0;e--){var a=globalStorage.key(e);t(globalStorage[a],a)}}function remove$4(t){return globalStorage.removeItem(t)}function clearAll$4(){each$6(function(t,e){delete globalStorage[t]})}var util$3=util$7,Global$2=util$3.Global,oldIEUserDataStorage={name:"oldIE-userDataStorage",write:write$4,read:read$4,each:each$5,remove:remove$3,clearAll:clearAll$3},storageName="storejs",doc$1=Global$2.document,_withStorageEl=_makeIEStorageElFunction(),disable=(Global$2.navigator?Global$2.navigator.userAgent:"").match(/ (MSIE 8|MSIE 9|MSIE 10)\./);function write$4(t,e){if(!disable){var a=fixKey(t);_withStorageEl(function(n){n.setAttribute(a,e),n.save(storageName)})}}function read$4(t){if(!disable){var e=fixKey(t),a=null;return _withStorageEl(function(n){a=n.getAttribute(e)}),a}}function each$5(t){_withStorageEl(function(e){for(var a=e.XMLDocument.documentElement.attributes,n=a.length-1;n>=0;n--){var r=a[n];t(e.getAttribute(r.name),r.name)}})}function remove$3(t){var e=fixKey(t);_withStorageEl(function(a){a.removeAttribute(e),a.save(storageName)})}function clearAll$3(){_withStorageEl(function(t){var e=t.XMLDocument.documentElement.attributes;t.load(storageName);for(var a=e.length-1;a>=0;a--)t.removeAttribute(e[a].name);t.save(storageName)})}var forbiddenCharsRegex=new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]","g");function fixKey(t){return t.replace(/^\d/,"___$&").replace(forbiddenCharsRegex,"___")}function _makeIEStorageElFunction(){if(!doc$1||!doc$1.documentElement||!doc$1.documentElement.addBehavior)return null;var t="script",e,a,n;try{a=new ActiveXObject("htmlfile"),a.open(),a.write("<"+t+">document.w=window'),a.close(),e=a.w.frames[0].document,n=e.createElement("div")}catch{n=doc$1.createElement("div"),e=doc$1.body}return function(r){var i=[].slice.call(arguments,0);i.unshift(n),e.appendChild(n),n.addBehavior("#default#userData"),n.load(storageName),r.apply(this,i),e.removeChild(n)}}var util$2=util$7,Global$1=util$2.Global,trim=util$2.trim,cookieStorage={name:"cookieStorage",read:read$3,write:write$3,each:each$4,remove:remove$2,clearAll:clearAll$2},doc=Global$1.document;function read$3(t){if(!t||!_has(t))return null;var e="(?:^|.*;\\s*)"+escape(t).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*";return unescape(doc.cookie.replace(new RegExp(e),"$1"))}function each$4(t){for(var e=doc.cookie.split(/; ?/g),a=e.length-1;a>=0;a--)if(trim(e[a])){var n=e[a].split("="),r=unescape(n[0]),i=unescape(n[1]);t(i,r)}}function write$3(t,e){t&&(doc.cookie=escape(t)+"="+escape(e)+"; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/")}function remove$2(t){!t||!_has(t)||(doc.cookie=escape(t)+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/")}function clearAll$2(){each$4(function(t,e){remove$2(e)})}function _has(t){return new RegExp("(?:^|;\\s*)"+escape(t).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=").test(doc.cookie)}var util$1=util$7,Global=util$1.Global,sessionStorage_1={name:"sessionStorage",read:read$2,write:write$2,each:each$3,remove:remove$1,clearAll:clearAll$1};function sessionStorage(){return Global.sessionStorage}function read$2(t){return sessionStorage().getItem(t)}function write$2(t,e){return sessionStorage().setItem(t,e)}function each$3(t){for(var e=sessionStorage().length-1;e>=0;e--){var a=sessionStorage().key(e);t(read$2(a),a)}}function remove$1(t){return sessionStorage().removeItem(t)}function clearAll$1(){return sessionStorage().clear()}var memoryStorage_1={name:"memoryStorage",read:read$1,write:write$1,each:each$2,remove,clearAll},memoryStorage={};function read$1(t){return memoryStorage[t]}function write$1(t,e){memoryStorage[t]=e}function each$2(t){for(var e in memoryStorage)memoryStorage.hasOwnProperty(e)&&t(memoryStorage[e],e)}function remove(t){delete memoryStorage[t]}function clearAll(t){memoryStorage={}}var all=[localStorage_1,oldFFGlobalStorage,oldIEUserDataStorage,cookieStorage,sessionStorage_1,memoryStorage_1],json2$1={},hasRequiredJson2;function requireJson2(){return hasRequiredJson2||(hasRequiredJson2=1,typeof JSON!="object"&&(JSON={}),function(){var rx_one=/^[\],:{}\s]*$/,rx_two=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,rx_three=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,rx_four=/(?:^|:|,)(?:\s*\[)+/g,rx_escapable=/[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,rx_dangerous=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;function f(t){return t<10?"0"+t:t}function this_value(){return this.valueOf()}typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},Boolean.prototype.toJSON=this_value,Number.prototype.toJSON=this_value,String.prototype.toJSON=this_value);var gap,indent,meta,rep;function quote(t){return rx_escapable.lastIndex=0,rx_escapable.test(t)?'"'+t.replace(rx_escapable,function(e){var a=meta[e];return typeof a=="string"?a:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var a,n,r,i,o=gap,s,l=e[t];switch(l&&typeof l=="object"&&typeof l.toJSON=="function"&&(l=l.toJSON(t)),typeof rep=="function"&&(l=rep.call(e,t,l)),typeof l){case"string":return quote(l);case"number":return isFinite(l)?String(l):"null";case"boolean":case"null":return String(l);case"object":if(!l)return"null";if(gap+=indent,s=[],Object.prototype.toString.apply(l)==="[object Array]"){for(i=l.length,a=0;an.set(r)),n}static accessor(e){const n=(this[$internals]=this[$internals]={accessors:{}}).accessors,r=this.prototype;function i(o){const s=normalizeHeader(o);n[s]||(buildAccessors(r,o),n[s]=!0)}return utils.isArray(e)?e.forEach(i):i(e),this}}AxiosHeaders.accessor(["Content-Type","Content-Length","Accept","Accept-Encoding","User-Agent","Authorization"]);utils.reduceDescriptors(AxiosHeaders.prototype,({value:t},e)=>{let a=e[0].toUpperCase()+e.slice(1);return{get:()=>t,set(n){this[a]=n}}});utils.freezeMethods(AxiosHeaders);const AxiosHeaders$1=AxiosHeaders;function transformData(t,e){const a=this||defaults$2,n=e||a,r=AxiosHeaders$1.from(n.headers);let i=n.data;return utils.forEach(t,function(s){i=s.call(a,i,r.normalize(),e?e.status:void 0)}),r.normalize(),i}function isCancel(t){return!!(t&&t.__CANCEL__)}function CanceledError(t,e,a){AxiosError.call(this,t??"canceled",AxiosError.ERR_CANCELED,e,a),this.name="CanceledError"}utils.inherits(CanceledError,AxiosError,{__CANCEL__:!0});function settle(t,e,a){const n=a.config.validateStatus;!a.status||!n||n(a.status)?t(a):e(new AxiosError("Request failed with status code "+a.status,[AxiosError.ERR_BAD_REQUEST,AxiosError.ERR_BAD_RESPONSE][Math.floor(a.status/100)-4],a.config,a.request,a))}const cookies=platform.isStandardBrowserEnv?function(){return{write:function(a,n,r,i,o,s){const l=[];l.push(a+"="+encodeURIComponent(n)),utils.isNumber(r)&&l.push("expires="+new Date(r).toGMTString()),utils.isString(i)&&l.push("path="+i),utils.isString(o)&&l.push("domain="+o),s===!0&&l.push("secure"),document.cookie=l.join("; ")},read:function(a){const n=document.cookie.match(new RegExp("(^|;\\s*)("+a+")=([^;]*)"));return n?decodeURIComponent(n[3]):null},remove:function(a){this.write(a,"",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}();function isAbsoluteURL(t){return/^([a-z][a-z\d+\-.]*:)?\/\//i.test(t)}function combineURLs(t,e){return e?t.replace(/\/+$/,"")+"/"+e.replace(/^\/+/,""):t}function buildFullPath(t,e){return t&&!isAbsoluteURL(e)?combineURLs(t,e):e}const isURLSameOrigin=platform.isStandardBrowserEnv?function(){const e=/(msie|trident)/i.test(navigator.userAgent),a=document.createElement("a");let n;function r(i){let o=i;return e&&(a.setAttribute("href",o),o=a.href),a.setAttribute("href",o),{href:a.href,protocol:a.protocol?a.protocol.replace(/:$/,""):"",host:a.host,search:a.search?a.search.replace(/^\?/,""):"",hash:a.hash?a.hash.replace(/^#/,""):"",hostname:a.hostname,port:a.port,pathname:a.pathname.charAt(0)==="/"?a.pathname:"/"+a.pathname}}return n=r(window.location.href),function(o){const s=utils.isString(o)?r(o):o;return s.protocol===n.protocol&&s.host===n.host}}():function(){return function(){return!0}}();function parseProtocol(t){const e=/^([-+\w]{1,25})(:?\/\/|:)/.exec(t);return e&&e[1]||""}function speedometer(t,e){t=t||10;const a=new Array(t),n=new Array(t);let r=0,i=0,o;return e=e!==void 0?e:1e3,function(l){const u=Date.now(),c=n[i];o||(o=u),a[r]=l,n[r]=u;let d=i,h=0;for(;d!==r;)h+=a[d++],d=d%t;if(r=(r+1)%t,r===i&&(i=(i+1)%t),u-o{const i=r.loaded,o=r.lengthComputable?r.total:void 0,s=i-a,l=n(s),u=i<=o;a=i;const c={loaded:i,total:o,progress:o?i/o:void 0,bytes:s,rate:l||void 0,estimated:l&&o&&u?(o-i)/l:void 0,event:r};c[e?"download":"upload"]=!0,t(c)}}const isXHRAdapterSupported=typeof XMLHttpRequest<"u",xhrAdapter=isXHRAdapterSupported&&function(t){return new Promise(function(a,n){let r=t.data;const i=AxiosHeaders$1.from(t.headers).normalize(),o=t.responseType;let s;function l(){t.cancelToken&&t.cancelToken.unsubscribe(s),t.signal&&t.signal.removeEventListener("abort",s)}utils.isFormData(r)&&(platform.isStandardBrowserEnv||platform.isStandardBrowserWebWorkerEnv?i.setContentType(!1):i.setContentType("multipart/form-data;",!1));let u=new XMLHttpRequest;if(t.auth){const m=t.auth.username||"",p=t.auth.password?unescape(encodeURIComponent(t.auth.password)):"";i.set("Authorization","Basic "+btoa(m+":"+p))}const c=buildFullPath(t.baseURL,t.url);u.open(t.method.toUpperCase(),buildURL(c,t.params,t.paramsSerializer),!0),u.timeout=t.timeout;function d(){if(!u)return;const m=AxiosHeaders$1.from("getAllResponseHeaders"in u&&u.getAllResponseHeaders()),v={data:!o||o==="text"||o==="json"?u.responseText:u.response,status:u.status,statusText:u.statusText,headers:m,config:t,request:u};settle(function(w){a(w),l()},function(w){n(w),l()},v),u=null}if("onloadend"in u?u.onloadend=d:u.onreadystatechange=function(){!u||u.readyState!==4||u.status===0&&!(u.responseURL&&u.responseURL.indexOf("file:")===0)||setTimeout(d)},u.onabort=function(){u&&(n(new AxiosError("Request aborted",AxiosError.ECONNABORTED,t,u)),u=null)},u.onerror=function(){n(new AxiosError("Network Error",AxiosError.ERR_NETWORK,t,u)),u=null},u.ontimeout=function(){let p=t.timeout?"timeout of "+t.timeout+"ms exceeded":"timeout exceeded";const v=t.transitional||transitionalDefaults;t.timeoutErrorMessage&&(p=t.timeoutErrorMessage),n(new AxiosError(p,v.clarifyTimeoutError?AxiosError.ETIMEDOUT:AxiosError.ECONNABORTED,t,u)),u=null},platform.isStandardBrowserEnv){const m=(t.withCredentials||isURLSameOrigin(c))&&t.xsrfCookieName&&cookies.read(t.xsrfCookieName);m&&i.set(t.xsrfHeaderName,m)}r===void 0&&i.setContentType(null),"setRequestHeader"in u&&utils.forEach(i.toJSON(),function(p,v){u.setRequestHeader(v,p)}),utils.isUndefined(t.withCredentials)||(u.withCredentials=!!t.withCredentials),o&&o!=="json"&&(u.responseType=t.responseType),typeof t.onDownloadProgress=="function"&&u.addEventListener("progress",progressEventReducer(t.onDownloadProgress,!0)),typeof t.onUploadProgress=="function"&&u.upload&&u.upload.addEventListener("progress",progressEventReducer(t.onUploadProgress)),(t.cancelToken||t.signal)&&(s=m=>{u&&(n(!m||m.type?new CanceledError(null,t,u):m),u.abort(),u=null)},t.cancelToken&&t.cancelToken.subscribe(s),t.signal&&(t.signal.aborted?s():t.signal.addEventListener("abort",s)));const h=parseProtocol(c);if(h&&platform.protocols.indexOf(h)===-1){n(new AxiosError("Unsupported protocol "+h+":",AxiosError.ERR_BAD_REQUEST,t));return}u.send(r||null)})},knownAdapters={http:httpAdapter,xhr:xhrAdapter};utils.forEach(knownAdapters,(t,e)=>{if(t){try{Object.defineProperty(t,"name",{value:e})}catch{}Object.defineProperty(t,"adapterName",{value:e})}});const adapters$1={getAdapter:t=>{t=utils.isArray(t)?t:[t];const{length:e}=t;let a,n;for(let r=0;rt instanceof AxiosHeaders$1?t.toJSON():t;function mergeConfig(t,e){e=e||{};const a={};function n(u,c,d){return utils.isPlainObject(u)&&utils.isPlainObject(c)?utils.merge.call({caseless:d},u,c):utils.isPlainObject(c)?utils.merge({},c):utils.isArray(c)?c.slice():c}function r(u,c,d){if(utils.isUndefined(c)){if(!utils.isUndefined(u))return n(void 0,u,d)}else return n(u,c,d)}function i(u,c){if(!utils.isUndefined(c))return n(void 0,c)}function o(u,c){if(utils.isUndefined(c)){if(!utils.isUndefined(u))return n(void 0,u)}else return n(void 0,c)}function s(u,c,d){if(d in e)return n(u,c);if(d in t)return n(void 0,u)}const l={url:i,method:i,data:i,baseURL:o,transformRequest:o,transformResponse:o,paramsSerializer:o,timeout:o,timeoutMessage:o,withCredentials:o,adapter:o,responseType:o,xsrfCookieName:o,xsrfHeaderName:o,onUploadProgress:o,onDownloadProgress:o,decompress:o,maxContentLength:o,maxBodyLength:o,beforeRedirect:o,transport:o,httpAgent:o,httpsAgent:o,cancelToken:o,socketPath:o,responseEncoding:o,validateStatus:s,headers:(u,c)=>r(headersToObject(u),headersToObject(c),!0)};return utils.forEach(Object.keys(Object.assign({},t,e)),function(c){const d=l[c]||r,h=d(t[c],e[c],c);utils.isUndefined(h)&&d!==s||(a[c]=h)}),a}const VERSION$1="1.5.0",validators$1={};["object","boolean","number","function","string","symbol"].forEach((t,e)=>{validators$1[t]=function(n){return typeof n===t||"a"+(e<1?"n ":" ")+t}});const deprecatedWarnings={};validators$1.transitional=function(e,a,n){function r(i,o){return"[Axios v"+VERSION$1+"] Transitional option '"+i+"'"+o+(n?". "+n:"")}return(i,o,s)=>{if(e===!1)throw new AxiosError(r(o," has been removed"+(a?" in "+a:"")),AxiosError.ERR_DEPRECATED);return a&&!deprecatedWarnings[o]&&(deprecatedWarnings[o]=!0,console.warn(r(o," has been deprecated since v"+a+" and will be removed in the near future"))),e?e(i,o,s):!0}};function assertOptions(t,e,a){if(typeof t!="object")throw new AxiosError("options must be an object",AxiosError.ERR_BAD_OPTION_VALUE);const n=Object.keys(t);let r=n.length;for(;r-- >0;){const i=n[r],o=e[i];if(o){const s=t[i],l=s===void 0||o(s,i,t);if(l!==!0)throw new AxiosError("option "+i+" must be "+l,AxiosError.ERR_BAD_OPTION_VALUE);continue}if(a!==!0)throw new AxiosError("Unknown option "+i,AxiosError.ERR_BAD_OPTION)}}const validator={assertOptions,validators:validators$1},validators=validator.validators;class Axios{constructor(e){this.defaults=e,this.interceptors={request:new InterceptorManager$1,response:new InterceptorManager$1}}request(e,a){typeof e=="string"?(a=a||{},a.url=e):a=e||{},a=mergeConfig(this.defaults,a);const{transitional:n,paramsSerializer:r,headers:i}=a;n!==void 0&&validator.assertOptions(n,{silentJSONParsing:validators.transitional(validators.boolean),forcedJSONParsing:validators.transitional(validators.boolean),clarifyTimeoutError:validators.transitional(validators.boolean)},!1),r!=null&&(utils.isFunction(r)?a.paramsSerializer={serialize:r}:validator.assertOptions(r,{encode:validators.function,serialize:validators.function},!0)),a.method=(a.method||this.defaults.method||"get").toLowerCase();let o=i&&utils.merge(i.common,i[a.method]);i&&utils.forEach(["delete","get","head","post","put","patch","common"],p=>{delete i[p]}),a.headers=AxiosHeaders$1.concat(o,i);const s=[];let l=!0;this.interceptors.request.forEach(function(v){typeof v.runWhen=="function"&&v.runWhen(a)===!1||(l=l&&v.synchronous,s.unshift(v.fulfilled,v.rejected))});const u=[];this.interceptors.response.forEach(function(v){u.push(v.fulfilled,v.rejected)});let c,d=0,h;if(!l){const p=[dispatchRequest.bind(this),void 0];for(p.unshift.apply(p,s),p.push.apply(p,u),h=p.length,c=Promise.resolve(a);d{if(!n._listeners)return;let i=n._listeners.length;for(;i-- >0;)n._listeners[i](r);n._listeners=null}),this.promise.then=r=>{let i;const o=new Promise(s=>{n.subscribe(s),i=s}).then(r);return o.cancel=function(){n.unsubscribe(i)},o},e(function(i,o,s){n.reason||(n.reason=new CanceledError(i,o,s),a(n.reason))})}throwIfRequested(){if(this.reason)throw this.reason}subscribe(e){if(this.reason){e(this.reason);return}this._listeners?this._listeners.push(e):this._listeners=[e]}unsubscribe(e){if(!this._listeners)return;const a=this._listeners.indexOf(e);a!==-1&&this._listeners.splice(a,1)}static source(){let e;return{token:new CancelToken(function(r){e=r}),cancel:e}}}const CancelToken$1=CancelToken;function spread(t){return function(a){return t.apply(null,a)}}function isAxiosError(t){return utils.isObject(t)&&t.isAxiosError===!0}const HttpStatusCode={Continue:100,SwitchingProtocols:101,Processing:102,EarlyHints:103,Ok:200,Created:201,Accepted:202,NonAuthoritativeInformation:203,NoContent:204,ResetContent:205,PartialContent:206,MultiStatus:207,AlreadyReported:208,ImUsed:226,MultipleChoices:300,MovedPermanently:301,Found:302,SeeOther:303,NotModified:304,UseProxy:305,Unused:306,TemporaryRedirect:307,PermanentRedirect:308,BadRequest:400,Unauthorized:401,PaymentRequired:402,Forbidden:403,NotFound:404,MethodNotAllowed:405,NotAcceptable:406,ProxyAuthenticationRequired:407,RequestTimeout:408,Conflict:409,Gone:410,LengthRequired:411,PreconditionFailed:412,PayloadTooLarge:413,UriTooLong:414,UnsupportedMediaType:415,RangeNotSatisfiable:416,ExpectationFailed:417,ImATeapot:418,MisdirectedRequest:421,UnprocessableEntity:422,Locked:423,FailedDependency:424,TooEarly:425,UpgradeRequired:426,PreconditionRequired:428,TooManyRequests:429,RequestHeaderFieldsTooLarge:431,UnavailableForLegalReasons:451,InternalServerError:500,NotImplemented:501,BadGateway:502,ServiceUnavailable:503,GatewayTimeout:504,HttpVersionNotSupported:505,VariantAlsoNegotiates:506,InsufficientStorage:507,LoopDetected:508,NotExtended:510,NetworkAuthenticationRequired:511};Object.entries(HttpStatusCode).forEach(([t,e])=>{HttpStatusCode[e]=t});const HttpStatusCode$1=HttpStatusCode;function createInstance(t){const e=new Axios$1(t),a=bind$4(Axios$1.prototype.request,e);return utils.extend(a,Axios$1.prototype,e,{allOwnKeys:!0}),utils.extend(a,e,null,{allOwnKeys:!0}),a.create=function(r){return createInstance(mergeConfig(t,r))},a}const axios=createInstance(defaults$2);axios.Axios=Axios$1;axios.CanceledError=CanceledError;axios.CancelToken=CancelToken$1;axios.isCancel=isCancel;axios.VERSION=VERSION$1;axios.toFormData=toFormData;axios.AxiosError=AxiosError;axios.Cancel=axios.CanceledError;axios.all=function(e){return Promise.all(e)};axios.spread=spread;axios.isAxiosError=isAxiosError;axios.mergeConfig=mergeConfig;axios.AxiosHeaders=AxiosHeaders$1;axios.formToJSON=t=>formDataToJSON(utils.isHTMLForm(t)?new FormData(t):t);axios.getAdapter=adapters$1.getAdapter;axios.HttpStatusCode=HttpStatusCode$1;axios.default=axios;const axios$1=axios;var commonjsGlobal=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function getDefaultExportFromCjs(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var assign$1=make_assign(),create$2=make_create(),trim$1=make_trim(),Global$5=typeof window<"u"?window:commonjsGlobal,util$7={assign:assign$1,create:create$2,trim:trim$1,bind:bind$3,slice:slice$2,each:each$9,map:map$2,pluck:pluck$1,isList:isList$1,isFunction:isFunction$5,isObject:isObject$b,Global:Global$5};function make_assign(){return Object.assign?Object.assign:function(e,a,n,r){for(var i=1;i"u"?null:console;if(t){var e=t.warn?t.warn:t.log;e.apply(t,arguments)}}function createStore(t,e,a){a||(a=""),t&&!isList(t)&&(t=[t]),e&&!isList(e)&&(e=[e]);var n=a?"__storejs_"+a+"_":"",r=a?new RegExp("^"+n):null,i=/^[a-zA-Z0-9_\-]*$/;if(!i.test(a))throw new Error("store.js namespaces can only have alphanumerics + underscores and dashes");var o={_namespacePrefix:n,_namespaceRegexp:r,_testStorage:function(l){try{var u="__storejs__test__";l.write(u,u);var c=l.read(u)===u;return l.remove(u),c}catch{return!1}},_assignPluginFnProp:function(l,u){var c=this[u];this[u]=function(){var h=slice$1(arguments,0),m=this;function p(){if(c)return each$8(arguments,function(y,w){h[w]=y}),c.apply(m,h)}var v=[p].concat(h);return l.apply(m,v)}},_serialize:function(l){return JSON.stringify(l)},_deserialize:function(l,u){if(!l)return u;var c="";try{c=JSON.parse(l)}catch{c=l}return c!==void 0?c:u},_addStorage:function(l){this.enabled||this._testStorage(l)&&(this.storage=l,this.enabled=!0)},_addPlugin:function(l){var u=this;if(isList(l)){each$8(l,function(h){u._addPlugin(h)});return}var c=pluck(this.plugins,function(h){return l===h});if(!c){if(this.plugins.push(l),!isFunction$4(l))throw new Error("Plugins must be function values that return objects");var d=l.call(this);if(!isObject$a(d))throw new Error("Plugins must return an object of function properties");each$8(d,function(h,m){if(!isFunction$4(h))throw new Error("Bad plugin property: "+m+" from plugin "+l.name+". Plugins should only return functions.");u._assignPluginFnProp(h,m)})}},addStorage:function(l){_warn("store.addStorage(storage) is deprecated. Use createStore([storages])"),this._addStorage(l)}},s=create$1(o,storeAPI,{plugins:[]});return s.raw={},each$8(s,function(l,u){isFunction$4(l)&&(s.raw[u]=bind$2(s,l))}),each$8(t,function(l){s._addStorage(l)}),each$8(e,function(l){s._addPlugin(l)}),s}var util$5=util$7,Global$4=util$5.Global,localStorage_1={name:"localStorage",read:read$6,write:write$6,each:each$7,remove:remove$5,clearAll:clearAll$5};function localStorage(){return Global$4.localStorage}function read$6(t){return localStorage().getItem(t)}function write$6(t,e){return localStorage().setItem(t,e)}function each$7(t){for(var e=localStorage().length-1;e>=0;e--){var a=localStorage().key(e);t(read$6(a),a)}}function remove$5(t){return localStorage().removeItem(t)}function clearAll$5(){return localStorage().clear()}var util$4=util$7,Global$3=util$4.Global,oldFFGlobalStorage={name:"oldFF-globalStorage",read:read$5,write:write$5,each:each$6,remove:remove$4,clearAll:clearAll$4},globalStorage=Global$3.globalStorage;function read$5(t){return globalStorage[t]}function write$5(t,e){globalStorage[t]=e}function each$6(t){for(var e=globalStorage.length-1;e>=0;e--){var a=globalStorage.key(e);t(globalStorage[a],a)}}function remove$4(t){return globalStorage.removeItem(t)}function clearAll$4(){each$6(function(t,e){delete globalStorage[t]})}var util$3=util$7,Global$2=util$3.Global,oldIEUserDataStorage={name:"oldIE-userDataStorage",write:write$4,read:read$4,each:each$5,remove:remove$3,clearAll:clearAll$3},storageName="storejs",doc$1=Global$2.document,_withStorageEl=_makeIEStorageElFunction(),disable=(Global$2.navigator?Global$2.navigator.userAgent:"").match(/ (MSIE 8|MSIE 9|MSIE 10)\./);function write$4(t,e){if(!disable){var a=fixKey(t);_withStorageEl(function(n){n.setAttribute(a,e),n.save(storageName)})}}function read$4(t){if(!disable){var e=fixKey(t),a=null;return _withStorageEl(function(n){a=n.getAttribute(e)}),a}}function each$5(t){_withStorageEl(function(e){for(var a=e.XMLDocument.documentElement.attributes,n=a.length-1;n>=0;n--){var r=a[n];t(e.getAttribute(r.name),r.name)}})}function remove$3(t){var e=fixKey(t);_withStorageEl(function(a){a.removeAttribute(e),a.save(storageName)})}function clearAll$3(){_withStorageEl(function(t){var e=t.XMLDocument.documentElement.attributes;t.load(storageName);for(var a=e.length-1;a>=0;a--)t.removeAttribute(e[a].name);t.save(storageName)})}var forbiddenCharsRegex=new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]","g");function fixKey(t){return t.replace(/^\d/,"___$&").replace(forbiddenCharsRegex,"___")}function _makeIEStorageElFunction(){if(!doc$1||!doc$1.documentElement||!doc$1.documentElement.addBehavior)return null;var t="script",e,a,n;try{a=new ActiveXObject("htmlfile"),a.open(),a.write("<"+t+">document.w=window'),a.close(),e=a.w.frames[0].document,n=e.createElement("div")}catch{n=doc$1.createElement("div"),e=doc$1.body}return function(r){var i=[].slice.call(arguments,0);i.unshift(n),e.appendChild(n),n.addBehavior("#default#userData"),n.load(storageName),r.apply(this,i),e.removeChild(n)}}var util$2=util$7,Global$1=util$2.Global,trim=util$2.trim,cookieStorage={name:"cookieStorage",read:read$3,write:write$3,each:each$4,remove:remove$2,clearAll:clearAll$2},doc=Global$1.document;function read$3(t){if(!t||!_has(t))return null;var e="(?:^|.*;\\s*)"+escape(t).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*";return unescape(doc.cookie.replace(new RegExp(e),"$1"))}function each$4(t){for(var e=doc.cookie.split(/; ?/g),a=e.length-1;a>=0;a--)if(trim(e[a])){var n=e[a].split("="),r=unescape(n[0]),i=unescape(n[1]);t(i,r)}}function write$3(t,e){t&&(doc.cookie=escape(t)+"="+escape(e)+"; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/")}function remove$2(t){!t||!_has(t)||(doc.cookie=escape(t)+"=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/")}function clearAll$2(){each$4(function(t,e){remove$2(e)})}function _has(t){return new RegExp("(?:^|;\\s*)"+escape(t).replace(/[\-\.\+\*]/g,"\\$&")+"\\s*\\=").test(doc.cookie)}var util$1=util$7,Global=util$1.Global,sessionStorage_1={name:"sessionStorage",read:read$2,write:write$2,each:each$3,remove:remove$1,clearAll:clearAll$1};function sessionStorage(){return Global.sessionStorage}function read$2(t){return sessionStorage().getItem(t)}function write$2(t,e){return sessionStorage().setItem(t,e)}function each$3(t){for(var e=sessionStorage().length-1;e>=0;e--){var a=sessionStorage().key(e);t(read$2(a),a)}}function remove$1(t){return sessionStorage().removeItem(t)}function clearAll$1(){return sessionStorage().clear()}var memoryStorage_1={name:"memoryStorage",read:read$1,write:write$1,each:each$2,remove,clearAll},memoryStorage={};function read$1(t){return memoryStorage[t]}function write$1(t,e){memoryStorage[t]=e}function each$2(t){for(var e in memoryStorage)memoryStorage.hasOwnProperty(e)&&t(memoryStorage[e],e)}function remove(t){delete memoryStorage[t]}function clearAll(t){memoryStorage={}}var all=[localStorage_1,oldFFGlobalStorage,oldIEUserDataStorage,cookieStorage,sessionStorage_1,memoryStorage_1],json2$1={},hasRequiredJson2;function requireJson2(){return hasRequiredJson2||(hasRequiredJson2=1,typeof JSON!="object"&&(JSON={}),function(){var rx_one=/^[\],:{}\s]*$/,rx_two=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,rx_three=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,rx_four=/(?:^|:|,)(?:\s*\[)+/g,rx_escapable=/[\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,rx_dangerous=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;function f(t){return t<10?"0"+t:t}function this_value(){return this.valueOf()}typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},Boolean.prototype.toJSON=this_value,Number.prototype.toJSON=this_value,String.prototype.toJSON=this_value);var gap,indent,meta,rep;function quote(t){return rx_escapable.lastIndex=0,rx_escapable.test(t)?'"'+t.replace(rx_escapable,function(e){var a=meta[e];return typeof a=="string"?a:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+t+'"'}function str(t,e){var a,n,r,i,o=gap,s,l=e[t];switch(l&&typeof l=="object"&&typeof l.toJSON=="function"&&(l=l.toJSON(t)),typeof rep=="function"&&(l=rep.call(e,t,l)),typeof l){case"string":return quote(l);case"number":return isFinite(l)?String(l):"null";case"boolean":case"null":return String(l);case"object":if(!l)return"null";if(gap+=indent,s=[],Object.prototype.toString.apply(l)==="[object Array]"){for(i=l.length,a=0;alastFlushedIndex&&queue.splice(e,1)}function queueFlush(){!flushing&&!flushPending&&(flushPending=!0,queueMicrotask(flushJobs))}function flushJobs(){flushPending=!1,flushing=!0;for(let t=0;tt.effect(e,{scheduler:a=>{shouldSchedule?scheduler(a):a()}}),raw=t.raw}function overrideEffect(t){effect$3=t}function elementBoundEffect(t){let e=()=>{};return[n=>{let r=effect$3(n);return t._x_effects||(t._x_effects=new Set,t._x_runEffects=()=>{t._x_effects.forEach(i=>i())}),t._x_effects.add(r),e=()=>{r!==void 0&&(t._x_effects.delete(r),release(r))},r},()=>{e()}]}var onAttributeAddeds=[],onElRemoveds=[],onElAddeds=[];function onElAdded(t){onElAddeds.push(t)}function onElRemoved(t,e){typeof e=="function"?(t._x_cleanups||(t._x_cleanups=[]),t._x_cleanups.push(e)):(e=t,onElRemoveds.push(e))}function onAttributesAdded(t){onAttributeAddeds.push(t)}function onAttributeRemoved(t,e,a){t._x_attributeCleanups||(t._x_attributeCleanups={}),t._x_attributeCleanups[e]||(t._x_attributeCleanups[e]=[]),t._x_attributeCleanups[e].push(a)}function cleanupAttributes(t,e){t._x_attributeCleanups&&Object.entries(t._x_attributeCleanups).forEach(([a,n])=>{(e===void 0||e.includes(a))&&(n.forEach(r=>r()),delete t._x_attributeCleanups[a])})}var observer=new MutationObserver(onMutate),currentlyObserving=!1;function startObservingMutations(){observer.observe(document,{subtree:!0,childList:!0,attributes:!0,attributeOldValue:!0}),currentlyObserving=!0}function stopObservingMutations(){flushObserver(),observer.disconnect(),currentlyObserving=!1}var recordQueue=[],willProcessRecordQueue=!1;function flushObserver(){recordQueue=recordQueue.concat(observer.takeRecords()),recordQueue.length&&!willProcessRecordQueue&&(willProcessRecordQueue=!0,queueMicrotask(()=>{processRecordQueue(),willProcessRecordQueue=!1}))}function processRecordQueue(){onMutate(recordQueue),recordQueue.length=0}function mutateDom(t){if(!currentlyObserving)return t();stopObservingMutations();let e=t();return startObservingMutations(),e}var isCollecting=!1,deferredMutations=[];function deferMutations(){isCollecting=!0}function flushAndStopDeferringMutations(){isCollecting=!1,onMutate(deferredMutations),deferredMutations=[]}function onMutate(t){if(isCollecting){deferredMutations=deferredMutations.concat(t);return}let e=[],a=[],n=new Map,r=new Map;for(let i=0;io.nodeType===1&&e.push(o)),t[i].removedNodes.forEach(o=>o.nodeType===1&&a.push(o))),t[i].type==="attributes")){let o=t[i].target,s=t[i].attributeName,l=t[i].oldValue,u=()=>{n.has(o)||n.set(o,[]),n.get(o).push({name:s,value:o.getAttribute(s)})},c=()=>{r.has(o)||r.set(o,[]),r.get(o).push(s)};o.hasAttribute(s)&&l===null?u():o.hasAttribute(s)?(c(),u()):c()}r.forEach((i,o)=>{cleanupAttributes(o,i)}),n.forEach((i,o)=>{onAttributeAddeds.forEach(s=>s(o,i))});for(let i of a)if(!e.includes(i)&&(onElRemoveds.forEach(o=>o(i)),i._x_cleanups))for(;i._x_cleanups.length;)i._x_cleanups.pop()();e.forEach(i=>{i._x_ignoreSelf=!0,i._x_ignore=!0});for(let i of e)a.includes(i)||i.isConnected&&(delete i._x_ignoreSelf,delete i._x_ignore,onElAddeds.forEach(o=>o(i)),i._x_ignore=!0,i._x_ignoreSelf=!0);e.forEach(i=>{delete i._x_ignoreSelf,delete i._x_ignore}),e=null,a=null,n=null,r=null}function scope(t){return mergeProxies(closestDataStack(t))}function addScopeToNode(t,e,a){return t._x_dataStack=[e,...closestDataStack(a||t)],()=>{t._x_dataStack=t._x_dataStack.filter(n=>n!==e)}}function closestDataStack(t){return t._x_dataStack?t._x_dataStack:typeof ShadowRoot=="function"&&t instanceof ShadowRoot?closestDataStack(t.host):t.parentNode?closestDataStack(t.parentNode):[]}function mergeProxies(t){let e=new Proxy({},{ownKeys:()=>Array.from(new Set(t.flatMap(a=>Object.keys(a)))),has:(a,n)=>t.some(r=>r.hasOwnProperty(n)),get:(a,n)=>(t.find(r=>{if(r.hasOwnProperty(n)){let i=Object.getOwnPropertyDescriptor(r,n);if(i.get&&i.get._x_alreadyBound||i.set&&i.set._x_alreadyBound)return!0;if((i.get||i.set)&&i.enumerable){let o=i.get,s=i.set,l=i;o=o&&o.bind(e),s=s&&s.bind(e),o&&(o._x_alreadyBound=!0),s&&(s._x_alreadyBound=!0),Object.defineProperty(r,n,{...l,get:o,set:s})}return!0}return!1})||{})[n],set:(a,n,r)=>{let i=t.find(o=>o.hasOwnProperty(n));return i?i[n]=r:t[t.length-1][n]=r,!0}});return e}function initInterceptors(t){let e=n=>typeof n=="object"&&!Array.isArray(n)&&n!==null,a=(n,r="")=>{Object.entries(Object.getOwnPropertyDescriptors(n)).forEach(([i,{value:o,enumerable:s}])=>{if(s===!1||o===void 0)return;let l=r===""?i:`${r}.${i}`;typeof o=="object"&&o!==null&&o._x_interceptor?n[i]=o.initialize(t,l,i):e(o)&&o!==n&&!(o instanceof Element)&&a(o,l)})};return a(t)}function interceptor(t,e=()=>{}){let a={initialValue:void 0,_x_interceptor:!0,initialize(n,r,i){return t(this.initialValue,()=>get$3(n,r),o=>set$3(n,r,o),r,i)}};return e(a),n=>{if(typeof n=="object"&&n!==null&&n._x_interceptor){let r=a.initialize.bind(a);a.initialize=(i,o,s)=>{let l=n.initialize(i,o,s);return a.initialValue=l,r(i,o,s)}}else a.initialValue=n;return a}}function get$3(t,e){return e.split(".").reduce((a,n)=>a[n],t)}function set$3(t,e,a){if(typeof e=="string"&&(e=e.split(".")),e.length===1)t[e[0]]=a;else{if(e.length===0)throw error;return t[e[0]]||(t[e[0]]={}),set$3(t[e[0]],e.slice(1),a)}}var magics={};function magic(t,e){magics[t]=e}function injectMagics(t,e){return Object.entries(magics).forEach(([a,n])=>{let r=null;function i(){if(r)return r;{let[o,s]=getElementBoundUtilities(e);return r={interceptor,...o},onElRemoved(e,s),r}}Object.defineProperty(t,`$${a}`,{get(){return n(e,i())},enumerable:!1})}),t}function tryCatch(t,e,a,...n){try{return a(...n)}catch(r){handleError(r,t,e)}}function handleError(t,e,a=void 0){Object.assign(t,{el:e,expression:a}),console.warn(`Alpine Expression Error: ${t.message} +`+o+"}":"{"+s.join(",")+"}",gap=o,r}}typeof JSON.stringify!="function"&&(meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},JSON.stringify=function(t,e,a){var n;if(gap="",indent="",typeof a=="number")for(n=0;nlastFlushedIndex&&queue.splice(e,1)}function queueFlush(){!flushing&&!flushPending&&(flushPending=!0,queueMicrotask(flushJobs))}function flushJobs(){flushPending=!1,flushing=!0;for(let t=0;tt.effect(e,{scheduler:a=>{shouldSchedule?scheduler(a):a()}}),raw=t.raw}function overrideEffect(t){effect$3=t}function elementBoundEffect(t){let e=()=>{};return[n=>{let r=effect$3(n);return t._x_effects||(t._x_effects=new Set,t._x_runEffects=()=>{t._x_effects.forEach(i=>i())}),t._x_effects.add(r),e=()=>{r!==void 0&&(t._x_effects.delete(r),release(r))},r},()=>{e()}]}function dispatch(t,e,a={}){t.dispatchEvent(new CustomEvent(e,{detail:a,bubbles:!0,composed:!0,cancelable:!0}))}function walk(t,e){if(typeof ShadowRoot=="function"&&t instanceof ShadowRoot){Array.from(t.children).forEach(r=>walk(r,e));return}let a=!1;if(e(t,()=>a=!0),a)return;let n=t.firstElementChild;for(;n;)walk(n,e),n=n.nextElementSibling}function warn(t,...e){console.warn(`Alpine Warning: ${t}`,...e)}var started=!1;function start$1(){started&&warn("Alpine has already been initialized on this page. Calling Alpine.start() more than once can cause problems."),started=!0,document.body||warn("Unable to initialize. Trying to load Alpine before `` is available. Did you forget to add `defer` in Alpine's ` - - - - - + + + + + {% endblock %} {% block styles %} {% endblock %} diff --git a/resources/views/javascript/variables.twig b/resources/views/javascript/variables.twig index 71a0c84137..65a669e8ac 100644 --- a/resources/views/javascript/variables.twig +++ b/resources/views/javascript/variables.twig @@ -54,9 +54,9 @@ var edit_selected_txt = "{{ trans('firefly.mass_edit')|escape('js') }}"; var edit_bulk_selected_txt = "{{ trans('firefly.bulk_edit')|escape('js') }}"; var delete_selected_txt = "{{ trans('firefly.mass_delete')|escape('js') }}"; -var mass_edit_url = '{{ route('transactions.mass.edit', ['']) }}'; -var bulk_edit_url = '{{ route('transactions.bulk.edit', ['']) }}'; -var mass_delete_url = '{{ route('transactions.mass.delete', ['']) }}'; +var mass_edit_url = '{{ route('transactions.mass.edit', [''], false) }}'; +var bulk_edit_url = '{{ route('transactions.bulk.edit', [''], false) }}'; +var mass_delete_url = '{{ route('transactions.mass.delete', [''], false) }}'; // for demo: var nextLabel = "{{ trans('firefly.intro_next_label')|escape('js') }}"; diff --git a/resources/views/layout/default.twig b/resources/views/layout/default.twig index 82fbcebedc..c29b0e0e80 100644 --- a/resources/views/layout/default.twig +++ b/resources/views/layout/default.twig @@ -1,7 +1,11 @@ - + + @@ -22,49 +26,60 @@ {# CSS things #} - - + + {# the theme #} - + {% if 'browser' == darkMode %} - - - - + + + + {% endif %} {% if 'dark' == darkMode %} - - + + {% endif %} {% if 'light' == darkMode %} - - + + {% endif %} {# Firefly III customisations #} - + {# Extra CSS for the demo: #} {% if not shownDemo %} - + {% endif %} {# Any local custom CSS. #} {% block styles %}{% endblock %} {# this entry is in the header so it's loaded early #} @@ -80,7 +95,7 @@
{# Logo #} -