Merge pull request #12327 from firefly-iii/release-1780342304

🤖 Automatically merge the PR into the develop branch.
This commit is contained in:
github-actions[bot]
2026-06-01 21:31:55 +02:00
committed by GitHub
20 changed files with 690 additions and 479 deletions
+196 -104
View File
@@ -471,23 +471,23 @@
},
{
"name": "friendsofphp/php-cs-fixer",
"version": "v3.95.2",
"version": "v3.95.3",
"source": {
"type": "git",
"url": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer.git",
"reference": "a28d88a5e172b27e78d0816992b15a9df3da20f1"
"reference": "3d681493acc0e93283481b1c63c263737df78687"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/a28d88a5e172b27e78d0816992b15a9df3da20f1",
"reference": "a28d88a5e172b27e78d0816992b15a9df3da20f1",
"url": "https://api.github.com/repos/PHP-CS-Fixer/PHP-CS-Fixer/zipball/3d681493acc0e93283481b1c63c263737df78687",
"reference": "3d681493acc0e93283481b1c63c263737df78687",
"shasum": ""
},
"require": {
"clue/ndjson-react": "^1.3",
"composer/semver": "^3.4",
"composer/xdebug-handler": "^3.0.5",
"ergebnis/agent-detector": "^1.1.1",
"ergebnis/agent-detector": "^1.2",
"ext-filter": "*",
"ext-hash": "*",
"ext-json": "*",
@@ -504,10 +504,10 @@
"symfony/filesystem": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/finder": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/options-resolver": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0",
"symfony/polyfill-mbstring": "^1.33",
"symfony/polyfill-php80": "^1.33",
"symfony/polyfill-php81": "^1.33",
"symfony/polyfill-php84": "^1.33",
"symfony/polyfill-mbstring": "^1.37",
"symfony/polyfill-php80": "^1.37",
"symfony/polyfill-php81": "^1.37",
"symfony/polyfill-php84": "^1.37",
"symfony/process": "^5.4.47 || ^6.4.24 || ^7.2 || ^8.0",
"symfony/stopwatch": "^5.4.45 || ^6.4.24 || ^7.0 || ^8.0"
},
@@ -521,9 +521,9 @@
"php-cs-fixer/phpunit-constraint-isidenticalstring": "^1.8",
"php-cs-fixer/phpunit-constraint-xmlmatchesxsd": "^1.8",
"phpunit/phpunit": "^9.6.34 || ^10.5.63 || ^11.5.55",
"symfony/polyfill-php85": "^1.33",
"symfony/polyfill-php85": "^1.37",
"symfony/var-dumper": "^5.4.48 || ^6.4.32 || ^7.4.4 || ^8.0.8",
"symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.8"
"symfony/yaml": "^5.4.45 || ^6.4.30 || ^7.4.1 || ^8.0.11"
},
"suggest": {
"ext-dom": "For handling output formats in XML",
@@ -564,7 +564,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.95.2"
"source": "https://github.com/PHP-CS-Fixer/PHP-CS-Fixer/tree/v3.95.3"
},
"funding": [
{
@@ -572,7 +572,7 @@
"type": "github"
}
],
"time": "2026-05-15T09:20:44+00:00"
"time": "2026-05-29T20:35:26+00:00"
},
{
"name": "psr/container",
@@ -1334,23 +1334,29 @@
},
{
"name": "symfony/console",
"version": "v8.0.11",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "3156577f46a38aa1b9323aad223de7a9cd426782"
"reference": "f5a856c6ecb56b3c21ed94a5b7bf940d857d110a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/3156577f46a38aa1b9323aad223de7a9cd426782",
"reference": "3156577f46a38aa1b9323aad223de7a9cd426782",
"url": "https://api.github.com/repos/symfony/console/zipball/f5a856c6ecb56b3c21ed94a5b7bf940d857d110a",
"reference": "f5a856c6ecb56b3c21ed94a5b7bf940d857d110a",
"shasum": ""
},
"require": {
"php": ">=8.4",
"php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "^1.0",
"symfony/polyfill-php85": "^1.32",
"symfony/service-contracts": "^2.5|^3",
"symfony/string": "^7.4|^8.0"
"symfony/string": "^7.4.6|^8.0.6"
},
"conflict": {
"symfony/dependency-injection": "<8.1",
"symfony/event-dispatcher": "<8.1"
},
"provide": {
"psr/log-implementation": "1.0|2.0|3.0"
@@ -1358,14 +1364,18 @@
"require-dev": {
"psr/log": "^1|^2|^3",
"symfony/config": "^7.4|^8.0",
"symfony/dependency-injection": "^7.4|^8.0",
"symfony/event-dispatcher": "^7.4|^8.0",
"symfony/dependency-injection": "^8.1",
"symfony/event-dispatcher": "^8.1",
"symfony/filesystem": "^7.4|^8.0",
"symfony/http-foundation": "^7.4|^8.0",
"symfony/http-kernel": "^7.4|^8.0",
"symfony/lock": "^7.4|^8.0",
"symfony/messenger": "^7.4|^8.0",
"symfony/mime": "^7.4|^8.0",
"symfony/process": "^7.4|^8.0",
"symfony/stopwatch": "^7.4|^8.0",
"symfony/uid": "^7.4|^8.0",
"symfony/validator": "^7.4|^8.0",
"symfony/var-dumper": "^7.4|^8.0"
},
"type": "library",
@@ -1400,7 +1410,7 @@
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v8.0.11"
"source": "https://github.com/symfony/console/tree/v8.1.0"
},
"funding": [
{
@@ -1420,7 +1430,7 @@
"type": "tidelift"
}
],
"time": "2026-05-13T12:07:53+00:00"
"time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -1495,20 +1505,21 @@
},
{
"name": "symfony/event-dispatcher",
"version": "v8.0.9",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/event-dispatcher.git",
"reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f"
"reference": "f249ae3f680958b6f1f9dd76e5747cf0695b4102"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/0c3c1a17604c4dbbec4b93fe162c538482096e1f",
"reference": "0c3c1a17604c4dbbec4b93fe162c538482096e1f",
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/f249ae3f680958b6f1f9dd76e5747cf0695b4102",
"reference": "f249ae3f680958b6f1f9dd76e5747cf0695b4102",
"shasum": ""
},
"require": {
"php": ">=8.4",
"php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/event-dispatcher-contracts": "^2.5|^3"
},
"conflict": {
@@ -1556,7 +1567,7 @@
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/event-dispatcher/tree/v8.0.9"
"source": "https://github.com/symfony/event-dispatcher/tree/v8.1.0"
},
"funding": [
{
@@ -1576,7 +1587,7 @@
"type": "tidelift"
}
],
"time": "2026-04-18T13:51:42+00:00"
"time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/event-dispatcher-contracts",
@@ -1660,20 +1671,21 @@
},
{
"name": "symfony/filesystem",
"version": "v8.0.11",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
"reference": "224db910898ce1317b892a9a1338f1f8f17eb7c7"
"reference": "99aec13b82b4967ec5088222c4a3ecca955949c2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/224db910898ce1317b892a9a1338f1f8f17eb7c7",
"reference": "224db910898ce1317b892a9a1338f1f8f17eb7c7",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/99aec13b82b4967ec5088222c4a3ecca955949c2",
"reference": "99aec13b82b4967ec5088222c4a3ecca955949c2",
"shasum": ""
},
"require": {
"php": ">=8.4",
"php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
@@ -1706,7 +1718,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/filesystem/tree/v8.0.11"
"source": "https://github.com/symfony/filesystem/tree/v8.1.0"
},
"funding": [
{
@@ -1726,24 +1738,24 @@
"type": "tidelift"
}
],
"time": "2026-05-11T16:39:47+00:00"
"time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/finder",
"version": "v8.0.8",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "8da41214757b87d97f181e3d14a4179286151007"
"reference": "58d2e767a66052c1487356f953445634a8194c64"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/8da41214757b87d97f181e3d14a4179286151007",
"reference": "8da41214757b87d97f181e3d14a4179286151007",
"url": "https://api.github.com/repos/symfony/finder/zipball/58d2e767a66052c1487356f953445634a8194c64",
"reference": "58d2e767a66052c1487356f953445634a8194c64",
"shasum": ""
},
"require": {
"php": ">=8.4"
"php": ">=8.4.1"
},
"require-dev": {
"symfony/filesystem": "^7.4|^8.0"
@@ -1774,7 +1786,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v8.0.8"
"source": "https://github.com/symfony/finder/tree/v8.1.0"
},
"funding": [
{
@@ -1794,24 +1806,24 @@
"type": "tidelift"
}
],
"time": "2026-03-30T15:14:47+00:00"
"time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v8.0.8",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "b48bce0a70b914f6953dafbd10474df232ed4de8"
"reference": "88f9c561f678a02d54b897014049fa839e33ff82"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/b48bce0a70b914f6953dafbd10474df232ed4de8",
"reference": "b48bce0a70b914f6953dafbd10474df232ed4de8",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/88f9c561f678a02d54b897014049fa839e33ff82",
"reference": "88f9c561f678a02d54b897014049fa839e33ff82",
"shasum": ""
},
"require": {
"php": ">=8.4",
"php": ">=8.4.1",
"symfony/deprecation-contracts": "^2.5|^3"
},
"type": "library",
@@ -1845,7 +1857,7 @@
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v8.0.8"
"source": "https://github.com/symfony/options-resolver/tree/v8.1.0"
},
"funding": [
{
@@ -1865,7 +1877,7 @@
"type": "tidelift"
}
],
"time": "2026-03-30T15:14:47+00:00"
"time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -1952,16 +1964,16 @@
},
{
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.37.0",
"version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "4864388bfbd3001ce88e234fab652acd91fdc57e"
"reference": "e9247d281d694a5120554d9afaf54e070e88a603"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/4864388bfbd3001ce88e234fab652acd91fdc57e",
"reference": "4864388bfbd3001ce88e234fab652acd91fdc57e",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603",
"reference": "e9247d281d694a5120554d9afaf54e070e88a603",
"shasum": ""
},
"require": {
@@ -2010,7 +2022,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.37.0"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1"
},
"funding": [
{
@@ -2030,20 +2042,20 @@
"type": "tidelift"
}
],
"time": "2026-04-26T13:13:48+00:00"
"time": "2026-05-26T05:58:03+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
"version": "v1.37.0",
"version": "v1.38.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "3833d7255cc303546435cb650316bff708a1c75c"
"reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
"reference": "3833d7255cc303546435cb650316bff708a1c75c",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b",
"reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b",
"shasum": ""
},
"require": {
@@ -2095,7 +2107,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.37.0"
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0"
},
"funding": [
{
@@ -2115,20 +2127,20 @@
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
"time": "2026-05-25T13:48:31+00:00"
},
{
"name": "symfony/polyfill-mbstring",
"version": "v1.37.0",
"version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315"
"reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315",
"reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/14c5439eec4ccff081ac14eca2dc57feb2a66d92",
"reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92",
"shasum": ""
},
"require": {
@@ -2180,7 +2192,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.37.0"
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.1"
},
"funding": [
{
@@ -2200,7 +2212,7 @@
"type": "tidelift"
}
],
"time": "2026-04-10T17:25:58+00:00"
"time": "2026-05-26T12:51:13+00:00"
},
{
"name": "symfony/polyfill-php80",
@@ -2288,16 +2300,16 @@
},
{
"name": "symfony/polyfill-php81",
"version": "v1.37.0",
"version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
"reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/6bfb9c766cacffbc8e118cb87217d08ed84e5cd7",
"reference": "6bfb9c766cacffbc8e118cb87217d08ed84e5cd7",
"shasum": ""
},
"require": {
@@ -2344,7 +2356,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.37.0"
"source": "https://github.com/symfony/polyfill-php81/tree/v1.38.1"
},
"funding": [
{
@@ -2364,20 +2376,20 @@
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
"time": "2026-05-26T12:45:58+00:00"
},
{
"name": "symfony/polyfill-php84",
"version": "v1.37.0",
"version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php84.git",
"reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06"
"reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/88486db2c389b290bf87ff1de7ebc1e13e42bb06",
"reference": "88486db2c389b290bf87ff1de7ebc1e13e42bb06",
"url": "https://api.github.com/repos/symfony/polyfill-php84/zipball/f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
"reference": "f4e1dfaee5b74aba5964fe1fd4dfc7ba5e3085fa",
"shasum": ""
},
"require": {
@@ -2424,7 +2436,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php84/tree/v1.37.0"
"source": "https://github.com/symfony/polyfill-php84/tree/v1.38.1"
},
"funding": [
{
@@ -2444,24 +2456,104 @@
"type": "tidelift"
}
],
"time": "2026-04-10T18:47:49+00:00"
"time": "2026-05-26T12:51:13+00:00"
},
{
"name": "symfony/process",
"version": "v8.0.11",
"name": "symfony/polyfill-php85",
"version": "v1.38.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "26d89e459f037d2873300605d0a07e7a8ef84db0"
"url": "https://github.com/symfony/polyfill-php85.git",
"reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/26d89e459f037d2873300605d0a07e7a8ef84db0",
"reference": "26d89e459f037d2873300605d0a07e7a8ef84db0",
"url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1",
"reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1",
"shasum": ""
},
"require": {
"php": ">=8.4"
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"url": "https://github.com/symfony/polyfill",
"name": "symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php85\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.5+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php85/tree/v1.38.1"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://github.com/nicolas-grekas",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2026-05-26T02:25:22+00:00"
},
{
"name": "symfony/process",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/process.git",
"reference": "c4a9e58f235a6bf7f97ffbfedae2687353ac79e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/process/zipball/c4a9e58f235a6bf7f97ffbfedae2687353ac79e5",
"reference": "c4a9e58f235a6bf7f97ffbfedae2687353ac79e5",
"shasum": ""
},
"require": {
"php": ">=8.4.1"
},
"type": "library",
"autoload": {
@@ -2489,7 +2581,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/process/tree/v8.0.11"
"source": "https://github.com/symfony/process/tree/v8.1.0"
},
"funding": [
{
@@ -2509,7 +2601,7 @@
"type": "tidelift"
}
],
"time": "2026-05-11T16:56:32+00:00"
"time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/service-contracts",
@@ -2600,20 +2692,20 @@
},
{
"name": "symfony/stopwatch",
"version": "v8.0.8",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/stopwatch.git",
"reference": "85954ed72d5440ea4dc9a10b7e49e01df766ffa3"
"reference": "21c07b026905d596e8379caeb115d87aa479499d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/85954ed72d5440ea4dc9a10b7e49e01df766ffa3",
"reference": "85954ed72d5440ea4dc9a10b7e49e01df766ffa3",
"url": "https://api.github.com/repos/symfony/stopwatch/zipball/21c07b026905d596e8379caeb115d87aa479499d",
"reference": "21c07b026905d596e8379caeb115d87aa479499d",
"shasum": ""
},
"require": {
"php": ">=8.4",
"php": ">=8.4.1",
"symfony/service-contracts": "^2.5|^3"
},
"type": "library",
@@ -2642,7 +2734,7 @@
"description": "Provides a way to profile code",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/stopwatch/tree/v8.0.8"
"source": "https://github.com/symfony/stopwatch/tree/v8.1.0"
},
"funding": [
{
@@ -2662,24 +2754,24 @@
"type": "tidelift"
}
],
"time": "2026-03-30T15:14:47+00:00"
"time": "2026-05-29T05:06:50+00:00"
},
{
"name": "symfony/string",
"version": "v8.0.11",
"version": "v8.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "39be2ad058a3c0bd558edca23e65f009865d75ff"
"reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/39be2ad058a3c0bd558edca23e65f009865d75ff",
"reference": "39be2ad058a3c0bd558edca23e65f009865d75ff",
"url": "https://api.github.com/repos/symfony/string/zipball/afd5944f4005862d961efb85c8bbd5c523c4e3c9",
"reference": "afd5944f4005862d961efb85c8bbd5c523c4e3c9",
"shasum": ""
},
"require": {
"php": ">=8.4",
"php": ">=8.4.1",
"symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-intl-grapheme": "^1.33",
"symfony/polyfill-intl-normalizer": "^1.0",
@@ -2732,7 +2824,7 @@
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v8.0.11"
"source": "https://github.com/symfony/string/tree/v8.1.0"
},
"funding": [
{
@@ -2752,7 +2844,7 @@
"type": "tidelift"
}
],
"time": "2026-05-13T12:07:53+00:00"
"time": "2026-05-29T05:06:50+00:00"
}
],
"packages-dev": [],
@@ -158,7 +158,10 @@ final class TagController extends Controller
'currency_id' => (string) $foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
$response[$foreignKey]['difference'] = bcadd(
(string) $response[$foreignKey]['difference'],
Steam::positive($journal['foreign_amount'])
);
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference'];
}
}
@@ -155,7 +155,10 @@ final class TagController extends Controller
'currency_id' => (string) $foreignCurrencyId,
'currency_code' => $journal['foreign_currency_code'],
];
$response[$foreignKey]['difference'] = bcadd((string) $response[$foreignKey]['difference'], Steam::positive($journal['foreign_amount']));
$response[$foreignKey]['difference'] = bcadd(
(string) $response[$foreignKey]['difference'],
Steam::positive($journal['foreign_amount'])
);
$response[$foreignKey]['difference_float'] = (float) $response[$foreignKey]['difference']; // intentional float
}
}
@@ -83,7 +83,12 @@ final class ShowController extends Controller
* @throws FireflyException
* @throws NotFoundExceptionInterface
*/
public function show(Request $request, Account $account, ?Carbon $start = null, ?Carbon $end = null): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse {
public function show(
Request $request,
Account $account,
?Carbon $start = null,
?Carbon $end = null
): Factory|\Illuminate\Contracts\View\View|Redirector|RedirectResponse {
if (0 === $account->id) {
throw new NotFoundHttpException();
}
@@ -255,7 +255,10 @@ final class IndexController extends Controller
if (count($bill['paid_dates']) < count($bill['pay_dates'])) {
$count = count($bill['pay_dates']) - count($bill['paid_dates']);
if ($count > 0) {
$avg = bcdiv(bcadd((string) $bill['amount_min'], (string) $bill['amount_max']), '2');
$avg = bcdiv(
bcadd((string) $bill['amount_min'], (string) $bill['amount_max']),
'2'
);
$avg = bcmul($avg, (string) $count);
$sums[$groupOrder][$currencyId]['total_left_to_pay'] = bcadd($sums[$groupOrder][$currencyId]['total_left_to_pay'], $avg);
Log::debug(
@@ -198,7 +198,13 @@ final class BudgetLimitController extends Controller
if ($request->expectsJson()) {
$array = $limit->toArray();
// add some extra metadata:
$spentArr = $this->opsRepository->sumExpenses($limit->start_date, $limit->end_date, null, new Collection()->push($budget), $currency);
$spentArr = $this->opsRepository->sumExpenses(
$limit->start_date,
$limit->end_date,
null,
new Collection()->push($budget),
$currency
);
$array['spent'] = $spentArr[$currency->id]['sum'] ?? '0';
$array['left_formatted'] = Amount::formatAnything($limit->transactionCurrency, bcadd($array['spent'], (string) $array['amount']));
$array['amount_formatted'] = Amount::formatAnything($limit->transactionCurrency, $limit['amount']);
@@ -284,7 +284,10 @@ final class IndexController extends Controller
if (array_key_exists($currency->id, $spentArr) && array_key_exists('sum', $spentArr[$currency->id])) {
$array['spent'][$currency->id]['spent'] = $spentArr[$currency->id]['sum'];
$array['spent'][$currency->id]['spent_outside'] = Steam::negative(bcsub($spentInLimits[$currency->id], $spentArr[$currency->id]['sum']));
$array['spent'][$currency->id]['spent_outside'] = Steam::negative(bcsub(
$spentInLimits[$currency->id],
$spentArr[$currency->id]['sum']
));
$array['spent'][$currency->id]['currency_id'] = $currency->id;
$array['spent'][$currency->id]['currency_symbol'] = $currency->symbol;
$array['spent'][$currency->id]['currency_decimal_places'] = $currency->decimal_places;
@@ -539,7 +539,13 @@ final class BudgetController extends Controller
}
// get spent amount in this period for this currency.
$sum = $this->opsRepository->sumExpenses($currentStart, $currentEnd, $accounts, new Collection()->push($budget), $currency);
$sum = $this->opsRepository->sumExpenses(
$currentStart,
$currentEnd,
$accounts,
new Collection()->push($budget),
$currency
);
$amount = Steam::positive($sum[$currency->id]['sum'] ?? '0');
$chartData[0]['entries'][$title] = Steam::bcround($amount, $currency->decimal_places);
+14 -2
View File
@@ -122,7 +122,13 @@ class CreateAutoBudgetLimits implements ShouldQueue
// if has one, calculate expenses and use that as a base.
$repository = app(OperationsRepositoryInterface::class);
$repository->setUser($autoBudget->budget->user);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
$spent = $repository->sumExpenses(
$previousStart,
$previousEnd,
null,
new Collection()->push($autoBudget->budget),
$autoBudget->transactionCurrency
);
$currencyId = $autoBudget->transaction_currency_id;
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));
@@ -212,7 +218,13 @@ class CreateAutoBudgetLimits implements ShouldQueue
// if has one, calculate expenses and use that as a base.
$repository = app(OperationsRepositoryInterface::class);
$repository->setUser($autoBudget->budget->user);
$spent = $repository->sumExpenses($previousStart, $previousEnd, null, new Collection()->push($autoBudget->budget), $autoBudget->transactionCurrency);
$spent = $repository->sumExpenses(
$previousStart,
$previousEnd,
null,
new Collection()->push($autoBudget->budget),
$autoBudget->transactionCurrency
);
$currencyId = $autoBudget->transaction_currency_id;
$spentAmount = $spent[$currencyId]['sum'] ?? '0';
Log::debug(sprintf('Spent in previous budget period (%s-%s) is %s', $previousStart->format('Y-m-d'), $previousEnd->format('Y-m-d'), $spentAmount));
+22 -21
View File
@@ -41,6 +41,7 @@ use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Safe\Exceptions\JsonException;
use function Safe\json_decode;
/**
@@ -53,10 +54,10 @@ class DownloadExchangeRates implements ShouldQueue
use Queueable;
use SerializesModels;
private array $active = [];
private Carbon $date;
private array $active = [];
private Carbon $date;
private CurrencyRepositoryInterface $repository;
private Collection $users;
private Collection $users;
/**
* Create a new job instance.
@@ -67,11 +68,11 @@ class DownloadExchangeRates implements ShouldQueue
// get all users:
/** @var UserRepositoryInterface $userRepository */
$userRepository = app(UserRepositoryInterface::class);
$this->users = $userRepository->all();
$userRepository = app(UserRepositoryInterface::class);
$this->users = $userRepository->all();
if ($date instanceof Carbon) {
$newDate = clone $date;
$newDate = clone $date;
$newDate->startOfDay();
$this->date = $newDate;
Log::debug(sprintf('Created new DownloadExchangeRates("%s")', $this->date->format('Y-m-d')));
@@ -94,7 +95,7 @@ class DownloadExchangeRates implements ShouldQueue
public function setDate(Carbon $date): void
{
$newDate = clone $date;
$newDate = clone $date;
$newDate->startOfDay();
$this->date = $newDate;
}
@@ -106,13 +107,13 @@ class DownloadExchangeRates implements ShouldQueue
private function downloadRates(TransactionCurrency $currency): void
{
Log::debug(sprintf('Now downloading new exchange rates for currency %s.', $currency->code));
$base = sprintf('%s/%s/%s', (string)config('cer.url'), $this->date->year, $this->date->isoWeek);
$client = new Client();
$url = sprintf('%s/%s.json', $base, $currency->code);
$base = sprintf('%s/%s/%s', (string) config('cer.url'), $this->date->year, $this->date->isoWeek);
$client = new Client();
$url = sprintf('%s/%s.json', $base, $currency->code);
try {
$res = $client->get($url);
} catch (ConnectException | RequestException $e) {
} catch (ConnectException|RequestException $e) {
Log::warning(sprintf('Trying to grab "%s" resulted in error "%s".', $url, $e->getMessage()));
return;
@@ -123,14 +124,14 @@ class DownloadExchangeRates implements ShouldQueue
return;
}
$body = (string)$res->getBody();
$json = json_decode($body, true);
$body = (string) $res->getBody();
$json = json_decode($body, true);
if (false === $json || null === $json) {
Log::warning(sprintf('Trying to grab "%s" resulted in bad JSON.', $url));
return;
}
$date = Carbon::createFromFormat('Y-m-d', $json['date'], config('app.timezone'));
$date = Carbon::createFromFormat('Y-m-d', $json['date'], config('app.timezone'));
if (!$date instanceof Carbon) {
return;
}
@@ -146,19 +147,19 @@ class DownloadExchangeRates implements ShouldQueue
return $this->active[$code];
}
// find it in the database.
$currency = $this->repository->findByCode($code);
$currency = $this->repository->findByCode($code);
if (!$currency instanceof TransactionCurrency) {
Log::debug(sprintf('Did not find currency %s.', $code));
$this->active[$code] = null;
return null;
}
// if (false === $currency->enabled) {
// Log::debug(sprintf('Currency %s is not enabled.', $code));
// $this->active[$code] = null;
//
// return null;
// }
// if (false === $currency->enabled) {
// Log::debug(sprintf('Currency %s is not enabled.', $code));
// $this->active[$code] = null;
//
// return null;
// }
Log::debug(sprintf('Currency %s is enabled.', $code));
$this->active[$code] = $currency;
@@ -251,10 +251,10 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
Log::debug(sprintf('Final result: %s', $result->code));
// code below is no longer relevant.
// if (false === $result->enabled) {
// Log::debug(sprintf('Also enabled currency %s', $result->code));
// $this->enable($result);
// }
// if (false === $result->enabled) {
// Log::debug(sprintf('Also enabled currency %s', $result->code));
// $this->enable($result);
// }
return $result;
}
@@ -275,14 +275,13 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
}
if (null !== $currencyCode && '' !== $currencyCode) {
Log::debug(sprintf('Searching for currency with code "%s"...', $currencyCode));
$result = $this->findByCode($currencyCode);
// if ($result instanceof TransactionCurrency && false === $result->enabled) {
// Log::debug(sprintf('Also enabled currency %s', $result->code));
// $this->enable($result);
// }
return $this->findByCode($currencyCode);
return $result;
// if ($result instanceof TransactionCurrency && false === $result->enabled) {
// Log::debug(sprintf('Also enabled currency %s', $result->code));
// $this->enable($result);
// }
}
Log::debug('Found no currency, returning NULL.');
@@ -362,6 +361,21 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
return null;
}
#[Override]
public function isEnabled(TransactionCurrency $currency): bool
{
if (null === $this->user && null === $this->userGroup) {
throw new FireflyException(sprintf('Cannot check enabled status for currency "%s" in stateless currency repository', $currency->code));
}
$userGroup = $this->userGroup;
if (null === $this->userGroup) {
$userGroup = $this->user->userGroup;
}
$currency = $userGroup->currencies()->find($currency->id);
return null !== $currency;
}
public function isFallbackCurrency(TransactionCurrency $currency): bool
{
return $currency->code === config('firefly.default_currency', 'EUR');
@@ -471,18 +485,4 @@ class CurrencyRepository implements CurrencyRepositoryInterface, UserGroupInterf
// also count foreign:
return $count + Transaction::query()->where('foreign_currency_id', $currency->id)->count();
}
#[\Override]
public function isEnabled(TransactionCurrency $currency): bool
{
if(null === $this->user && null === $this->userGroup){
throw new FireflyException(sprintf('Cannot check enabled status for currency "%s" in stateless currency repository', $currency->code));
}
$userGroup = $this->userGroup;
if(null === $this->userGroup) {
$userGroup = $this->user->userGroup;
}
$currency = $userGroup->currencies()->find($currency->id);
return null !== $currency;
}
}
@@ -93,8 +93,6 @@ interface CurrencyRepositoryInterface
*/
public function getCompleteSet(): Collection;
public function isEnabled(TransactionCurrency $currency): bool;
/**
* Get currency exchange rate.
*
@@ -102,6 +100,8 @@ interface CurrencyRepositoryInterface
*/
public function getExchangeRate(TransactionCurrency $fromCurrency, TransactionCurrency $toCurrency, Carbon $date): ?CurrencyExchangeRate;
public function isEnabled(TransactionCurrency $currency): bool;
public function isFallbackCurrency(TransactionCurrency $currency): bool;
public function makePrimary(TransactionCurrency $currency): void;
@@ -222,7 +222,14 @@ trait AugumentData
$currentEnd->addMonth();
}
// primary currency amount.
$expenses = $opsRepository->sumExpenses($currentStart, $currentEnd, null, $budgetCollection, $entry->transactionCurrency, $this->convertToPrimary);
$expenses = $opsRepository->sumExpenses(
$currentStart,
$currentEnd,
null,
$budgetCollection,
$entry->transactionCurrency,
$this->convertToPrimary
);
$spent = $expenses[$currency->id]['sum'] ?? '0';
$entry->pc_spent = $spent;
@@ -354,7 +354,10 @@ class RecurringEnrichment implements EnrichmentInterface
/** @var RecurrenceRepetition $repetition */
foreach ($set as $repetition) {
$recurrence = $this->collection->filter(static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id)->first();
$recurrence = $this->collection
->filter(static fn (Recurrence $item): bool => (int) $item->id === (int) $repetition->recurrence_id)
->first()
;
$fromDate = clone ($recurrence->latest_date ?? $recurrence->first_date);
$recurrenceId = (int) $repetition->recurrence_id;
$repId = (int) $repetition->id;
Generated
+381 -262
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -78,8 +78,8 @@ return [
'running_balance_column' => (bool)env_default_when_empty(env('USE_RUNNING_BALANCE'), true), // this is only the default value, is not used.
// see cer.php for exchange rates feature flag.
],
'version' => 'develop/2026-05-25',
'build_time' => 1779690884,
'version' => 'develop/2026-06-01',
'build_time' => 1780342304,
'api_version' => '2.1.0', // field is no longer used.
'db_version' => 28, // field is no longer used.
-48
View File
@@ -2053,9 +2053,6 @@
"arm"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2077,9 +2074,6 @@
"arm"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2101,9 +2095,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2125,9 +2116,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2149,9 +2137,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2173,9 +2158,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2369,9 +2351,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2389,9 +2368,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2409,9 +2385,6 @@
"ppc64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2429,9 +2402,6 @@
"s390x"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2449,9 +2419,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MIT",
"optional": true,
"os": [
@@ -2469,9 +2436,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MIT",
"optional": true,
"os": [
@@ -7620,9 +7584,6 @@
"arm64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7644,9 +7605,6 @@
"arm64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7668,9 +7626,6 @@
"x64"
],
"dev": true,
"libc": [
"glibc"
],
"license": "MPL-2.0",
"optional": true,
"os": [
@@ -7692,9 +7647,6 @@
"x64"
],
"dev": true,
"libc": [
"musl"
],
"license": "MPL-2.0",
"optional": true,
"os": [
Executable → Regular
View File
-4
View File
@@ -99,10 +99,6 @@
"/public/v1/js/ff/transactions/mass/edit-bulk.js": "/public/v1/js/ff/transactions/mass/edit-bulk.js",
"/public/v1/js/ff/transactions/mass/edit.js": "/public/v1/js/ff/transactions/mass/edit.js",
"/public/v1/js/ff/transactions/show.js": "/public/v1/js/ff/transactions/show.js",
"/public/v1/js/js/layout.js": "/public/v1/js/js/layout.js",
"/public/v1/js/js/layout.js.LICENSE.txt": "/public/v1/js/js/layout.js.LICENSE.txt",
"/public/v1/js/layout.js": "/public/v1/js/layout.js",
"/public/v1/js/layout.js.LICENSE.txt": "/public/v1/js/layout.js.LICENSE.txt",
"/public/v1/js/lib/Chart.bundle.min.js": "/public/v1/js/lib/Chart.bundle.min.js",
"/public/v1/js/lib/accounting.min.js": "/public/v1/js/lib/accounting.min.js",
"/public/v1/js/lib/bootstrap-multiselect.js": "/public/v1/js/lib/bootstrap-multiselect.js",
+1 -1
View File
@@ -1416,7 +1416,7 @@ return [
'pref_two_factor_auth_code_help' => 'Scan the QR code with an application on your phone such as Authy or Google Authenticator and enter the generated code. The QR code changes every time you visit this page. Make sure you use the most recent one.',
'pref_two_factor_auth_reset_code' => 'Reset verification code',
'pref_two_factor_auth_disable_2fa' => 'Disable MFA',
'pref_two_factor_qr_code' => 'QR code',
'pref_two_factor_qr_code' => 'QR code',
'2fa_use_secret_instead' => 'If you cannot scan the QR code, feel free to use the secret instead: <code>:secret</code>.',
'2fa_backup_codes' => 'Store these backup codes for access in case you lose your device.',
'2fa_already_enabled' => 'Multi-factor authentication verification is already enabled.',