Compare commits

..

71 Commits

Author SHA1 Message Date
github-actions
2a3ba9799e Auto commit for release 'develop' on 2024-04-08 2024-04-08 05:09:59 +02:00
James Cole
d121aad28f Check the directory, not the file. 2024-04-07 16:27:15 +02:00
github-actions
dc808fa807 Auto commit for release 'develop' on 2024-04-07 2024-04-07 16:22:39 +02:00
James Cole
a1be6ff62b Limit the number of error messages Firefly III will send. 2024-04-07 16:12:41 +02:00
James Cole
20dc5b0256 Fix layout errors. 2024-04-07 15:57:51 +02:00
James Cole
edd54e23c5 Merge branch 'main' into develop 2024-04-07 10:40:03 +02:00
James Cole
1238df8784 Switch to v38 2024-04-07 10:38:17 +02:00
github-actions
b8c62652b0 Auto commit for release 'develop' on 2024-04-07 2024-04-07 10:37:19 +02:00
James Cole
54b2d02f63 Build JS in one go. 2024-04-07 10:31:24 +02:00
James Cole
47faf89a5c Update script to apply patch. 2024-04-07 10:29:54 +02:00
James Cole
b7fb5a3854 This configuration works but patch-package doesn't take (yt) 2024-04-07 10:12:23 +02:00
James Cole
a384b4202a Add gitkeep file 2024-04-07 07:26:31 +02:00
James Cole
99ecac0ce4 Clean up some scripts. 2024-04-07 07:25:54 +02:00
James Cole
6102982456 Move more JS files 2024-04-07 07:21:08 +02:00
James Cole
b88e981b4b Move v2 files 2024-04-07 07:17:34 +02:00
James Cole
827263b03e Move v1 assets 2024-04-07 07:16:38 +02:00
James Cole
d44e74d334 Merge branch 'main' into develop 2024-04-07 06:52:49 +02:00
github-actions
911f46c590 Auto commit for release 'develop' on 2024-04-07 2024-04-07 06:51:34 +02:00
James Cole
7d42c4ee5d Move to v37 2024-04-07 06:45:48 +02:00
James Cole
ea89f6177f Move selected translations to Firefly III 2024-04-07 06:44:45 +02:00
James Cole
74291b3870 Expand API administration validation 2024-04-07 06:06:40 +02:00
James Cole
2c4f2082fe Update workflows. 2024-04-06 06:26:21 +02:00
github-actions
d8d58cc29b Auto commit for release 'develop' on 2024-04-04 2024-04-04 05:11:18 +02:00
James Cole
85b17e4035 Drop the type for now, fixes https://github.com/orgs/firefly-iii/discussions/8750 2024-04-03 20:07:18 +02:00
James Cole
83de5667b3 Fix icons en styling 2024-04-03 08:59:44 +02:00
James Cole
5fffe873c6 Update PR template 2024-04-03 05:55:39 +02:00
James Cole
78c09c82d6 Merge branch 'main' into develop 2024-04-03 05:48:55 +02:00
James Cole
704abc315d New template 2024-04-03 05:48:38 +02:00
github-actions
86b4965458 Auto commit for release 'develop' on 2024-04-03 2024-04-03 05:19:06 +02:00
James Cole
d2dc0c2bf0 Merge branch 'main' into develop 2024-04-03 05:12:51 +02:00
James Cole
9f4894bbb5 Fix https://github.com/firefly-iii/firefly-iii/issues/8748 2024-04-03 05:12:28 +02:00
James Cole
76a8675a34 make sure boxes are empty 2024-04-02 18:04:42 +02:00
James Cole
6988301da1 Merge pull request #8746 from imlonghao/patch-1
Set date to now when cloning journal
2024-04-02 18:03:52 +02:00
imlonghao
109cd37211 Set date to now when cloning journal
Signed-off-by: imlonghao <git@imlonghao.com>
2024-04-02 23:44:45 +08:00
James Cole
284ff4d1b0 Merge branch 'main' into develop 2024-04-02 16:53:31 +02:00
James Cole
bc0ab7af99 Spelling error in nightly release instructions 2024-04-02 16:53:18 +02:00
James Cole
a17bc7258f Fix phpstan error courtesy of the laravel 11 upgrade (changed signatures and return types) 2024-04-02 15:40:33 +02:00
James Cole
87911c2438 Catch empty preference, just in case. 2024-04-02 12:38:31 +02:00
github-actions
746f1fd300 Auto commit for release 'develop' on 2024-04-02 2024-04-02 07:47:24 +02:00
James Cole
9e5faf919f Add space 2024-04-02 07:40:40 +02:00
James Cole
cc6cbe6605 Add something to changelog before I forget. 2024-04-02 07:01:13 +02:00
James Cole
dc6d708897 Replace frontpageAccounts variable name. 2024-04-02 06:59:40 +02:00
James Cole
6189d24b98 Replace variable names. 2024-04-01 20:26:02 +02:00
James Cole
f6e28dc88f Fine tune preferences to handle multi-administration options. 2024-04-01 19:59:21 +02:00
James Cole
75ea035630 Preferences can be administration specific. Not yet really working. 2024-04-01 18:18:48 +02:00
James Cole
4cdb14301d Add administration specific thing to preferences. 2024-04-01 18:03:43 +02:00
James Cole
9f95221ba3 Various code cleanup. 2024-04-01 17:43:31 +02:00
James Cole
e3a67be412 Clear user groups when loading 2024-04-01 16:07:14 +02:00
James Cole
5749b642ce Wrong response code. 2024-04-01 16:07:03 +02:00
James Cole
baff7c67f9 Expand user group views and translations 2024-04-01 15:41:16 +02:00
James Cole
ccc005942f Expand user group pages. 2024-04-01 15:40:53 +02:00
James Cole
5b83c33039 Turns out it's pointless to add "default_administration", you can force that already through the owner role (which is already in place). 2024-04-01 14:15:35 +02:00
James Cole
cc32578c5f Add new strings. 2024-04-01 14:04:36 +02:00
James Cole
80f410835b Expand models, user groups need more properties. 2024-04-01 14:04:22 +02:00
James Cole
b537a3145d Expand financial administrations views. 2024-04-01 14:01:52 +02:00
James Cole
bfa1fcbaf8 make sure output.txt is writeable. 2024-04-01 09:08:19 +02:00
James Cole
56243907c4 Add some debug info 2024-04-01 09:01:53 +02:00
James Cole
5928dd72e6 Forgot the zip name 2024-04-01 08:53:56 +02:00
github-actions
c6bf0ff1cd Auto commit for release 'v6.1.13' on 2024-04-01 2024-04-01 08:51:46 +02:00
James Cole
19d1cf192b Fix tests, update changelog. 2024-04-01 08:46:13 +02:00
James Cole
37d7dc7e3e Merge branch 'main' into develop 2024-04-01 08:37:57 +02:00
James Cole
95a3a194b8 Better instructions 2024-04-01 08:37:49 +02:00
James Cole
3542387188 Merge branch 'main' into develop 2024-04-01 08:36:25 +02:00
James Cole
da1b002a64 Clean up and expand normal release 2024-04-01 08:36:15 +02:00
James Cole
46daee28e7 Merge branch 'main' into develop 2024-04-01 08:33:02 +02:00
James Cole
9ade5635d4 Add file with revision of the used branch. 2024-04-01 08:32:51 +02:00
James Cole
e14e80f33c Merge branch 'main' into develop 2024-04-01 08:31:32 +02:00
github-actions
0c824e21c8 Auto commit for release 'develop' on 2024-04-01 2024-04-01 05:10:33 +02:00
James Cole
fab1c68569 Merge branch 'develop' of github.com:firefly-iii/firefly-iii into develop 2024-03-31 19:32:00 +02:00
James Cole
c1534657f2 Fix the installation template. 2024-03-31 19:31:52 +02:00
James Cole
43a720b62b It helps when you actually add 1 2024-03-31 17:06:37 +02:00
451 changed files with 13094 additions and 1082 deletions

View File

@@ -1,5 +1,5 @@
{ {
"require": { "require": {
"friendsofphp/php-cs-fixer": "^3.12" "friendsofphp/php-cs-fixer": "^3.12"
} }
} }

View File

@@ -538,16 +538,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v7.0.4", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f" "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f", "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5",
"reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f", "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -611,7 +611,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v7.0.4" "source": "https://github.com/symfony/console/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -627,7 +627,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-22T20:27:20+00:00" "time": "2024-04-01T11:04:53+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@@ -778,16 +778,16 @@
}, },
{ {
"name": "symfony/event-dispatcher-contracts", "name": "symfony/event-dispatcher-contracts",
"version": "v3.4.0", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git", "url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "a76aed96a42d2b521153fb382d418e30d18b59df" "reference": "4e64b49bf370ade88e567de29465762e316e4224"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/4e64b49bf370ade88e567de29465762e316e4224",
"reference": "a76aed96a42d2b521153fb382d418e30d18b59df", "reference": "4e64b49bf370ade88e567de29465762e316e4224",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -834,7 +834,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@@ -850,20 +850,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-05-23T14:45:45+00:00" "time": "2024-01-23T14:51:35+00:00"
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v7.0.3", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12" "reference": "408105dff4c104454100730bdfd1a9cdd993f04d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/2890e3a825bc0c0558526c04499c13f83e1b6b12", "url": "https://api.github.com/repos/symfony/filesystem/zipball/408105dff4c104454100730bdfd1a9cdd993f04d",
"reference": "2890e3a825bc0c0558526c04499c13f83e1b6b12", "reference": "408105dff4c104454100730bdfd1a9cdd993f04d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -897,7 +897,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v7.0.3" "source": "https://github.com/symfony/filesystem/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -913,7 +913,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-23T15:02:46+00:00" "time": "2024-03-21T19:37:36+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
@@ -1583,16 +1583,16 @@
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
"version": "v3.4.1", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/service-contracts.git", "url": "https://github.com/symfony/service-contracts.git",
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" "reference": "11bbf19a0fb7b36345861e85c5768844c552906e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e",
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "reference": "11bbf19a0fb7b36345861e85c5768844c552906e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1645,7 +1645,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.4.1" "source": "https://github.com/symfony/service-contracts/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@@ -1661,7 +1661,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-12-26T14:02:43+00:00" "time": "2023-12-19T21:51:00+00:00"
}, },
{ {
"name": "symfony/stopwatch", "name": "symfony/stopwatch",

View File

@@ -9,16 +9,16 @@
"packages-dev": [ "packages-dev": [
{ {
"name": "composer/pcre", "name": "composer/pcre",
"version": "3.1.2", "version": "3.1.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/pcre.git", "url": "https://github.com/composer/pcre.git",
"reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace" "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/pcre/zipball/4775f35b2d70865807c89d32c8e7385b86eb0ace", "url": "https://api.github.com/repos/composer/pcre/zipball/5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"reference": "4775f35b2d70865807c89d32c8e7385b86eb0ace", "reference": "5b16e25a5355f1f3afdfc2f954a0a80aec4826a8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -60,7 +60,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/composer/pcre/issues", "issues": "https://github.com/composer/pcre/issues",
"source": "https://github.com/composer/pcre/tree/3.1.2" "source": "https://github.com/composer/pcre/tree/3.1.3"
}, },
"funding": [ "funding": [
{ {
@@ -76,20 +76,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-03-07T15:38:35+00:00" "time": "2024-03-19T10:26:25+00:00"
}, },
{ {
"name": "composer/xdebug-handler", "name": "composer/xdebug-handler",
"version": "3.0.3", "version": "3.0.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/composer/xdebug-handler.git", "url": "https://github.com/composer/xdebug-handler.git",
"reference": "ced299686f41dce890debac69273b47ffe98a40c" "reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/composer/xdebug-handler/zipball/ced299686f41dce890debac69273b47ffe98a40c", "url": "https://api.github.com/repos/composer/xdebug-handler/zipball/4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
"reference": "ced299686f41dce890debac69273b47ffe98a40c", "reference": "4f988f8fdf580d53bdb2d1278fe93d1ed5462255",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -100,7 +100,7 @@
"require-dev": { "require-dev": {
"phpstan/phpstan": "^1.0", "phpstan/phpstan": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1", "phpstan/phpstan-strict-rules": "^1.1",
"symfony/phpunit-bridge": "^6.0" "phpunit/phpunit": "^8.5 || ^9.6 || ^10.5"
}, },
"type": "library", "type": "library",
"autoload": { "autoload": {
@@ -124,9 +124,9 @@
"performance" "performance"
], ],
"support": { "support": {
"irc": "irc://irc.freenode.org/composer", "irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/xdebug-handler/issues", "issues": "https://github.com/composer/xdebug-handler/issues",
"source": "https://github.com/composer/xdebug-handler/tree/3.0.3" "source": "https://github.com/composer/xdebug-handler/tree/3.0.4"
}, },
"funding": [ "funding": [
{ {
@@ -142,7 +142,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-02-25T21:32:43+00:00" "time": "2024-03-26T18:29:49+00:00"
}, },
{ {
"name": "pdepend/pdepend", "name": "pdepend/pdepend",

View File

@@ -19,9 +19,9 @@
~ along with this program. If not, see <https://www.gnu.org/licenses/>. ~ along with this program. If not, see <https://www.gnu.org/licenses/>.
--> -->
<ruleset name="pcsg-generated-ruleset" <ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="pcsg-generated-ruleset"
xmlns="http://pmd.sf.net/ruleset/1.0.0" xmlns="http://pmd.sf.net/ruleset/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd" xsi:schemaLocation="http://pmd.sf.net/ruleset/1.0.0 http://pmd.sf.net/ruleset_xml_schema.xsd"
xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd"> xsi:noNamespaceSchemaLocation="http://pmd.sf.net/ruleset_xml_schema.xsd">
<description>Firefly III ruleset.</description> <description>Firefly III ruleset.</description>

View File

@@ -1,13 +1,19 @@
<!-- <!--
Before you create a new PR, please consider: Thank you for submitting new code to Firefly III, or any of the related projects. Please read the following rules carefully.
1) Pull requests for the MAIN branch will be closed. - Do not submit solutions for problems that are not already reported in an issue
2) DO NOT include translations in your PR. Only English US sentences. - Firefly III can't be your learning experience. If you're new to all of this, please go be new somewhere else
- Do not open PRs to "discuss" possible solutions or to "get feedback" on your code. I don't have time for that.
- Pull requests for the MAIN branch will be closed.
- DO NOT include translated strings in your PR.
Perhaps open an issue first, before you open a PR?
See also: https://docs.firefly-iii.org/explanation/support/#contributing-code
Thanks.
--> -->
Fixes issue # (if relevant) This PR fixes issue # (if relevant).
Changes in this pull request: Changes in this pull request:

58
.github/stale.yml vendored
View File

@@ -1,58 +0,0 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an Issue or Pull Request becomes stale
daysUntilStale: 14
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 14
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
# - "[Status] Maybe Later"
exemptLabels:
- enhancement
- feature
- bug
- announcement
- "layout-v3"
# Set to true to ignore issues in a project (defaults to false)
exemptProjects: false
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: false
# Label to use when marking as stale
staleLabel: stale
# Comment to post when marking as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions.
# Comment to post when removing the stale label.
# unmarkComment: >
# Your comment here.
# Comment to post when closing a stale Issue or Pull Request.
# closeComment: >
# Your comment here.
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30
# Limit to only `issues` or `pulls`
# only: issues
# Optionally, specify configuration settings that are specific to just 'issues' or 'pulls':
# pulls:
# daysUntilStale: 30
# markComment: >
# This pull request has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# issues:
# exemptLabels:
# - confirmed

View File

@@ -3,7 +3,7 @@ name: "Issues - Command to close duplicate issues"
# the workflow to execute on is comments that are newly created # the workflow to execute on is comments that are newly created
on: on:
issue_comment: issue_comment:
types: [created] types: [ created ]
permissions: permissions:
issues: write issues: write

View File

@@ -3,9 +3,9 @@ name: 'Issues - Respond to hidden commands'
# the workflow to execute on is comments that are newly created # the workflow to execute on is comments that are newly created
on: on:
issues: issues:
types: [opened, edited] types: [ opened, edited ]
issue_comment: issue_comment:
types: [created] types: [ created ]
# permissions needed for reacting to IssueOps commands on issues and PRs # permissions needed for reacting to IssueOps commands on issues and PRs
permissions: permissions:

View File

@@ -2,11 +2,11 @@ name: 'Issues - Reply to specific labels'
on: on:
issues: issues:
types: [labeled, unlabeled] types: [ labeled, unlabeled ]
pull_request_target: pull_request_target:
types: [labeled, unlabeled] types: [ labeled, unlabeled ]
discussion: discussion:
types: [labeled, unlabeled] types: [ labeled, unlabeled ]
permissions: permissions:
contents: read contents: read

View File

@@ -4,11 +4,11 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
version: version:
description: 'Version to release' description: 'Release "v1.2.3" or "develop"'
required: true required: true
default: 'develop' default: 'develop'
schedule: schedule:
- cron: '0 3 * * MON,THU' - cron: '0 3 * * MON,THU'
jobs: jobs:
build: build:
@@ -51,7 +51,7 @@ jobs:
CROWDIN_TOKEN: ${{ secrets.CROWDIN_TOKEN }} CROWDIN_TOKEN: ${{ secrets.CROWDIN_TOKEN }}
- name: Cleanup translations - name: Cleanup translations
id: cleanup-transactions id: cleanup-transactions
uses: JC5/firefly-iii-dev@v36 uses: JC5/firefly-iii-dev@v38
with: with:
action: 'ff3:crowdin-warning' action: 'ff3:crowdin-warning'
output: '' output: ''
@@ -60,7 +60,7 @@ jobs:
GH_TOKEN: '' GH_TOKEN: ''
- name: Cleanup changelog - name: Cleanup changelog
id: cleanup-changelog id: cleanup-changelog
uses: JC5/firefly-iii-dev@v36 uses: JC5/firefly-iii-dev@v38
with: with:
action: 'ff3:changelog' action: 'ff3:changelog'
output: '' output: ''
@@ -69,7 +69,7 @@ jobs:
GH_TOKEN: ${{ secrets.CHANGELOG_TOKEN }} GH_TOKEN: ${{ secrets.CHANGELOG_TOKEN }}
- name: Extract changelog - name: Extract changelog
id: extract-changelog id: extract-changelog
uses: JC5/firefly-iii-dev@v36 uses: JC5/firefly-iii-dev@v38
with: with:
action: 'ff3:extract-changelog' action: 'ff3:extract-changelog'
output: 'output' output: 'output'
@@ -78,7 +78,7 @@ jobs:
GH_TOKEN: "" GH_TOKEN: ""
- name: Replace version - name: Replace version
id: replace-version id: replace-version
uses: JC5/firefly-iii-dev@v36 uses: JC5/firefly-iii-dev@v38
with: with:
action: 'ff3:version' action: 'ff3:version'
output: '' output: ''
@@ -88,7 +88,7 @@ jobs:
FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }} FF_III_VERSION: ${{ github.event_name == 'schedule' && 'develop' || github.event.inputs.version }}
- name: Generate JSON v1 - name: Generate JSON v1
id: json-v1 id: json-v1
uses: JC5/firefly-iii-dev@v36 uses: JC5/firefly-iii-dev@v38
with: with:
action: 'ff3:json-translations v1' action: 'ff3:json-translations v1'
output: '' output: ''
@@ -97,7 +97,7 @@ jobs:
GH_TOKEN: '' GH_TOKEN: ''
- name: Generate JSON v2 - name: Generate JSON v2
id: json-v2 id: json-v2
uses: JC5/firefly-iii-dev@v36 uses: JC5/firefly-iii-dev@v38
with: with:
action: 'ff3:json-translations v2' action: 'ff3:json-translations v2'
output: '' output: ''
@@ -106,27 +106,19 @@ jobs:
GH_TOKEN: '' GH_TOKEN: ''
- name: Code cleanup - name: Code cleanup
id: code-cleanup id: code-cleanup
uses: JC5/firefly-iii-dev@v36 uses: JC5/firefly-iii-dev@v38
with: with:
action: 'ff3:code' action: 'ff3:code'
output: '' output: ''
env: env:
FIREFLY_III_ROOT: /github/workspace FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: '' GH_TOKEN: ''
- name: Build new JS - name: Build JS
run: | run: |
npm install npm install
npm update npm update
npm run build npm run prod --workspace=v1
- name: Build old JS npm run build --workspace=v2
id: old-js
uses: JC5/firefly-iii-dev@v36
with:
action: 'ff3:old-js'
output: ''
env:
FIREFLY_III_ROOT: /github/workspace
GH_TOKEN: ''
- name: Run CI - name: Run CI
run: | run: |
rm -rf vendor composer.lock rm -rf vendor composer.lock
@@ -136,20 +128,24 @@ jobs:
.ci/phpcs.sh .ci/phpcs.sh
- name: Release - name: Release
run: | run: |
# do some configuration
sudo timedatectl set-timezone Europe/Amsterdam sudo timedatectl set-timezone Europe/Amsterdam
git config user.name github-actions git config user.name github-actions
git config user.email 41898282+github-actions[bot]@users.noreply.github.com git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git config advice.addIgnoredFile false git config advice.addIgnoredFile false
# set some variables
releaseName=$version
originalName=$version
zipName=FireflyIII-$version.zip
tarName=FireflyIII-$version.tar.gz
# update composer (again) # update composer (again)
composer validate --strict composer validate --strict
composer update --no-dev --no-scripts --no-plugins composer update --no-dev --no-scripts --no-plugins
composer dump-autoload composer dump-autoload
releaseName=$version # if this is a develop build, slightly different variable names.
originalName=$version
tarName=FireflyIII-$version.tar.gz
if [[ "develop" == "$version" ]]; then if [[ "develop" == "$version" ]]; then
[[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0; [[ -z $(git status --untracked-files=normal --porcelain) ]] && echo "this branch is clean, no need to push..." && exit 0;
releaseName=$version-$(date +'%Y%m%d') releaseName=$version-$(date +'%Y%m%d')
@@ -167,6 +163,7 @@ jobs:
echo "Tag $releaseName exists already." echo "Tag $releaseName exists already."
releaseName="$originalName"."$tagCount" releaseName="$originalName"."$tagCount"
echo "Tag for release is now $releaseName" echo "Tag for release is now $releaseName"
tagCount=$((tagCount+1))
else else
echo "Tag $releaseName does not exist, can continue" echo "Tag $releaseName does not exist, can continue"
tagFound=false tagFound=false
@@ -174,6 +171,8 @@ jobs:
done done
echo "Will use tag and release name $releaseName." echo "Will use tag and release name $releaseName."
# add all content, except output.txt (this contains the changelog and/or the download instructions)
echo 'Add all and reset output.txt'
git add -A git add -A
if test -f "output.txt"; then if test -f "output.txt"; then
git reset output.txt git reset output.txt
@@ -182,15 +181,19 @@ jobs:
git push git push
# zip and tar everything # zip and tar everything
echo 'Zip and tar...'
zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*" zip -rq $zipName . -x "*.git*" "*.ci*" "*.github*" "*node_modules*" "*output.txt*"
touch $tarName touch $tarName
tar --exclude=$tarName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' -czf $tarName . tar --exclude=$tarName --exclude=$zipName --exclude='./.git' --exclude='./.ci' --exclude='./.github' --exclude='./node_modules' --exclude='./output.txt' -czf $tarName .
# add sha256 sum # add sha256 sum
echo 'Sha sum ...'
sha256sum -b $zipName > $zipName.sha256 sha256sum -b $zipName > $zipName.sha256
sha256sum -b $tarName > $tarName.sha256 sha256sum -b $tarName > $tarName.sha256
# create a development (nightly) release:
if [[ "develop" == "$version" ]]; then if [[ "develop" == "$version" ]]; then
echo 'Develop release.'
# add text to output.txt (instructions) # add text to output.txt (instructions)
rm output.txt rm output.txt
echo "Bi-weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt echo "Bi-weekly development release of Firefly III with the latest fixes, translations and features. Docker users can find this release under the \`develop\` tag." >> output.txt
@@ -200,7 +203,7 @@ jobs:
echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt echo "* Please read the installation instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/installation/docker/), [Portainer](https://docs.firefly-iii.org/how-to/firefly-iii/installation/portainer/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/installation/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/installation/self-managed/)" >> output.txt
echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt echo "* Or read the upgrade instructions for [Docker](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/docker/), [Kubernetes](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/kubernetes/) or [self-managed servers](https://docs.firefly-iii.org/how-to/firefly-iii/upgrade/self-managed/)" >> output.txt
echo "" >> output.txt echo "" >> output.txt
echo ":warning: Please be careful with this pre-release, as is may not work as expected." >> output.txt echo ":warning: Please be careful with this pre-release, as it may not work as expected." >> output.txt
# create the release: # create the release:
echo "Create nightly release." echo "Create nightly release."
@@ -218,9 +221,13 @@ jobs:
gh release upload $releaseName $zipName.sha256 gh release upload $releaseName $zipName.sha256
gh release upload $releaseName $tarName.sha256 gh release upload $releaseName $tarName.sha256
# rm output.txt again # get current HEAD and add as file to the release
rm output.txt HEAD=$(git rev-parse HEAD)
echo $HEAD > HEAD.txt
gh release upload $releaseName HEAD.txt
else else
echo 'MAIN (real) release'
sudo chown -R runner:docker output.txt
# add text to output.txt (more instructions) # add text to output.txt (more instructions)
echo '' >> output.txt echo '' >> output.txt
echo '### Instructions' >> output.txt echo '### Instructions' >> output.txt
@@ -232,13 +239,29 @@ jobs:
git tag -a $releaseName -m "Here be changelog" git tag -a $releaseName -m "Here be changelog"
git push origin $releaseName git push origin $releaseName
gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag gh release create $releaseName -F output.txt -t "$releaseName" --verify-tag
# add zip file to release.
# add archive files to release
gh release upload $releaseName $zipName gh release upload $releaseName $zipName
# add sha256 sum to release gh release upload $releaseName $tarName
# add sha256 sums to release
gh release upload $releaseName $zipName.sha256 gh release upload $releaseName $zipName.sha256
gh release upload $releaseName $tarName.sha256
# get current HEAD and add as file to the release
HEAD=$(git rev-parse HEAD)
echo $HEAD > HEAD.txt
gh release upload $releaseName HEAD.txt
# remove all temporary files
rm output.txt rm output.txt
rm HEAD.txt
rm $zipName rm $zipName
rm $zipName.sha256 rm $zipName.sha256
rm $tarName
rm $tarName.sha256
# merge main back into develop
git checkout develop git checkout develop
git merge main git merge main
git push git push

View File

@@ -17,7 +17,7 @@ jobs:
- uses: actions/stale@v9 - uses: actions/stale@v9
with: with:
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: > stale-issue-message: |
Hi there! Hi there!
This is an automatic reply. `Share and enjoy` This is an automatic reply. `Share and enjoy`
@@ -25,7 +25,7 @@ jobs:
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
Thank you for your contributions. Thank you for your contributions.
stale-pr-message: > stale-pr-message: |
Hi there! Hi there!
This is an automatic reply. `Share and enjoy` This is an automatic reply. `Share and enjoy`

8
.gitignore vendored
View File

@@ -10,3 +10,11 @@ coverage.xml
# ignore generated files. # ignore generated files.
public/build public/build
# ignore v1 build files
resources/assets/v1/node_modules
resources/assets/v1/build
# ignore v2 build files
resources/assets/v2/node_modules
resources/assets/v2/build

View File

@@ -83,17 +83,17 @@ class AccountController extends Controller
// user's preferences // user's preferences
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray(); $defaultSet = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
/** @var Preference $frontPage */ /** @var Preference $frontpage */
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet); $frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
$default = app('amount')->getDefaultCurrency(); $default = app('amount')->getDefaultCurrency();
if (!(is_array($frontPage->data) && count($frontPage->data) > 0)) { if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
$frontPage->data = $defaultSet; $frontpage->data = $defaultSet;
$frontPage->save(); $frontpage->save();
} }
// get accounts: // get accounts:
$accounts = $this->repository->getAccountsById($frontPage->data); $accounts = $this->repository->getAccountsById($frontpage->data);
$chartData = []; $chartData = [];
/** @var Account $account */ /** @var Account $account */

View File

@@ -72,6 +72,11 @@ class UpdateController extends Controller
app('log')->debug('Now in update routine for transaction group!'); app('log')->debug('Now in update routine for transaction group!');
$data = $request->getAll(); $data = $request->getAll();
// Fixes 8750.
foreach ($data['transactions'] as $index => $info) {
unset($data['transactions'][$index]['type']);
}
$transactionGroup = $this->groupRepository->update($transactionGroup, $data); $transactionGroup = $this->groupRepository->update($transactionGroup, $data);
$manager = $this->getManager(); $manager = $this->getManager();

View File

@@ -54,17 +54,13 @@ class TestRequest extends FormRequest
private function getDate(string $field): ?Carbon private function getDate(string $field): ?Carbon
{ {
$value = $this->query($field); $value = $this->query($field);
if (is_array($value)) { if (is_array($value)) {
return null; return null;
} }
$value = (string)$value; $value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
return $result; return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
} }
private function getAccounts(): array private function getAccounts(): array

View File

@@ -48,17 +48,13 @@ class TriggerRequest extends FormRequest
private function getDate(string $field): ?Carbon private function getDate(string $field): ?Carbon
{ {
$value = $this->query($field); $value = $this->query($field);
if (is_array($value)) { if (is_array($value)) {
return null; return null;
} }
$value = (string)$value; $value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
return $result; return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
} }
private function getAccounts(): array private function getAccounts(): array

View File

@@ -48,17 +48,13 @@ class TestRequest extends FormRequest
private function getDate(string $field): ?Carbon private function getDate(string $field): ?Carbon
{ {
$value = $this->query($field); $value = $this->query($field);
if (is_array($value)) { if (is_array($value)) {
return null; return null;
} }
$value = (string)$value; $value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
return $result; return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
} }
private function getAccounts(): array private function getAccounts(): array

View File

@@ -48,17 +48,13 @@ class TriggerRequest extends FormRequest
private function getDate(string $field): ?Carbon private function getDate(string $field): ?Carbon
{ {
$value = $this->query($field); $value = $this->query($field);
if (is_array($value)) { if (is_array($value)) {
return null; return null;
} }
$value = (string)$value; $value = (string)$value;
$result = null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
if (false === $result) {
return null;
}
return $result; return null === $this->query($field) ? null : Carbon::createFromFormat('Y-m-d', substr($value, 0, 10));
} }
private function getAccounts(): array private function getAccounts(): array

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V2\Controllers\Chart;
use Carbon\Carbon; use Carbon\Carbon;
use FireflyIII\Api\V2\Controllers\Controller; use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Chart\DashboardChartRequest; use FireflyIII\Api\V2\Request\Chart\DashboardChartRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Models\AccountType; use FireflyIII\Models\AccountType;
@@ -46,6 +47,7 @@ class AccountController extends Controller
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
private AccountRepositoryInterface $repository; private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
public function __construct() public function __construct()
{ {
@@ -54,9 +56,7 @@ class AccountController extends Controller
function ($request, $next) { function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class); $this->repository = app(AccountRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request); $userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) { $this->repository->setUserGroup($userGroup);
$this->repository->setUserGroup($userGroup);
}
return $next($request); return $next($request);
} }
@@ -98,14 +98,14 @@ class AccountController extends Controller
// user's preferences // user's preferences
if (0 === $accounts->count()) { if (0 === $accounts->count()) {
$defaultSet = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT])->pluck('id')->toArray(); $defaultSet = $this->repository->getAccountsByType([AccountType::ASSET, AccountType::DEFAULT])->pluck('id')->toArray();
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet); $frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
if (!(is_array($frontPage->data) && count($frontPage->data) > 0)) { if (!(is_array($frontpage->data) && count($frontpage->data) > 0)) {
$frontPage->data = $defaultSet; $frontpage->data = $defaultSet;
$frontPage->save(); $frontpage->save();
} }
$accounts = $this->repository->getAccountsById($frontPage->data); $accounts = $this->repository->getAccountsById($frontpage->data);
} }
// both options are overruled by "preselected" // both options are overruled by "preselected"

View File

@@ -27,6 +27,7 @@ namespace FireflyIII\Api\V2\Controllers;
use Carbon\Carbon; use Carbon\Carbon;
use Carbon\Exceptions\InvalidDateException; use Carbon\Exceptions\InvalidDateException;
use Carbon\Exceptions\InvalidFormatException; use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Transformers\V2\AbstractTransformer; use FireflyIII\Transformers\V2\AbstractTransformer;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
@@ -55,6 +56,7 @@ class Controller extends BaseController
protected const string CONTENT_TYPE = 'application/vnd.api+json'; protected const string CONTENT_TYPE = 'application/vnd.api+json';
protected ParameterBag $parameters; protected ParameterBag $parameters;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
public function __construct() public function __construct()
{ {

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller; use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Api\V2\Request\Model\Account\IndexRequest; use FireflyIII\Api\V2\Request\Model\Account\IndexRequest;
use FireflyIII\Api\V2\Request\Model\Transaction\InfiniteListRequest; use FireflyIII\Api\V2\Request\Model\Transaction\InfiniteListRequest;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface; use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\V2\AccountTransformer; use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -33,9 +34,10 @@ use Illuminate\Pagination\LengthAwarePaginator;
class IndexController extends Controller class IndexController extends Controller
{ {
public const string RESOURCE_KEY = 'accounts'; public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository; private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
/** /**
* AccountController constructor. * AccountController constructor.
@@ -48,9 +50,7 @@ class IndexController extends Controller
$this->repository = app(AccountRepositoryInterface::class); $this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation // new way of user group validation
$userGroup = $this->validateUserGroup($request); $userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) { $this->repository->setUserGroup($userGroup);
$this->repository->setUserGroup($userGroup);
}
return $next($request); return $next($request);
} }

View File

@@ -25,7 +25,9 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Controllers\Model\Account; namespace FireflyIII\Api\V2\Controllers\Model\Account;
use FireflyIII\Api\V2\Controllers\Controller; use FireflyIII\Api\V2\Controllers\Controller;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\Account; use FireflyIII\Models\Account;
use FireflyIII\Repositories\UserGroups\Account\AccountRepositoryInterface;
use FireflyIII\Transformers\V2\AccountTransformer; use FireflyIII\Transformers\V2\AccountTransformer;
use Illuminate\Http\JsonResponse; use Illuminate\Http\JsonResponse;
@@ -36,6 +38,29 @@ use Illuminate\Http\JsonResponse;
*/ */
class ShowController extends Controller class ShowController extends Controller
{ {
public const string RESOURCE_KEY = 'accounts';
private AccountRepositoryInterface $repository;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY, UserRoleEnum::MANAGE_TRANSACTIONS];
/**
* AccountController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
$this->repository = app(AccountRepositoryInterface::class);
// new way of user group validation
$userGroup = $this->validateUserGroup($request);
$this->repository->setUserGroup($userGroup);
return $next($request);
}
);
}
/** /**
* TODO this endpoint is not yet reachable. * TODO this endpoint is not yet reachable.
*/ */

View File

@@ -77,13 +77,11 @@ class BasicController extends Controller
$this->opsRepository = app(OperationsRepositoryInterface::class); $this->opsRepository = app(OperationsRepositoryInterface::class);
$userGroup = $this->validateUserGroup($request); $userGroup = $this->validateUserGroup($request);
if (null !== $userGroup) { $this->abRepository->setUserGroup($userGroup);
$this->abRepository->setUserGroup($userGroup); $this->accountRepository->setUserGroup($userGroup);
$this->accountRepository->setUserGroup($userGroup); $this->billRepository->setUserGroup($userGroup);
$this->billRepository->setUserGroup($userGroup); $this->budgetRepository->setUserGroup($userGroup);
$this->budgetRepository->setUserGroup($userGroup); $this->opsRepository->setUserGroup($userGroup);
$this->opsRepository->setUserGroup($userGroup);
}
return $next($request); return $next($request);
} }
@@ -298,7 +296,7 @@ class BasicController extends Controller
app('log')->debug(sprintf('Amount left is %s', $left)); app('log')->debug(sprintf('Amount left is %s', $left));
// how much left per day? // how much left per day?
$days = (int) $today->diffInDays($end, true) + 1; $days = (int)$today->diffInDays($end, true) + 1;
$perDay = '0'; $perDay = '0';
$perDayNative = '0'; $perDayNative = '0';
if (0 !== $days && bccomp($left, '0') > -1) { if (0 !== $days && bccomp($left, '0') > -1) {

View File

@@ -79,4 +79,12 @@ class UpdateController extends Controller
->header('Content-Type', self::CONTENT_TYPE) ->header('Content-Type', self::CONTENT_TYPE)
; ;
} }
public function useUserGroup(UserGroup $userGroup): JsonResponse
{
// group validation is already in place, so can just update the user.
$this->repository->useUserGroup($userGroup);
return response()->json([], 204);
}
} }

View File

@@ -23,6 +23,7 @@ declare(strict_types=1);
namespace FireflyIII\Api\V2\Request\Chart; namespace FireflyIII\Api\V2\Request\Chart;
use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait; use FireflyIII\Support\Http\Api\ValidatesUserGroupTrait;
use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
@@ -39,6 +40,8 @@ class DashboardChartRequest extends FormRequest
use ConvertsDataTypes; use ConvertsDataTypes;
use ValidatesUserGroupTrait; use ValidatesUserGroupTrait;
protected array $acceptedRoles = [UserRoleEnum::READ_ONLY];
/** /**
* Get all data from the request. * Get all data from the request.
*/ */

View File

@@ -26,6 +26,7 @@ namespace FireflyIII\Api\V2\Request\UserGroup;
use FireflyIII\Enums\UserRoleEnum; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
use FireflyIII\Rules\IsDefaultUserGroupName;
use FireflyIII\Support\Request\ChecksLogin; use FireflyIII\Support\Request\ChecksLogin;
use FireflyIII\Support\Request\ConvertsDataTypes; use FireflyIII\Support\Request\ConvertsDataTypes;
use Illuminate\Foundation\Http\FormRequest; use Illuminate\Foundation\Http\FormRequest;
@@ -53,7 +54,7 @@ class UpdateRequest extends FormRequest
$userGroup = $this->route()->parameter('userGroup'); $userGroup = $this->route()->parameter('userGroup');
return [ return [
'title' => sprintf('required|min:1|max:255|unique:user_groups,title,%d', $userGroup->id), 'title' => ['required', 'min:1', 'max:255', sprintf('unique:user_groups,title,%d', $userGroup->id), new IsDefaultUserGroupName($userGroup)],
]; ];
} }
} }

View File

@@ -73,6 +73,7 @@ class CorrectDatabase extends Command
// new! // new!
'firefly-iii:unify-group-accounts', 'firefly-iii:unify-group-accounts',
'firefly-iii:trigger-credit-recalculation', 'firefly-iii:trigger-credit-recalculation',
'firefly-iii:migrate-preferences',
]; ];
foreach ($commands as $command) { foreach ($commands as $command) {
$this->friendlyLine(sprintf('Now executing command "%s"', $command)); $this->friendlyLine(sprintf('Now executing command "%s"', $command));

View File

@@ -50,7 +50,7 @@ class FixFrontpageAccounts extends Command
/** @var User $user */ /** @var User $user */
foreach ($users as $user) { foreach ($users as $user) {
$preference = app('preferences')->getForUser($user, 'frontPageAccounts'); $preference = app('preferences')->getForUser($user, 'frontpageAccounts');
if (null !== $preference) { if (null !== $preference) {
$this->fixPreference($preference); $this->fixPreference($preference);
} }
@@ -83,6 +83,6 @@ class FixFrontpageAccounts extends Command
} }
} }
} }
app('preferences')->setForUser($preference->user, 'frontPageAccounts', $fixed); app('preferences')->setForUser($preference->user, 'frontpageAccounts', $fixed);
} }
} }

View File

@@ -0,0 +1,66 @@
<?php
declare(strict_types=1);
/*
* MigratePreferences.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
namespace FireflyIII\Console\Commands\Correction;
use FireflyIII\Models\Preference;
use FireflyIII\User;
use Illuminate\Console\Command;
use Symfony\Component\Console\Command\Command as CommandAlias;
class MigratePreferences extends Command
{
protected $description = 'Give Firefly III preferences a user group ID so they can be made administration specific.';
protected $signature = 'firefly-iii:migrate-preferences';
/**
* Execute the console command.
*/
public function handle(): int
{
$items = config('firefly.admin_specific_prefs');
$users = User::get();
/** @var User $user */
foreach ($users as $user) {
$count = 0;
foreach ($items as $item) {
$preference = Preference::where('name', $item)->where('user_id', $user->id)->first();
if (null === $preference) {
continue;
}
if (null !== $preference->user_group_id) {
$preference->user_group_id = $user->user_group_id;
$preference->save();
++$count;
}
}
if ($count > 0) {
$this->info(sprintf('Migrated %d preference(s) for user #%d ("%s").', $count, $user->id, $user->email));
}
}
return CommandAlias::SUCCESS;
}
}

View File

@@ -191,7 +191,7 @@ class ExportData extends Command
$this->friendlyError(sprintf('%s date "%s" must be formatted YYYY-MM-DD. Field will be ignored.', $field, $this->option('start'))); $this->friendlyError(sprintf('%s date "%s" must be formatted YYYY-MM-DD. Field will be ignored.', $field, $this->option('start')));
$error = true; $error = true;
} }
if (false === $date) { if (null === $date) {
$this->friendlyError(sprintf('%s date "%s" must be formatted YYYY-MM-DD.', $field, $this->option('start'))); $this->friendlyError(sprintf('%s date "%s" must be formatted YYYY-MM-DD.', $field, $this->option('start')));
throw new FireflyException(sprintf('%s date "%s" must be formatted YYYY-MM-DD.', $field, $this->option('start'))); throw new FireflyException(sprintf('%s date "%s" must be formatted YYYY-MM-DD.', $field, $this->option('start')));

View File

@@ -80,7 +80,7 @@ class CreateGroupMemberships extends Command
// check if membership exists // check if membership exists
$userGroup = UserGroup::where('title', $user->email)->first(); $userGroup = UserGroup::where('title', $user->email)->first();
if (null === $userGroup) { if (null === $userGroup) {
$userGroup = UserGroup::create(['title' => $user->email]); $userGroup = UserGroup::create(['title' => $user->email, 'default_administration' => true]);
} }
$userRole = UserRole::where('title', UserRoleEnum::OWNER->value)->first(); $userRole = UserRole::where('title', UserRoleEnum::OWNER->value)->first();

View File

@@ -32,24 +32,13 @@ class LaravelPassportKeys extends Command
{ {
use ShowsFriendlyMessages; use ShowsFriendlyMessages;
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'firefly-iii:laravel-passport-keys';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Calls the Laravel "passport:keys" but doesn\'t exit 1.'; protected $description = 'Calls the Laravel "passport:keys" but doesn\'t exit 1.';
protected $signature = 'firefly-iii:laravel-passport-keys';
/** /**
* Execute the console command. * Execute the console command.
*/ */
public function handle() public function handle(): int
{ {
Artisan::call('passport:keys --no-interaction', []); Artisan::call('passport:keys --no-interaction', []);
$result = Artisan::output(); $result = Artisan::output();

View File

@@ -285,7 +285,7 @@ class ApplyRules extends Command
if (null !== $endString && '' !== $endString) { if (null !== $endString && '' !== $endString) {
$inputEnd = Carbon::createFromFormat('Y-m-d', $endString); $inputEnd = Carbon::createFromFormat('Y-m-d', $endString);
} }
if (false === $inputEnd || false === $inputStart) { if (null === $inputEnd || null === $inputStart) {
Log::error('Could not parse start or end date in verifyInputDate().'); Log::error('Could not parse start or end date in verifyInputDate().');
return; return;

View File

@@ -69,6 +69,7 @@ class UpgradeDatabase extends Command
'firefly-iii:create-group-memberships', 'firefly-iii:create-group-memberships',
'firefly-iii:upgrade-group-information', 'firefly-iii:upgrade-group-information',
'firefly-iii:upgrade-currency-preferences', 'firefly-iii:upgrade-currency-preferences',
'firefly-iii:correct-database',
]; ];
$args = []; $args = [];
if ($this->option('force')) { if ($this->option('force')) {

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Exceptions; namespace FireflyIII\Exceptions;
use FireflyIII\Jobs\MailError; use FireflyIII\Jobs\MailError;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException; use Illuminate\Auth\AuthenticationException;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler; use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
@@ -98,6 +99,13 @@ class Handler extends ExceptionHandler
return response()->json(['message' => 'Resource not found', 'exception' => 'NotFoundHttpException'], 404); return response()->json(['message' => 'Resource not found', 'exception' => 'NotFoundHttpException'], 404);
} }
if ($e instanceof AuthorizationException && $expectsJson) {
// somehow Laravel handler does not catch this:
app('log')->debug('Return JSON unauthorized error.');
return response()->json(['message' => $e->getMessage(), 'exception' => 'AuthorizationException'], 401);
}
if ($e instanceof AuthenticationException && $expectsJson) { if ($e instanceof AuthenticationException && $expectsJson) {
// somehow Laravel handler does not catch this: // somehow Laravel handler does not catch this:
app('log')->debug('Return JSON unauthenticated error.'); app('log')->debug('Return JSON unauthenticated error.');

View File

@@ -405,7 +405,7 @@ class UserEventHandler
} }
// clean up old entries (6 months) // clean up old entries (6 months)
$carbon = Carbon::createFromFormat('Y-m-d H:i:s', $preference[$index]['time']); $carbon = Carbon::createFromFormat('Y-m-d H:i:s', $preference[$index]['time']);
if (false !== $carbon && $carbon->diffInMonths(today(), true) > 6) { if (null !== $carbon && $carbon->diffInMonths(today(), true) > 6) {
app('log')->debug(sprintf('Entry for %s is very old, remove it.', $row['ip'])); app('log')->debug(sprintf('Entry for %s is very old, remove it.', $row['ip']));
unset($preference[$index]); unset($preference[$index]);
} }

View File

@@ -145,13 +145,13 @@ class CreateController extends Controller
Log::channel('audit')->info('Stored new account.', $data); Log::channel('audit')->info('Stored new account.', $data);
// update preferences if necessary: // update preferences if necessary:
$frontPage = app('preferences')->get('frontPageAccounts', [])->data; $frontpage = app('preferences')->get('frontpageAccounts', [])->data;
if (!is_array($frontPage)) { if (!is_array($frontpage)) {
$frontPage = []; $frontpage = [];
} }
if (AccountType::ASSET === $account->accountType->type) { if (AccountType::ASSET === $account->accountType->type) {
$frontPage[] = $account->id; $frontpage[] = $account->id;
app('preferences')->set('frontPageAccounts', $frontPage); app('preferences')->set('frontpageAccounts', $frontpage);
} }
// store attachment(s): // store attachment(s):

View File

@@ -128,7 +128,7 @@ class BudgetLimitController extends Controller
$start = Carbon::createFromFormat('Y-m-d', $request->get('start')); $start = Carbon::createFromFormat('Y-m-d', $request->get('start'));
$end = Carbon::createFromFormat('Y-m-d', $request->get('end')); $end = Carbon::createFromFormat('Y-m-d', $request->get('end'));
if (false === $start || false === $end) { if (null === $start || null === $end) {
return response()->json([]); return response()->json([]);
} }

View File

@@ -301,14 +301,14 @@ class AccountController extends Controller
$end = clone session('end', today(config('app.timezone'))->endOfMonth()); $end = clone session('end', today(config('app.timezone'))->endOfMonth());
$defaultSet = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray(); $defaultSet = $repository->getAccountsByType([AccountType::DEFAULT, AccountType::ASSET])->pluck('id')->toArray();
app('log')->debug('Default set is ', $defaultSet); app('log')->debug('Default set is ', $defaultSet);
$frontPage = app('preferences')->get('frontPageAccounts', $defaultSet); $frontpage = app('preferences')->get('frontpageAccounts', $defaultSet);
$frontPageArray = !is_array($frontPage->data) ? [] : $frontPage->data; $frontpageArray = !is_array($frontpage->data) ? [] : $frontpage->data;
app('log')->debug('Frontpage preference set is ', $frontPageArray); app('log')->debug('Frontpage preference set is ', $frontpageArray);
if (0 === count($frontPageArray)) { if (0 === count($frontpageArray)) {
app('preferences')->set('frontPageAccounts', $defaultSet); app('preferences')->set('frontpageAccounts', $defaultSet);
app('log')->debug('frontpage set is empty!'); app('log')->debug('frontpage set is empty!');
} }
$accounts = $repository->getAccountsById($frontPageArray); $accounts = $repository->getAccountsById($frontpageArray);
return response()->json($this->accountBalanceChart($accounts, $start, $end)); return response()->json($this->accountBalanceChart($accounts, $start, $end));
} }

View File

@@ -116,8 +116,8 @@ class CategoryController extends Controller
return response()->json($cache->get()); return response()->json($cache->get());
} }
$frontPageGenerator = new FrontpageChartGenerator($start, $end); $frontpageGenerator = new FrontpageChartGenerator($start, $end);
$chartData = $frontPageGenerator->generate(); $chartData = $frontpageGenerator->generate();
$data = $this->generator->multiSet($chartData); $data = $this->generator->multiSet($chartData);
$cache->store($data); $cache->store($data);

View File

@@ -79,10 +79,10 @@ class HomeController extends Controller
app('log')->error(sprintf('End could not parse date string "%s" so ignore it.', $stringEnd)); app('log')->error(sprintf('End could not parse date string "%s" so ignore it.', $stringEnd));
$end = Carbon::now()->endOfMonth(); $end = Carbon::now()->endOfMonth();
} }
if (false === $start) { if (null === $start) {
$start = Carbon::now()->startOfMonth(); $start = Carbon::now()->startOfMonth();
} }
if (false === $end) { if (null === $end) {
$end = Carbon::now()->endOfMonth(); $end = Carbon::now()->endOfMonth();
} }
@@ -120,33 +120,45 @@ class HomeController extends Controller
*/ */
public function index(AccountRepositoryInterface $repository): mixed public function index(AccountRepositoryInterface $repository): mixed
{ {
$types = config('firefly.accountTypesByIdentifier.asset'); $types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types); $count = $repository->count($types);
Log::channel('audit')->info('User visits homepage.'); Log::channel('audit')->info('User visits homepage.');
if (0 === $count) { if (0 === $count) {
return redirect(route('new-user.index')); return redirect(route('new-user.index'));
} }
if ('v1' === (string)config('view.layout')) {
return $this->indexV1($repository);
}
if ('v2' === (string)config('view.layout')) {
return $this->indexV2();
}
throw new FireflyException('Invalid layout configuration');
}
private function indexV1(AccountRepositoryInterface $repository): mixed
{
$types = config('firefly.accountTypesByIdentifier.asset');
$count = $repository->count($types);
$subTitle = (string)trans('firefly.welcome_back'); $subTitle = (string)trans('firefly.welcome_back');
$transactions = []; $transactions = [];
$frontPage = app('preferences')->getFresh('frontPageAccounts', $repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray()); $frontpage = app('preferences')->getFresh('frontpageAccounts', $repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray());
$frontPageArray = $frontPage->data; $frontpageArray = $frontpage->data;
if (!is_array($frontPageArray)) { if (!is_array($frontpageArray)) {
$frontPageArray = []; $frontpageArray = [];
} }
/** @var Carbon $start */ /** @var Carbon $start */
$start = session('start', today(config('app.timezone'))->startOfMonth());
/** @var Carbon $end */ /** @var Carbon $end */
$start = session('start', today(config('app.timezone'))->startOfMonth());
$end = session('end', today(config('app.timezone'))->endOfMonth()); $end = session('end', today(config('app.timezone'))->endOfMonth());
$accounts = $repository->getAccountsById($frontPageArray); $accounts = $repository->getAccountsById($frontpageArray);
$today = today(config('app.timezone')); $today = today(config('app.timezone'));
$accounts = $accounts->sortBy('order'); // sort frontpage accounts by order
// sort frontpage accounts by order app('log')->debug('Frontpage accounts are ', $frontpageArray);
$accounts = $accounts->sortBy('order');
app('log')->debug('Frontpage accounts are ', $frontPageArray);
/** @var BillRepositoryInterface $billRepository */ /** @var BillRepositoryInterface $billRepository */
$billRepository = app(BillRepositoryInterface::class); $billRepository = app(BillRepositoryInterface::class);
@@ -166,4 +178,18 @@ class HomeController extends Controller
return view('index', compact('count', 'subTitle', 'transactions', 'billCount', 'start', 'end', 'today')); return view('index', compact('count', 'subTitle', 'transactions', 'billCount', 'start', 'end', 'today'));
} }
private function indexV2(): mixed
{
$subTitle = (string)trans('firefly.welcome_back');
$start = session('start', today(config('app.timezone'))->startOfMonth());
$end = session('end', today(config('app.timezone'))->endOfMonth());
/** @var User $user */
$user = auth()->user();
event(new RequestedVersionCheckStatus($user));
return view('index', compact('subTitle', 'start', 'end'));
}
} }

View File

@@ -130,7 +130,7 @@ class BoxController extends Controller
$boxTitle = (string)trans('firefly.left_to_spend'); $boxTitle = (string)trans('firefly.left_to_spend');
$activeDaysLeft = $this->activeDaysLeft($start, $end); // see method description. $activeDaysLeft = $this->activeDaysLeft($start, $end); // see method description.
$display = 1; // not overspent $display = 1; // not overspent
$leftPerDayAmount = 0 === (int) $activeDaysLeft ? $leftToSpendAmount : bcdiv($leftToSpendAmount, (string)$activeDaysLeft); $leftPerDayAmount = 0 === $activeDaysLeft ? $leftToSpendAmount : bcdiv($leftToSpendAmount, (string)$activeDaysLeft);
app('log')->debug(sprintf('Left to spend per day is %s', $leftPerDayAmount)); app('log')->debug(sprintf('Left to spend per day is %s', $leftPerDayAmount));
} }
} }

View File

@@ -81,7 +81,7 @@ class RecurrenceController extends Controller
$skip = $skip < 0 || $skip > 31 ? 0 : $skip; $skip = $skip < 0 || $skip > 31 ? 0 : $skip;
$weekend = $weekend < 1 || $weekend > 4 ? 1 : $weekend; $weekend = $weekend < 1 || $weekend > 4 ? 1 : $weekend;
if (false === $start || false === $end || false === $firstDate || false === $endDate) { if (null === $start || null === $end || null === $firstDate || null === $endDate) {
return response()->json(); return response()->json();
} }
@@ -112,7 +112,7 @@ class RecurrenceController extends Controller
$actualEnd = clone $end; $actualEnd = clone $end;
if ('until_date' === $endsAt) { if ('until_date' === $endsAt) {
$actualEnd = $endDate ?? clone $end; $actualEnd = $endDate;
$occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd); $occurrences = $this->recurring->getOccurrencesInRange($repetition, $actualStart, $actualEnd);
} }
if ('times' === $endsAt) { if ('times' === $endsAt) {
@@ -155,7 +155,7 @@ class RecurrenceController extends Controller
} catch (InvalidFormatException $e) { } catch (InvalidFormatException $e) {
$date = Carbon::today(config('app.timezone')); $date = Carbon::today(config('app.timezone'));
} }
if (false === $date) { if (null === $date) {
return response()->json(); return response()->json();
} }
$date->startOfDay(); $date->startOfDay();

View File

@@ -115,7 +115,7 @@ class NewUserController extends Controller
// store frontpage preferences: // store frontpage preferences:
$accounts = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray(); $accounts = $this->repository->getAccountsByType([AccountType::ASSET])->pluck('id')->toArray();
app('preferences')->set('frontPageAccounts', $accounts); app('preferences')->set('frontpageAccounts', $accounts);
// mark. // mark.
app('preferences')->mark(); app('preferences')->mark();

View File

@@ -89,10 +89,10 @@ class PreferencesController extends Controller
/** @var array<int, int> $accountIds */ /** @var array<int, int> $accountIds */
$accountIds = $accounts->pluck('id')->toArray(); $accountIds = $accounts->pluck('id')->toArray();
$viewRange = app('navigation')->getViewRange(false); $viewRange = app('navigation')->getViewRange(false);
$frontPageAccountsPref = app('preferences')->get('frontPageAccounts', $accountIds); $frontpageAccountsPref = app('preferences')->get('frontpageAccounts', $accountIds);
$frontPageAccounts = $frontPageAccountsPref->data; $frontpageAccounts = $frontpageAccountsPref->data;
if (!is_array($frontPageAccounts)) { if (!is_array($frontpageAccounts)) {
$frontPageAccounts = $accountIds; $frontpageAccounts = $accountIds;
} }
$language = app('steam')->getLanguage(); $language = app('steam')->getLanguage();
$languages = config('firefly.languages'); $languages = config('firefly.languages');
@@ -128,8 +128,8 @@ class PreferencesController extends Controller
$locales = ['equal' => (string)trans('firefly.equal_to_language')] + $locales; $locales = ['equal' => (string)trans('firefly.equal_to_language')] + $locales;
// an important fallback is that the frontPageAccount array gets refilled automatically // an important fallback is that the frontPageAccount array gets refilled automatically
// when it turns up empty. // when it turns up empty.
if (0 === count($frontPageAccounts)) { if (0 === count($frontpageAccounts)) {
$frontPageAccounts = $accountIds; $frontpageAccounts = $accountIds;
} }
// for the demo user, the slackUrl is automatically emptied. // for the demo user, the slackUrl is automatically emptied.
@@ -139,7 +139,7 @@ class PreferencesController extends Controller
$slackUrl = ''; $slackUrl = '';
} }
return view('preferences.index', compact('language', 'groupedAccounts', 'isDocker', 'frontPageAccounts', 'languages', 'darkMode', 'availableDarkModes', 'notifications', 'slackUrl', 'locales', 'locale', 'tjOptionalFields', 'viewRange', 'customFiscalYear', 'listPageSize', 'fiscalYearStart')); return view('preferences.index', compact('language', 'groupedAccounts', 'isDocker', 'frontpageAccounts', 'languages', 'darkMode', 'availableDarkModes', 'notifications', 'slackUrl', 'locales', 'locale', 'tjOptionalFields', 'viewRange', 'customFiscalYear', 'listPageSize', 'fiscalYearStart'));
} }
/** /**
@@ -155,12 +155,12 @@ class PreferencesController extends Controller
public function postIndex(Request $request) public function postIndex(Request $request)
{ {
// front page accounts // front page accounts
$frontPageAccounts = []; $frontpageAccounts = [];
if (is_array($request->get('frontPageAccounts')) && count($request->get('frontPageAccounts')) > 0) { if (is_array($request->get('frontpageAccounts')) && count($request->get('frontpageAccounts')) > 0) {
foreach ($request->get('frontPageAccounts') as $id) { foreach ($request->get('frontpageAccounts') as $id) {
$frontPageAccounts[] = (int)$id; $frontpageAccounts[] = (int)$id;
} }
app('preferences')->set('frontPageAccounts', $frontPageAccounts); app('preferences')->set('frontpageAccounts', $frontpageAccounts);
} }
// extract notifications: // extract notifications:
@@ -223,8 +223,8 @@ class PreferencesController extends Controller
// same for locale: // same for locale:
if (!auth()->user()->hasRole('demo')) { if (!auth()->user()->hasRole('demo')) {
/** @var Preference $locale */ $locale = (string) $request->get('locale');
$locale = $request->get('locale'); $locale = '' === $locale ? null : $locale;
app('preferences')->set('locale', $locale); app('preferences')->set('locale', $locale);
} }

View File

@@ -23,7 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers; namespace FireflyIII\Http\Controllers;
use Auth;
use FireflyIII\Events\UserChangedEmail; use FireflyIII\Events\UserChangedEmail;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Exceptions\ValidationException; use FireflyIII\Exceptions\ValidationException;
@@ -467,9 +466,7 @@ class ProfileController extends Controller
if (is_array($secret)) { if (is_array($secret)) {
$secret = null; $secret = null;
} }
if (is_int($secret)) { $secret = (string)$secret;
$secret = (string)$secret;
}
$repository->setMFACode($user, $secret); $repository->setMFACode($user, $secret);

View File

@@ -36,7 +36,7 @@ class CreateController extends Controller
public function create() public function create()
{ {
$title = (string)trans('firefly.administrations_page_title'); $title = (string)trans('firefly.administrations_page_title');
$subTitle = (string)trans('firefly.administrations_page_sub_title'); $subTitle = (string)trans('firefly.administrations_page_create_sub_title');
$mainTitleIcon = 'fa-book'; $mainTitleIcon = 'fa-book';
app('log')->debug(sprintf('Now at %s', __METHOD__)); app('log')->debug(sprintf('Now at %s', __METHOD__));

View File

@@ -0,0 +1,46 @@
<?php
/*
* CreateController.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\UserGroup;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Models\UserGroup;
use Illuminate\Contracts\View\Factory;
use Illuminate\Contracts\View\View;
use Illuminate\Foundation\Application;
class EditController extends Controller
{
/**
* @return Application|Factory|\Illuminate\Contracts\Foundation\Application|View
*/
public function edit(UserGroup $userGroup)
{
$title = (string)trans('firefly.administrations_page_title');
$subTitle = (string)trans('firefly.administrations_page_edit_sub_title', ['title' => $userGroup->title]);
$mainTitleIcon = 'fa-book';
app('log')->debug(sprintf('Now at %s', __METHOD__));
return view('administrations.edit')->with(compact('title', 'subTitle', 'mainTitleIcon'));
}
}

View File

@@ -119,7 +119,7 @@ class DownloadExchangeRates implements ShouldQueue
return; return;
} }
$date = Carbon::createFromFormat('Y-m-d', $json['date'], config('app.timezone')); $date = Carbon::createFromFormat('Y-m-d', $json['date'], config('app.timezone'));
if (false === $date) { if (null === $date) {
return; return;
} }
$this->saveRates($currency, $date, $json['rates']); $this->saveRates($currency, $date, $json['rates']);

View File

@@ -27,6 +27,7 @@ use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Message; use Illuminate\Mail\Message;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Mailer\Exception\TransportException; use Symfony\Component\Mailer\Exception\TransportException;
/** /**
@@ -68,6 +69,14 @@ class MailError extends Job implements ShouldQueue
$args['user'] = $this->userData; $args['user'] = $this->userData;
$args['ip'] = $this->ipAddress; $args['ip'] = $this->ipAddress;
$args['token'] = config('firefly.ipinfo_token'); $args['token'] = config('firefly.ipinfo_token');
// limit number of error mails that can be sent.
if ($this->reachedLimit()) {
Log::info('MailError: reached limit, not sending email.');
return;
}
if ($this->attempts() < 3 && '' !== $email) { if ($this->attempts() < 3 && '' !== $email) {
try { try {
\Mail::send( \Mail::send(
@@ -96,4 +105,62 @@ class MailError extends Job implements ShouldQueue
} }
} }
} }
private function reachedLimit(): bool
{
Log::debug('reachedLimit()');
$types = [
'5m' => ['limit' => 5, 'reset' => 5 * 60],
'1h' => ['limit' => 15, 'reset' => 60 * 60],
'24h' => ['limit' => 15, 'reset' => 24 * 60 * 60],
];
$file = storage_path('framework/cache/error-count.json');
$directory = storage_path('framework/cache');
$limits = [];
if (!is_writable($directory)) {
Log::error(sprintf('MailError: cannot write to "%s", cannot rate limit errors!', $directory));
return false;
}
if (!file_exists($file)) {
Log::debug(sprintf('Wrote new file in "%s"', $file));
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
}
if (file_exists($file)) {
Log::debug(sprintf('Read file in "%s"', $file));
$limits = json_decode(file_get_contents($file), true);
}
// limit reached?
foreach ($types as $type => $info) {
Log::debug(sprintf('Now checking limit "%s"', $type), $info);
if (!isset($limits[$type])) {
Log::debug(sprintf('Limit "%s" reset to zero, did not exist yet.', $type));
$limits[$type] = [
'time' => time(),
'sent' => 0,
];
}
if (time() - $limits[$type]['time'] > $info['reset']) {
Log::debug(sprintf('Time past for this limit is %d seconds, exceeding %d seconds. Reset to zero.', time() - $limits[$type]['time'], $info['reset']));
$limits[$type] = [
'time' => time(),
'sent' => 0,
];
}
if ($limits[$type]['sent'] > $info['limit']) {
Log::warning(sprintf('Sent %d emails in %s, return true.', $limits[$type]['sent'], $type));
return true;
}
++$limits[$type]['sent'];
}
file_put_contents($file, json_encode($limits, JSON_PRETTY_PRINT));
Log::debug('No limits reached, return FALSE.');
return false;
}
} }

View File

@@ -128,7 +128,7 @@ class WarnAboutBills implements ShouldQueue
$today = clone $this->date; $today = clone $this->date;
$carbon = clone $bill->{$field}; $carbon = clone $bill->{$field};
return (int) $today->diffInDays($carbon); return (int)$today->diffInDays($carbon);
} }
private function sendWarning(Bill $bill, string $field): void private function sendWarning(Bill $bill, string $field): void

View File

@@ -110,6 +110,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static EloquentBuilder|Account whereUserGroupId($value) * @method static EloquentBuilder|Account whereUserGroupId($value)
* *
* @property null|UserGroup $userGroup * @property null|UserGroup $userGroup
* @property mixed $account_id
* *
* @mixin Eloquent * @mixin Eloquent
*/ */

View File

@@ -61,6 +61,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|InvitedUser whereUpdatedAt($value) * @method static Builder|InvitedUser whereUpdatedAt($value)
* @method static Builder|InvitedUser whereUserId($value) * @method static Builder|InvitedUser whereUserId($value)
* *
* @property mixed $user_group_id
*
* @mixin Eloquent * @mixin Eloquent
*/ */
class InvitedUser extends Model class InvitedUser extends Model

View File

@@ -36,13 +36,13 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/** /**
* FireflyIII\Models\Preference * FireflyIII\Models\Preference
* *
* @property int $id * @property int $id
* @property null|Carbon $created_at * @property null|Carbon $created_at
* @property null|Carbon $updated_at * @property null|Carbon $updated_at
* @property int $user_id * @property int $user_id
* @property string $name * @property string $name
* @property null|array|int|string $data * @property null|array|bool|int|string $data
* @property User $user * @property User $user
* *
* @method static Builder|Preference newModelQuery() * @method static Builder|Preference newModelQuery()
* @method static Builder|Preference newQuery() * @method static Builder|Preference newQuery()
@@ -54,6 +54,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
* @method static Builder|Preference whereUpdatedAt($value) * @method static Builder|Preference whereUpdatedAt($value)
* @method static Builder|Preference whereUserId($value) * @method static Builder|Preference whereUserId($value)
* *
* @property mixed $user_group_id
*
* @mixin Eloquent * @mixin Eloquent
*/ */
class Preference extends Model class Preference extends Model
@@ -79,22 +81,39 @@ class Preference extends Model
{ {
if (auth()->check()) { if (auth()->check()) {
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
// some preferences do not have an administration ID.
// some need it, to make sure the correct one is selected.
$userGroupId = (int)$user->user_group_id;
$userGroupId = 0 === $userGroupId ? null : $userGroupId;
/** @var null|Preference $preference */ /** @var null|Preference $preference */
$preference = $user->preferences()->where('name', $value)->first(); $preference = null;
$items = config('firefly.admin_specific_prefs');
if (null !== $userGroupId && in_array($value, $items, true)) {
// find a preference with a specific user_group_id
$preference = $user->preferences()->where('user_group_id', $userGroupId)->where('name', $value)->first();
}
if (!in_array($value, $items, true)) {
// find any one.
$preference = $user->preferences()->where('name', $value)->first();
}
// try again with ID, but this time don't care about the preferred user_group_id
if (null === $preference) { if (null === $preference) {
$preference = $user->preferences()->where('id', (int)$value)->first(); $preference = $user->preferences()->where('id', (int)$value)->first();
} }
if (null !== $preference) { if (null !== $preference) {
return $preference; return $preference;
} }
$default = config('firefly.default_preferences'); $default = config('firefly.default_preferences');
if (array_key_exists($value, $default)) { if (array_key_exists($value, $default)) {
$preference = new self(); $preference = new self();
$preference->name = $value; $preference->name = $value;
$preference->data = $default[$value]; $preference->data = $default[$value];
$preference->user_id = (int)$user->id; $preference->user_id = (int)$user->id;
$preference->user_group_id = in_array($value, $items, true) ? $userGroupId : null;
$preference->save(); $preference->save();
return $preference; return $preference;

View File

@@ -81,6 +81,7 @@ use Illuminate\Database\Query\Builder;
* @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransaction whereTransactionTypeId($value) * @method static \Illuminate\Database\Eloquent\Builder|RecurrenceTransaction whereTransactionTypeId($value)
* *
* @property null|TransactionType $transactionType * @property null|TransactionType $transactionType
* @property mixed $user_id
* *
* @mixin Eloquent * @mixin Eloquent
*/ */

View File

@@ -98,7 +98,7 @@ class UserGroup extends Model
{ {
use ReturnsIntegerIdTrait; use ReturnsIntegerIdTrait;
protected $fillable = ['title']; protected $fillable = ['title', 'default_administration'];
/** /**
* Route binder. Converts the key in the URL to the specified object (or throw 404). * Route binder. Converts the key in the URL to the specified object (or throw 404).

View File

@@ -69,7 +69,10 @@ class AppServiceProvider extends ServiceProvider
if ('' === $firstParam && str_contains($name, $route)) { if ('' === $firstParam && str_contains($name, $route)) {
return true; return true;
} }
$params = Route::getCurrentRoute()->parameters() ?? [];
/** @var null|array $params */
$params = Route::getCurrentRoute()->parameters();
$params ??= [];
$objectType = $params['objectType'] ?? ''; $objectType = $params['objectType'] ?? '';
if ($objectType === $firstParam && str_contains($name, $route)) { if ($objectType === $firstParam && str_contains($name, $route)) {
return true; return true;

View File

@@ -183,21 +183,21 @@ class BudgetRepository implements BudgetRepositoryInterface
// |-----------| // |-----------|
// |----------------| // |----------------|
if ($start->gte($limit->start_date) && $end->lte($limit->end_date)) { if ($start->gte($limit->start_date) && $end->lte($limit->end_date)) {
return (int) $start->diffInDays($end, true) + 1; // add one day return (int)$start->diffInDays($end, true) + 1; // add one day
} }
// limit starts earlier and limit ends first: // limit starts earlier and limit ends first:
// |-----------| // |-----------|
// |-------| // |-------|
if ($limit->start_date->lte($start) && $limit->end_date->lte($end)) { if ($limit->start_date->lte($start) && $limit->end_date->lte($end)) {
// return days in the range $start-$limit_end // return days in the range $start-$limit_end
return (int) $start->diffInDays($limit->end_date, true) + 1; // add one day, the day itself return (int)$start->diffInDays($limit->end_date, true) + 1; // add one day, the day itself
} }
// limit starts later and limit ends earlier // limit starts later and limit ends earlier
// |-----------| // |-----------|
// |-------| // |-------|
if ($limit->start_date->gte($start) && $limit->end_date->gte($end)) { if ($limit->start_date->gte($start) && $limit->end_date->gte($end)) {
// return days in the range $limit_start - $end // return days in the range $limit_start - $end
return (int) $limit->start_date->diffInDays($end, true) + 1; // add one day, the day itself return (int)$limit->start_date->diffInDays($end, true) + 1; // add one day, the day itself
} }
return 0; return 0;

View File

@@ -51,7 +51,7 @@ class OperationsRepository implements OperationsRepositoryInterface
$total = '0'; $total = '0';
$count = 0; $count = 0;
foreach ($budget->budgetlimits as $limit) { foreach ($budget->budgetlimits as $limit) {
$diff = (int) $limit->start_date->diffInDays($limit->end_date, true); $diff = (int)$limit->start_date->diffInDays($limit->end_date, true);
$diff = 0 === $diff ? 1 : $diff; $diff = 0 === $diff ? 1 : $diff;
$amount = $limit->amount; $amount = $limit->amount;
$perDay = bcdiv($amount, (string)$diff); $perDay = bcdiv($amount, (string)$diff);

View File

@@ -301,7 +301,7 @@ class PiggyBankRepository implements PiggyBankRepositoryInterface
if (null !== $piggyBank->targetdate && $repetition->currentamount < $piggyBank->targetamount) { if (null !== $piggyBank->targetdate && $repetition->currentamount < $piggyBank->targetamount) {
$now = today(config('app.timezone')); $now = today(config('app.timezone'));
$startDate = null !== $piggyBank->startdate && $piggyBank->startdate->gte($now) ? $piggyBank->startdate : $now; $startDate = null !== $piggyBank->startdate && $piggyBank->startdate->gte($now) ? $piggyBank->startdate : $now;
$diffInMonths = (int) $startDate->diffInMonths($piggyBank->targetdate); $diffInMonths = (int)$startDate->diffInMonths($piggyBank->targetdate);
$remainingAmount = bcsub($piggyBank->targetamount, $repetition->currentamount); $remainingAmount = bcsub($piggyBank->targetamount, $repetition->currentamount);
// more than 1 month to go and still need money to save: // more than 1 month to go and still need money to save:

View File

@@ -473,10 +473,10 @@ class RecurringRepository implements RecurringRepositoryInterface
if ('yearly' === $repetition->repetition_type) { if ('yearly' === $repetition->repetition_type) {
$today = today(config('app.timezone'))->endOfYear(); $today = today(config('app.timezone'))->endOfYear();
$repDate = Carbon::createFromFormat('Y-m-d', $repetition->repetition_moment); $repDate = Carbon::createFromFormat('Y-m-d', $repetition->repetition_moment);
if (false === $repDate) { if (null === $repDate) {
$repDate = clone $today; $repDate = clone $today;
} }
$diffInYears = (int) $today->diffInYears($repDate, true); $diffInYears = (int)$today->diffInYears($repDate, true);
$repDate->addYears($diffInYears); // technically not necessary. $repDate->addYears($diffInYears); // technically not necessary.
$string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js')); $string = $repDate->isoFormat((string)trans('config.month_and_day_no_year_js'));

View File

@@ -242,6 +242,30 @@ class UserRepository implements UserRepositoryInterface
return false; return false;
} }
#[\Override]
public function getUserGroups(User $user): Collection
{
$memberships = $user->groupMemberships()->get();
$set = [];
$collection = new Collection();
/** @var GroupMembership $membership */
foreach ($memberships as $membership) {
/** @var null|UserGroup $group */
$group = $membership->userGroup()->first();
if (null !== $group) {
$groupId = $group->id;
if (in_array($groupId, array_keys($set), true)) {
continue;
}
$set[$groupId] = $group;
}
}
$collection->push(...$set);
return $collection;
}
public function inviteUser(null|Authenticatable|User $user, string $email): InvitedUser public function inviteUser(null|Authenticatable|User $user, string $email): InvitedUser
{ {
$now = today(config('app.timezone')); $now = today(config('app.timezone'));

View File

@@ -94,6 +94,8 @@ interface UserRepositoryInterface
*/ */
public function getUserData(User $user): array; public function getUserData(User $user): array;
public function getUserGroups(User $user): Collection;
public function hasRole(null|Authenticatable|User $user, string $role): bool; public function hasRole(null|Authenticatable|User $user, string $role): bool;
public function inviteUser(null|Authenticatable|User $user, string $email): InvitedUser; public function inviteUser(null|Authenticatable|User $user, string $email): InvitedUser;

View File

@@ -106,8 +106,8 @@ class UserGroupRepository implements UserGroupRepositoryInterface
/** @var null|UserGroup $group */ /** @var null|UserGroup $group */
$group = $membership->userGroup()->first(); $group = $membership->userGroup()->first();
if (null !== $group) { if (null !== $group) {
$groupId = (int)$group->id; $groupId = $group->id;
if (in_array($groupId, $set, true)) { if (in_array($groupId, array_keys($set), true)) {
continue; continue;
} }
$set[$groupId] = $group; $set[$groupId] = $group;
@@ -288,4 +288,11 @@ class UserGroupRepository implements UserGroupRepositoryInterface
return $roles; return $roles;
} }
#[\Override]
public function useUserGroup(UserGroup $userGroup): void
{
$this->user->user_group_id = $userGroup->id;
$this->user->save();
}
} }

View File

@@ -47,4 +47,6 @@ interface UserGroupRepositoryInterface
public function update(UserGroup $userGroup, array $data): UserGroup; public function update(UserGroup $userGroup, array $data): UserGroup;
public function updateMembership(UserGroup $userGroup, array $data): UserGroup; public function updateMembership(UserGroup $userGroup, array $data): UserGroup;
public function useUserGroup(UserGroup $userGroup): void;
} }

View File

@@ -63,6 +63,8 @@ interface AccountRepositoryInterface
*/ */
public function getMetaValue(Account $account, string $field): ?string; public function getMetaValue(Account $account, string $field): ?string;
public function getUserGroup(): UserGroup;
/** /**
* Reset order types of the mentioned accounts. * Reset order types of the mentioned accounts.
*/ */

View File

@@ -0,0 +1,63 @@
<?php
/**
* IsTransferAccount.php
* Copyright (c) 2020 james@firefly-iii.org
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Rules;
use FireflyIII\Models\UserGroup;
use FireflyIII\Repositories\User\UserRepositoryInterface;
use FireflyIII\User;
use Illuminate\Contracts\Validation\ValidationRule;
/**
* Class IsDefaultUserGroupName
*/
class IsDefaultUserGroupName implements ValidationRule
{
private UserGroup $userGroup;
public function __construct(UserGroup $userGroup)
{
$this->userGroup = $userGroup;
}
/**
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function validate(string $attribute, mixed $value, \Closure $fail): void
{
app('log')->debug(sprintf('Now in %s(%s)', __METHOD__, $value));
// are you owner of this group and the name is the same? fail.
/** @var User $user */
$user = auth()->user();
/** @var UserRepositoryInterface $userRepos */
$userRepos = app(UserRepositoryInterface::class);
$roles = $userRepos->getRolesInGroup($user, $this->userGroup->id);
if ($this->userGroup->title === $user->email && in_array('owner', $roles, true)) {
$fail('validation.administration_owner_rename')->translate();
}
}
}

View File

@@ -117,7 +117,7 @@ class UpdateRequest implements UpdateRequestInterface
// parse response a bit. No message yet. // parse response a bit. No message yet.
$response = $json['firefly_iii'][$channel]; $response = $json['firefly_iii'][$channel];
$date = Carbon::createFromFormat('Y-m-d', $response['date']); $date = Carbon::createFromFormat('Y-m-d', $response['date']);
if (false === $date) { if (null === $date) {
$date = today(config('app.timezone')); $date = today(config('app.timezone'));
} }
$return['version'] = $response['version']; $return['version'] = $response['version'];

View File

@@ -54,7 +54,7 @@ class GroupCloneService
{ {
$newJournal = $journal->replicate(); $newJournal = $journal->replicate();
$newJournal->transaction_group_id = $newGroup->id; $newJournal->transaction_group_id = $newGroup->id;
$newJournal->date = today(config('app.timezone')); $newJournal->date = now();
$newJournal->save(); $newJournal->save();
foreach ($journal->transactions as $transaction) { foreach ($journal->transactions as $transaction) {

View File

@@ -187,7 +187,7 @@ class JournalUpdateService
// make new account validator. // make new account validator.
$expectedType = $this->getExpectedType(); $expectedType = $this->getExpectedType();
app('log')->debug(sprintf('Expected type (new or unchanged) is %s', $expectedType)); app('log')->debug(sprintf('(a) Expected type (new or unchanged) is %s', $expectedType));
// make a new validator. // make a new validator.
/** @var AccountValidator $validator */ /** @var AccountValidator $validator */
@@ -273,7 +273,7 @@ class JournalUpdateService
// make new account validator. // make new account validator.
$expectedType = $this->getExpectedType(); $expectedType = $this->getExpectedType();
app('log')->debug(sprintf('Expected type (new or unchanged) is %s', $expectedType)); app('log')->debug(sprintf('(b) Expected type (new or unchanged) is %s', $expectedType));
// make a new validator. // make a new validator.
/** @var AccountValidator $validator */ /** @var AccountValidator $validator */
@@ -404,7 +404,7 @@ class JournalUpdateService
// make new account validator. // make new account validator.
$expectedType = $this->getExpectedType(); $expectedType = $this->getExpectedType();
app('log')->debug(sprintf('Expected type (new or unchanged) is %s', $expectedType)); app('log')->debug(sprintf('(c) Expected type (new or unchanged) is %s', $expectedType));
try { try {
$result = $this->getAccount($expectedType, 'destination', $destInfo); $result = $this->getAccount($expectedType, 'destination', $destInfo);

View File

@@ -146,7 +146,7 @@ class RemoteUserGuard implements Guard
return $this->user?->id; return $this->user?->id;
} }
public function setUser(null|Authenticatable|User $user): void public function setUser(null|Authenticatable|User $user): void // @phpstan-ignore-line
{ {
app('log')->debug(sprintf('Now at %s', __METHOD__)); app('log')->debug(sprintf('Now at %s', __METHOD__));
if ($user instanceof User) { if ($user instanceof User) {

View File

@@ -36,6 +36,14 @@ use Illuminate\Contracts\Auth\UserProvider;
*/ */
class RemoteUserProvider implements UserProvider class RemoteUserProvider implements UserProvider
{ {
#[\Override]
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
throw new FireflyException(sprintf('Did not implement %s', __METHOD__));
}
/** /**
* @throws FireflyException * @throws FireflyException
* *
@@ -120,12 +128,4 @@ class RemoteUserProvider implements UserProvider
throw new FireflyException(sprintf('C) Did not implement %s', __METHOD__)); throw new FireflyException(sprintf('C) Did not implement %s', __METHOD__));
} }
#[\Override]
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void
{
app('log')->debug(sprintf('Now at %s', __METHOD__));
throw new FireflyException(sprintf('Did not implement %s', __METHOD__));
}
} }

View File

@@ -23,10 +23,12 @@ declare(strict_types=1);
namespace FireflyIII\Support\Http\Api; namespace FireflyIII\Support\Http\Api;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Enums\UserRoleEnum;
use FireflyIII\Models\GroupMembership; use FireflyIII\Models\GroupMembership;
use FireflyIII\Models\UserGroup; use FireflyIII\Models\UserGroup;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Http\Request; use Illuminate\Http\Request;
/** /**
@@ -35,37 +37,68 @@ use Illuminate\Http\Request;
trait ValidatesUserGroupTrait trait ValidatesUserGroupTrait
{ {
/** /**
* This check does not validate which rights the user has, that comes later. * @throws AuthorizationException
* * @throws AuthenticationException
* @throws FireflyException
*/ */
protected function validateUserGroup(Request $request): ?UserGroup protected function validateUserGroup(Request $request): UserGroup
{ {
app('log')->debug(sprintf('validateUserGroup: %s', static::class));
if (!auth()->check()) { if (!auth()->check()) {
app('log')->debug('validateUserGroup: user is not logged in, return NULL.'); app('log')->debug('validateUserGroup: user is not logged in, return NULL.');
return null; throw new AuthenticationException();
} }
/** @var User $user */ /** @var User $user */
$user = auth()->user(); $user = auth()->user();
$groupId = 0;
if (!$request->has('user_group_id')) { if (!$request->has('user_group_id')) {
$group = $user->userGroup; $groupId = $user->user_group_id;
app('log')->debug(sprintf('validateUserGroup: no user group submitted, return default group #%d.', $group?->id)); app('log')->debug(sprintf('validateUserGroup: no user group submitted, use default group #%d.', $groupId));
}
return $group; if ($request->has('user_group_id')) {
$groupId = (int)$request->get('user_group_id');
app('log')->debug(sprintf('validateUserGroup: user group submitted, search for memberships in group #%d.', $groupId));
} }
$groupId = (int)$request->get('user_group_id');
/** @var null|GroupMembership $membership */ /** @var null|GroupMembership $membership */
$membership = $user->groupMemberships()->where('user_group_id', $groupId)->first(); $membership = $user->groupMemberships()->where('user_group_id', $groupId)->first();
if (null === $membership) { if (null === $membership) {
app('log')->debug('validateUserGroup: user has no access to this group.'); app('log')->debug(sprintf('validateUserGroup: user has no access to group #%d.', $groupId));
throw new FireflyException((string)trans('validation.belongs_user_or_user_group')); throw new AuthorizationException((string)trans('validation.no_access_group'));
} }
app('log')->debug(sprintf('validateUserGroup: user has role "%s" in group #%d.', $membership->userRole->title, $membership->userGroup->id));
return $membership->userGroup; // need to get the group from the membership:
/** @var null|UserGroup $group */
$group = $membership->userGroup;
if (null === $group) {
app('log')->debug(sprintf('validateUserGroup: group #%d does not exist.', $groupId));
throw new AuthorizationException((string)trans('validation.belongs_user_or_user_group'));
}
app('log')->debug(sprintf('validateUserGroup: validate access of user to group #%d ("%s").', $groupId, $group->title));
$roles = property_exists($this, 'acceptedRoles') ? $this->acceptedRoles : [];
if (0 === count($roles)) {
app('log')->debug('validateUserGroup: no roles defined, so no access.');
throw new AuthorizationException((string)trans('validation.no_accepted_roles_defined'));
}
app('log')->debug(sprintf('validateUserGroup: have %d roles to check.', count($roles)), $roles);
/** @var UserRoleEnum $role */
foreach ($roles as $role) {
if ($user->hasRoleInGroupOrOwner($group, $role)) {
app('log')->debug(sprintf('validateUserGroup: User has role "%s" in group #%d, return the group.', $role->value, $groupId));
return $group;
}
app('log')->debug(sprintf('validateUserGroup: User does NOT have role "%s" in group #%d, continue searching.', $role->value, $groupId));
}
app('log')->debug('validateUserGroup: User does NOT have enough rights to access endpoint.');
throw new AuthorizationException((string)trans('validation.belongs_user_or_user_group'));
} }
} }

View File

@@ -46,7 +46,7 @@ trait DateCalculation
$difference = $today->diffInDays($end); $difference = $today->diffInDays($end);
} }
return (int) (0 === $difference ? 1 : $difference); return (int)(0 === $difference ? 1 : $difference);
} }
/** /**
@@ -63,7 +63,7 @@ trait DateCalculation
$difference = $start->diffInDays($today, true) + 1; $difference = $start->diffInDays($today, true) + 1;
} }
return (int) $difference; return (int)$difference;
} }
protected function calculateStep(Carbon $start, Carbon $end): string protected function calculateStep(Carbon $start, Carbon $end): string

View File

@@ -145,14 +145,14 @@ trait RequestInformation
$attributes['location'] ??= ''; $attributes['location'] ??= '';
$attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', new Route('get', '', [])); $attributes['accounts'] = AccountList::routeBinder($attributes['accounts'] ?? '', new Route('get', '', []));
$date = Carbon::createFromFormat('Ymd', $attributes['startDate']); $date = Carbon::createFromFormat('Ymd', $attributes['startDate']);
if (false === $date) { if (null === $date) {
$date = today(config('app.timezone')); $date = today(config('app.timezone'));
} }
$date->startOfMonth(); $date->startOfMonth();
$attributes['startDate'] = $date; $attributes['startDate'] = $date;
$date2 = Carbon::createFromFormat('Ymd', $attributes['endDate']); $date2 = Carbon::createFromFormat('Ymd', $attributes['endDate']);
if (false === $date2) { if (null === $date2) {
$date2 = today(config('app.timezone')); $date2 = today(config('app.timezone'));
} }
$date2->endOfDay(); $date2->endOfDay();

View File

@@ -188,7 +188,7 @@ class Navigation
Log::debug(sprintf('Function is ->%s()', $function)); Log::debug(sprintf('Function is ->%s()', $function));
if (array_key_exists($function, $parameterMap)) { if (array_key_exists($function, $parameterMap)) {
Log::debug(sprintf('Parameter map, function becomes ->%s(%s)', $function, implode(', ', $parameterMap[$function]))); Log::debug(sprintf('Parameter map, function becomes ->%s(%s)', $function, implode(', ', $parameterMap[$function])));
$date->{$function}($parameterMap[$function][0]); $date->{$function}($parameterMap[$function][0]); // @phpstan-ignore-line
Log::debug(sprintf('Result is "%s"', $date->toIso8601String())); Log::debug(sprintf('Result is "%s"', $date->toIso8601String()));
return $date; return $date;
@@ -274,7 +274,7 @@ class Navigation
/** @var Carbon $tEnd */ /** @var Carbon $tEnd */
$tEnd = session('end', today(config('app.timezone'))->endOfMonth()); $tEnd = session('end', today(config('app.timezone'))->endOfMonth());
$diffInDays = (int) $tStart->diffInDays($tEnd, true); $diffInDays = (int)$tStart->diffInDays($tEnd, true);
} }
Log::debug(sprintf('Diff in days is %d', $diffInDays)); Log::debug(sprintf('Diff in days is %d', $diffInDays));
$currentEnd->addDays($diffInDays); $currentEnd->addDays($diffInDays);
@@ -327,7 +327,7 @@ class Navigation
{ {
$endOfMonth = $date->copy()->endOfMonth(); $endOfMonth = $date->copy()->endOfMonth();
return (int) $date->diffInDays($endOfMonth, true); return (int)$date->diffInDays($endOfMonth, true);
} }
public function diffInPeriods(string $period, int $skip, Carbon $beginning, Carbon $end): int public function diffInPeriods(string $period, int $skip, Carbon $beginning, Carbon $end): int
@@ -677,7 +677,7 @@ class Navigation
/** @var Carbon $tEnd */ /** @var Carbon $tEnd */
$tEnd = session('end', today(config('app.timezone'))->endOfMonth()); $tEnd = session('end', today(config('app.timezone'))->endOfMonth());
$diffInDays = (int) $tStart->diffInDays($tEnd, true); $diffInDays = (int)$tStart->diffInDays($tEnd, true);
$date->subDays($diffInDays * $subtract); $date->subDays($diffInDays * $subtract);
return $date; return $date;

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Support; namespace FireflyIII\Support;
use Carbon\Carbon; use Carbon\Carbon;
use Carbon\CarbonInterface;
use Carbon\Exceptions\InvalidFormatException; use Carbon\Exceptions\InvalidFormatException;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use Illuminate\Support\Facades\Log; use Illuminate\Support\Facades\Log;
@@ -122,12 +123,12 @@ class ParseDateString
{ {
$today = today(config('app.timezone'))->startOfDay(); $today = today(config('app.timezone'))->startOfDay();
return match ($keyword) { return match ($keyword) { // @phpstan-ignore-line
default => $today, default => $today,
'yesterday' => $today->subDay(), 'yesterday' => $today->subDay(),
'tomorrow' => $today->addDay(), 'tomorrow' => $today->addDay(),
'start of this week' => $today->startOfWeek(Carbon::MONDAY), 'start of this week' => $today->startOfWeek(CarbonInterface::MONDAY),
'end of this week' => $today->endOfWeek(Carbon::SUNDAY), 'end of this week' => $today->endOfWeek(CarbonInterface::SUNDAY),
'start of this month' => $today->startOfMonth(), 'start of this month' => $today->startOfMonth(),
'end of this month' => $today->endOfMonth(), 'end of this month' => $today->endOfMonth(),
'start of this quarter' => $today->startOfQuarter(), 'start of this quarter' => $today->startOfQuarter(),

View File

@@ -26,7 +26,10 @@ namespace FireflyIII\Support;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Models\Preference; use FireflyIII\Models\Preference;
use FireflyIII\User; use FireflyIII\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Session;
/** /**
* Class Preferences. * Class Preferences.
@@ -40,20 +43,17 @@ class Preferences
return new Collection(); return new Collection();
} }
return Preference::where('user_id', $user->id)->get(); return Preference::where('user_id', $user->id)
->where(function (Builder $q) use ($user): void {
$q->whereNull('user_group_id');
$q->orWhere('user_group_id', $user->user_group_id);
})
->get()
;
} }
/** public function get(string $name, null|array|bool|int|string $default = null): ?Preference
* @param mixed $default
*
* @throws FireflyException
*/
public function get(string $name, $default = null): ?Preference
{ {
if ('currencyPreference' === $name) {
throw new FireflyException('No longer supports "currencyPreference", please refactor me.');
}
/** @var null|User $user */ /** @var null|User $user */
$user = auth()->user(); $user = auth()->user();
if (null === $user) { if (null === $user) {
@@ -66,15 +66,12 @@ class Preferences
return $this->getForUser($user, $name, $default); return $this->getForUser($user, $name, $default);
} }
/**
* @throws FireflyException
*/
public function getForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference public function getForUser(User $user, string $name, null|array|bool|int|string $default = null): ?Preference
{ {
if ('currencyPreference' === $name) { // don't care about user group ID, except for some specific preferences.
throw new FireflyException('No longer supports "currencyPreference", please refactor me.'); $userGroupId = $this->getUserGroupId($user, $name);
} $preference = Preference::where('user_group_id', $userGroupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']);
$preference = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'user_id', 'name', 'data', 'updated_at', 'created_at']);
if (null !== $preference && null === $preference->data) { if (null !== $preference && null === $preference->data) {
$preference->delete(); $preference->delete();
$preference = null; $preference = null;
@@ -92,17 +89,22 @@ class Preferences
return $this->setForUser($user, $name, $default); return $this->setForUser($user, $name, $default);
} }
/** private function getUserGroupId(User $user, string $preferenceName): ?int
* @throws FireflyException {
*/ $groupId = null;
$items = config('firefly.admin_specific_prefs') ?? [];
if (in_array($preferenceName, $items, true)) {
$groupId = (int)$user->user_group_id;
}
return $groupId;
}
public function delete(string $name): bool public function delete(string $name): bool
{ {
if ('currencyPreference' === $name) {
throw new FireflyException('No longer supports "currencyPreference", please refactor me.');
}
$fullName = sprintf('preference%s%s', auth()->user()->id, $name); $fullName = sprintf('preference%s%s', auth()->user()->id, $name);
if (\Cache::has($fullName)) { if (Cache::has($fullName)) {
\Cache::forget($fullName); Cache::forget($fullName);
} }
Preference::where('user_id', auth()->user()->id)->where('name', $name)->delete(); Preference::where('user_id', auth()->user()->id)->where('name', $name)->delete();
@@ -111,29 +113,19 @@ class Preferences
public function forget(User $user, string $name): void public function forget(User $user, string $name): void
{ {
if ('currencyPreference' === $name) {
throw new FireflyException('No longer supports "currencyPreference", please refactor me.');
}
$key = sprintf('preference%s%s', $user->id, $name); $key = sprintf('preference%s%s', $user->id, $name);
\Cache::forget($key); Cache::forget($key);
\Cache::put($key, '', 5); Cache::put($key, '', 5);
} }
/** public function setForUser(User $user, string $name, null|array|bool|int|string $value): Preference
* @param mixed $value
*
* @throws FireflyException
*/
public function setForUser(User $user, string $name, $value): Preference
{ {
if ('currencyPreference' === $name) {
throw new FireflyException('No longer supports "currencyPreference", please refactor me.');
}
$fullName = sprintf('preference%s%s', $user->id, $name); $fullName = sprintf('preference%s%s', $user->id, $name);
\Cache::forget($fullName); $groupId = $this->getUserGroupId($user, $name);
Cache::forget($fullName);
/** @var null|Preference $pref */ /** @var null|Preference $pref */
$pref = Preference::where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']); $pref = Preference::where('user_group_id', $groupId)->where('user_id', $user->id)->where('name', $name)->first(['id', 'name', 'data', 'updated_at', 'created_at']);
if (null !== $pref && null === $value) { if (null !== $pref && null === $value) {
$pref->delete(); $pref->delete();
@@ -144,18 +136,14 @@ class Preferences
return new Preference(); return new Preference();
} }
if (null === $pref) { if (null === $pref) {
$pref = new Preference(); $pref = new Preference();
$pref->user_id = (int)$user->id; $pref->user_id = (int)$user->id;
$pref->name = $name; $pref->user_group_id = $groupId;
$pref->name = $name;
} }
$pref->data = $value; $pref->data = $value;
$pref->save();
try { Cache::forever($fullName, $pref);
$pref->save();
} catch (\PDOException $e) {
throw new FireflyException(sprintf('Could not save preference: %s', $e->getMessage()), 0, $e);
}
\Cache::forever($fullName, $pref);
return $pref; return $pref;
} }
@@ -165,19 +153,25 @@ class Preferences
return Preference::where('user_id', $user->id)->where('name', 'LIKE', $search.'%')->get(); return Preference::where('user_id', $user->id)->where('name', 'LIKE', $search.'%')->get();
} }
/**
* Find by name, has no user ID in it, because the method is called from an unauthenticated route any way.
*/
public function findByName(string $name): Collection public function findByName(string $name): Collection
{ {
if ('currencyPreference' === $name) {
throw new FireflyException('No longer supports "currencyPreference", please refactor me.');
}
return Preference::where('name', $name)->get(); return Preference::where('name', $name)->get();
} }
public function getArrayForUser(User $user, array $list): array public function getArrayForUser(User $user, array $list): array
{ {
$result = []; $result = [];
$preferences = Preference::where('user_id', $user->id)->whereIn('name', $list)->get(['id', 'name', 'data']); $preferences = Preference::where('user_id', $user->id)
->where(function (Builder $q) use ($user): void {
$q->whereNull('user_group_id');
$q->orWhere('user_group_id', $user->user_group_id);
})
->whereIn('name', $list)
->get(['id', 'name', 'data'])
;
/** @var Preference $preference */ /** @var Preference $preference */
foreach ($preferences as $preference) { foreach ($preferences as $preference) {
@@ -192,17 +186,8 @@ class Preferences
return $result; return $result;
} }
/** public function getFresh(string $name, null|array|bool|int|string $default = null): ?Preference
* @param mixed $default
*
* @throws FireflyException
*/
public function getFresh(string $name, $default = null): ?Preference
{ {
if ('currencyPreference' === $name) {
throw new FireflyException('No longer supports "currencyPreference", please refactor me.');
}
/** @var null|User $user */ /** @var null|User $user */
$user = auth()->user(); $user = auth()->user();
if (null === $user) { if (null === $user) {
@@ -212,22 +197,6 @@ class Preferences
return $preference; return $preference;
} }
return $this->getFreshForUser($user, $name, $default);
}
/**
* TODO remove me.
*
* @param null $default
*
* @throws FireflyException
*/
public function getFreshForUser(User $user, string $name, $default = null): ?Preference
{
if ('currencyPreference' === $name) {
throw new FireflyException('No longer supports "currencyPreference", please refactor me.');
}
return $this->getForUser($user, $name, $default); return $this->getForUser($user, $name, $default);
} }
@@ -252,19 +221,12 @@ class Preferences
public function mark(): void public function mark(): void
{ {
$this->set('lastActivity', microtime()); $this->set('lastActivity', microtime());
\Session::forget('first'); Session::forget('first');
} }
/** public function set(string $name, null|array|bool|int|string $value): Preference
* @param mixed $value
*
* @throws FireflyException
*/
public function set(string $name, $value): Preference
{ {
if ('currencyPreference' === $name) { /** @var null|User $user */
throw new FireflyException('No longer supports "currencyPreference", please refactor me.');
}
$user = auth()->user(); $user = auth()->user();
if (null === $user) { if (null === $user) {
// make new preference, return it: // make new preference, return it:
@@ -275,6 +237,6 @@ class Preferences
return $pref; return $pref;
} }
return $this->setForUser(auth()->user(), $name, $value); return $this->setForUser($user, $name, $value);
} }
} }

View File

@@ -250,7 +250,7 @@ trait ConvertsDataTypes
return null; return null;
} }
if (false === $carbon) { if (null === $carbon) {
app('log')->error(sprintf('[2] "%s" is of an invalid format.', $value)); app('log')->error(sprintf('[2] "%s" is of an invalid format.', $value));
return null; return null;

View File

@@ -29,7 +29,7 @@ use Symfony\Component\ExpressionLanguage\SyntaxError;
class ActionExpression class ActionExpression
{ {
private static array $NAMES private static array $NAMES
= [ = [
// 'transaction_group_id', // 'transaction_group_id',
// 'user_id', // 'user_id',

View File

@@ -185,7 +185,7 @@ class AccountTransformer extends AbstractTransformer
// try classic date: // try classic date:
if (10 === strlen($monthlyPaymentDate)) { if (10 === strlen($monthlyPaymentDate)) {
$object = Carbon::createFromFormat('!Y-m-d', $monthlyPaymentDate, config('app.timezone')); $object = Carbon::createFromFormat('!Y-m-d', $monthlyPaymentDate, config('app.timezone'));
if (false === $object) { if (null === $object) {
$object = today(config('app.timezone')); $object = today(config('app.timezone'));
} }
$monthlyPaymentDate = $object->toAtomString(); $monthlyPaymentDate = $object->toAtomString();
@@ -212,7 +212,7 @@ class AccountTransformer extends AbstractTransformer
} }
if (null !== $openingBalanceDate) { if (null !== $openingBalanceDate) {
$object = Carbon::createFromFormat('Y-m-d H:i:s', $openingBalanceDate, config('app.timezone')); $object = Carbon::createFromFormat('Y-m-d H:i:s', $openingBalanceDate, config('app.timezone'));
if (false === $object) { if (null === $object) {
$object = today(config('app.timezone')); $object = today(config('app.timezone'));
} }
$openingBalanceDate = $object->toAtomString(); $openingBalanceDate = $object->toAtomString();

View File

@@ -82,7 +82,7 @@ class BillTransformer extends AbstractTransformer
$payDatesFormatted = []; $payDatesFormatted = [];
foreach ($paidData as $object) { foreach ($paidData as $object) {
$date = Carbon::createFromFormat('!Y-m-d', $object['date'], config('app.timezone')); $date = Carbon::createFromFormat('!Y-m-d', $object['date'], config('app.timezone'));
if (false === $date) { if (null === $date) {
$date = today(config('app.timezone')); $date = today(config('app.timezone'));
} }
$object['date'] = $date->toAtomString(); $object['date'] = $date->toAtomString();
@@ -91,7 +91,7 @@ class BillTransformer extends AbstractTransformer
foreach ($payDates as $string) { foreach ($payDates as $string) {
$date = Carbon::createFromFormat('!Y-m-d', $string, config('app.timezone')); $date = Carbon::createFromFormat('!Y-m-d', $string, config('app.timezone'));
if (false === $date) { if (null === $date) {
$date = today(config('app.timezone')); $date = today(config('app.timezone'));
} }
$payDatesFormatted[] = $date->toAtomString(); $payDatesFormatted[] = $date->toAtomString();
@@ -104,7 +104,7 @@ class BillTransformer extends AbstractTransformer
if (null !== $firstPayDate) { if (null !== $firstPayDate) {
$nemDate = Carbon::createFromFormat('!Y-m-d', $firstPayDate, config('app.timezone')); $nemDate = Carbon::createFromFormat('!Y-m-d', $firstPayDate, config('app.timezone'));
if (false === $nemDate) { if (null === $nemDate) {
$nemDate = today(config('app.timezone')); $nemDate = today(config('app.timezone'));
} }
$nem = $nemDate->toAtomString(); $nem = $nemDate->toAtomString();
@@ -129,7 +129,7 @@ class BillTransformer extends AbstractTransformer
$current = $payDatesFormatted[0] ?? null; $current = $payDatesFormatted[0] ?? null;
if (null !== $current && !$nemDate->isToday()) { if (null !== $current && !$nemDate->isToday()) {
$temp2 = Carbon::createFromFormat('Y-m-d\TH:i:sP', $current); $temp2 = Carbon::createFromFormat('Y-m-d\TH:i:sP', $current);
if (false === $temp2) { if (null === $temp2) {
$temp2 = today(config('app.timezone')); $temp2 = today(config('app.timezone'));
} }
$nemDiff = trans('firefly.bill_expected_date', ['date' => $temp2->diffForHumans(today(config('app.timezone')), CarbonInterface::DIFF_RELATIVE_TO_NOW)]); $nemDiff = trans('firefly.bill_expected_date', ['date' => $temp2->diffForHumans(today(config('app.timezone')), CarbonInterface::DIFF_RELATIVE_TO_NOW)]);

View File

@@ -35,12 +35,15 @@ class PreferenceTransformer extends AbstractTransformer
*/ */
public function transform(Preference $preference): array public function transform(Preference $preference): array
{ {
$userGroupId = 0 === $preference->user_group_id ? null : $preference->user_group_id;
return [ return [
'id' => $preference->id, 'id' => $preference->id,
'created_at' => $preference->created_at->toAtomString(), 'created_at' => $preference->created_at->toAtomString(),
'updated_at' => $preference->updated_at->toAtomString(), 'updated_at' => $preference->updated_at->toAtomString(),
'name' => $preference->name, 'user_group_id' => $userGroupId,
'data' => $preference->data, 'name' => $preference->name,
'data' => $preference->data,
]; ];
} }
} }

View File

@@ -248,7 +248,7 @@ class PiggyBankTransformer extends AbstractTransformer
if (bccomp($currentAmount, $targetAmount) < 1) { if (bccomp($currentAmount, $targetAmount) < 1) {
$now = today(config('app.timezone')); $now = today(config('app.timezone'));
$startDate = null !== $startDate && $startDate->gte($now) ? $startDate : $now; $startDate = null !== $startDate && $startDate->gte($now) ? $startDate : $now;
$diffInMonths = (int) $startDate->diffInMonths($targetDate); $diffInMonths = (int)$startDate->diffInMonths($targetDate);
$remainingAmount = bcsub($targetAmount, $currentAmount); $remainingAmount = bcsub($targetAmount, $currentAmount);
// more than 1 month to go and still need money to save: // more than 1 month to go and still need money to save:

View File

@@ -462,7 +462,7 @@ class TransactionGroupTransformer extends AbstractTransformer
// app('log')->debug(sprintf('Now in date("%s")', $string)); // app('log')->debug(sprintf('Now in date("%s")', $string));
if (10 === strlen($string)) { if (10 === strlen($string)) {
$res = Carbon::createFromFormat('Y-m-d', $string, config('app.timezone')); $res = Carbon::createFromFormat('Y-m-d', $string, config('app.timezone'));
if (false === $res) { if (null === $res) {
return null; return null;
} }
@@ -473,7 +473,7 @@ class TransactionGroupTransformer extends AbstractTransformer
} }
if (19 === strlen($string) && str_contains($string, 'T')) { if (19 === strlen($string) && str_contains($string, 'T')) {
$res = Carbon::createFromFormat('Y-m-d\TH:i:s', substr($string, 0, 19), config('app.timezone')); $res = Carbon::createFromFormat('Y-m-d\TH:i:s', substr($string, 0, 19), config('app.timezone'));
if (false === $res) { if (null === $res) {
return null; return null;
} }
@@ -482,7 +482,7 @@ class TransactionGroupTransformer extends AbstractTransformer
// 2022-01-01 01:01:01 // 2022-01-01 01:01:01
$res = Carbon::createFromFormat('Y-m-d H:i:s', substr($string, 0, 19), config('app.timezone')); $res = Carbon::createFromFormat('Y-m-d H:i:s', substr($string, 0, 19), config('app.timezone'));
if (false === $res) { if (null === $res) {
return null; return null;
} }

View File

@@ -35,9 +35,9 @@ use Illuminate\Support\Collection;
*/ */
class UserGroupTransformer extends AbstractTransformer class UserGroupTransformer extends AbstractTransformer
{ {
private array $inUse;
private array $memberships; private array $memberships;
private array $membershipsVisible; private array $membershipsVisible;
private array $inUse;
public function __construct() public function __construct()
{ {

View File

@@ -3,6 +3,30 @@
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/). This project adheres to [Semantic Versioning](http://semver.org/).
## 6.1.14 - 2024-xx-xx
### Changed
- You will have to define again which asset accounts you want to see on the dashboard. Sorry about that.
## 6.1.13 - 2024-04-01
### Added
- sha256 checksums for the release files
- git HEAD added to the release files for easier validation
### Changed
- Updated pages in the `v2`-layout
### Fixed
- [Issue 8648](https://github.com/firefly-iii/firefly-iii/issues/8648) (Crashes during initial setup with PG 16 dbs) reported by @Lysholm
- [Issue 8725](https://github.com/firefly-iii/firefly-iii/issues/8725) (API: Call to `api/v1/bills` without arguments fails) reported by @dreautall
- [Issue 8732](https://github.com/firefly-iii/firefly-iii/issues/8732) (Error "Division by zero" when opening the "Budget" section) reported by @mrResident
- [PR 8735](https://github.com/firefly-iii/firefly-iii/pull/8735) (Fix `Division error by zero` in budget views) reported by @mansuf
## 6.1.12 - 2024-03-21 ## 6.1.12 - 2024-03-21
### Fixed ### Fixed

327
composer.lock generated
View File

@@ -1670,16 +1670,16 @@
}, },
{ {
"name": "laravel/framework", "name": "laravel/framework",
"version": "v11.1.1", "version": "v11.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/laravel/framework.git", "url": "https://github.com/laravel/framework.git",
"reference": "1437cea6d2b04cbc83743fbb208e1a01efccd9ec" "reference": "a1750156b671f37cba702380107e2d22161c31e3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/1437cea6d2b04cbc83743fbb208e1a01efccd9ec", "url": "https://api.github.com/repos/laravel/framework/zipball/a1750156b671f37cba702380107e2d22161c31e3",
"reference": "1437cea6d2b04cbc83743fbb208e1a01efccd9ec", "reference": "a1750156b671f37cba702380107e2d22161c31e3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1871,7 +1871,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2024-03-28T15:07:18+00:00" "time": "2024-04-02T14:01:33+00:00"
}, },
{ {
"name": "laravel/passport", "name": "laravel/passport",
@@ -2728,16 +2728,16 @@
}, },
{ {
"name": "league/flysystem", "name": "league/flysystem",
"version": "3.26.0", "version": "3.27.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/thephpleague/flysystem.git", "url": "https://github.com/thephpleague/flysystem.git",
"reference": "072735c56cc0da00e10716dd90d5a7f7b40b36be" "reference": "4729745b1ab737908c7d055148c9a6b3e959832f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/072735c56cc0da00e10716dd90d5a7f7b40b36be", "url": "https://api.github.com/repos/thephpleague/flysystem/zipball/4729745b1ab737908c7d055148c9a6b3e959832f",
"reference": "072735c56cc0da00e10716dd90d5a7f7b40b36be", "reference": "4729745b1ab737908c7d055148c9a6b3e959832f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2802,7 +2802,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/thephpleague/flysystem/issues", "issues": "https://github.com/thephpleague/flysystem/issues",
"source": "https://github.com/thephpleague/flysystem/tree/3.26.0" "source": "https://github.com/thephpleague/flysystem/tree/3.27.0"
}, },
"funding": [ "funding": [
{ {
@@ -2814,7 +2814,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-03-25T11:49:53+00:00" "time": "2024-04-07T19:17:50+00:00"
}, },
{ {
"name": "league/flysystem-local", "name": "league/flysystem-local",
@@ -3366,16 +3366,16 @@
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
"version": "3.2.3", "version": "3.2.4",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/briannesbitt/Carbon.git", "url": "https://github.com/briannesbitt/Carbon.git",
"reference": "4d599a6e2351d6b6bf21737accdfe1a4ce3fdbb1" "reference": "82c28278c1c8f7b82dcdab25692237f052ffc8d8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/4d599a6e2351d6b6bf21737accdfe1a4ce3fdbb1", "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/82c28278c1c8f7b82dcdab25692237f052ffc8d8",
"reference": "4d599a6e2351d6b6bf21737accdfe1a4ce3fdbb1", "reference": "82c28278c1c8f7b82dcdab25692237f052ffc8d8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3468,7 +3468,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-03-30T18:22:00+00:00" "time": "2024-04-05T09:58:10+00:00"
}, },
{ {
"name": "nette/schema", "name": "nette/schema",
@@ -5481,16 +5481,16 @@
}, },
{ {
"name": "spatie/laravel-ignition", "name": "spatie/laravel-ignition",
"version": "2.5.0", "version": "2.5.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/spatie/laravel-ignition.git", "url": "https://github.com/spatie/laravel-ignition.git",
"reference": "e23f4e8ce6644dc3d68b9d8a0aed3beaca0d6ada" "reference": "0c864b3cbd66ce67a2096c5f743e07ce8f1d6ab9"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/e23f4e8ce6644dc3d68b9d8a0aed3beaca0d6ada", "url": "https://api.github.com/repos/spatie/laravel-ignition/zipball/0c864b3cbd66ce67a2096c5f743e07ce8f1d6ab9",
"reference": "e23f4e8ce6644dc3d68b9d8a0aed3beaca0d6ada", "reference": "0c864b3cbd66ce67a2096c5f743e07ce8f1d6ab9",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5569,7 +5569,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-03-29T14:14:55+00:00" "time": "2024-04-02T06:30:22+00:00"
}, },
{ {
"name": "spatie/period", "name": "spatie/period",
@@ -5627,16 +5627,16 @@
}, },
{ {
"name": "symfony/cache", "name": "symfony/cache",
"version": "v7.0.4", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/cache.git", "url": "https://github.com/symfony/cache.git",
"reference": "fc822951dd360a593224bb2cef90a087d0dff60f" "reference": "2d0d3f92c74c445410d05374908b03e0a1131e2b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/cache/zipball/fc822951dd360a593224bb2cef90a087d0dff60f", "url": "https://api.github.com/repos/symfony/cache/zipball/2d0d3f92c74c445410d05374908b03e0a1131e2b",
"reference": "fc822951dd360a593224bb2cef90a087d0dff60f", "reference": "2d0d3f92c74c445410d05374908b03e0a1131e2b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5703,7 +5703,7 @@
"psr6" "psr6"
], ],
"support": { "support": {
"source": "https://github.com/symfony/cache/tree/v7.0.4" "source": "https://github.com/symfony/cache/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -5719,20 +5719,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-22T20:27:20+00:00" "time": "2024-03-27T19:55:25+00:00"
}, },
{ {
"name": "symfony/cache-contracts", "name": "symfony/cache-contracts",
"version": "v3.4.0", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/cache-contracts.git", "url": "https://github.com/symfony/cache-contracts.git",
"reference": "1d74b127da04ffa87aa940abe15446fa89653778" "reference": "2c9db6509a1b21dad229606897639d3284f54b2a"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/cache-contracts/zipball/1d74b127da04ffa87aa940abe15446fa89653778", "url": "https://api.github.com/repos/symfony/cache-contracts/zipball/2c9db6509a1b21dad229606897639d3284f54b2a",
"reference": "1d74b127da04ffa87aa940abe15446fa89653778", "reference": "2c9db6509a1b21dad229606897639d3284f54b2a",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5779,7 +5779,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/cache-contracts/tree/v3.4.0" "source": "https://github.com/symfony/cache-contracts/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@@ -5795,7 +5795,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-09-25T12:52:38+00:00" "time": "2024-01-23T14:51:35+00:00"
}, },
{ {
"name": "symfony/clock", "name": "symfony/clock",
@@ -5873,16 +5873,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v7.0.4", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f" "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/6b099f3306f7c9c2d2786ed736d0026b2903205f", "url": "https://api.github.com/repos/symfony/console/zipball/fde915cd8e7eb99b3d531d3d5c09531429c3f9e5",
"reference": "6b099f3306f7c9c2d2786ed736d0026b2903205f", "reference": "fde915cd8e7eb99b3d531d3d5c09531429c3f9e5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5946,7 +5946,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v7.0.4" "source": "https://github.com/symfony/console/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -5962,7 +5962,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-22T20:27:20+00:00" "time": "2024-04-01T11:04:53+00:00"
}, },
{ {
"name": "symfony/css-selector", "name": "symfony/css-selector",
@@ -6098,16 +6098,16 @@
}, },
{ {
"name": "symfony/error-handler", "name": "symfony/error-handler",
"version": "v7.0.4", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/error-handler.git", "url": "https://github.com/symfony/error-handler.git",
"reference": "677b24759decff69e65b1e9d1471d90f95ced880" "reference": "46a4cc138f799886d4bd70477c55c699d3e9dfc8"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/error-handler/zipball/677b24759decff69e65b1e9d1471d90f95ced880", "url": "https://api.github.com/repos/symfony/error-handler/zipball/46a4cc138f799886d4bd70477c55c699d3e9dfc8",
"reference": "677b24759decff69e65b1e9d1471d90f95ced880", "reference": "46a4cc138f799886d4bd70477c55c699d3e9dfc8",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6153,7 +6153,7 @@
"description": "Provides tools to manage errors and ease debugging PHP code", "description": "Provides tools to manage errors and ease debugging PHP code",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/error-handler/tree/v7.0.4" "source": "https://github.com/symfony/error-handler/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -6169,7 +6169,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-22T20:27:20+00:00" "time": "2024-03-19T11:57:22+00:00"
}, },
{ {
"name": "symfony/event-dispatcher", "name": "symfony/event-dispatcher",
@@ -6253,16 +6253,16 @@
}, },
{ {
"name": "symfony/event-dispatcher-contracts", "name": "symfony/event-dispatcher-contracts",
"version": "v3.4.0", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/event-dispatcher-contracts.git", "url": "https://github.com/symfony/event-dispatcher-contracts.git",
"reference": "a76aed96a42d2b521153fb382d418e30d18b59df" "reference": "4e64b49bf370ade88e567de29465762e316e4224"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/a76aed96a42d2b521153fb382d418e30d18b59df", "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/4e64b49bf370ade88e567de29465762e316e4224",
"reference": "a76aed96a42d2b521153fb382d418e30d18b59df", "reference": "4e64b49bf370ade88e567de29465762e316e4224",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6309,7 +6309,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.0" "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@@ -6325,7 +6325,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-05-23T14:45:45+00:00" "time": "2024-01-23T14:51:35+00:00"
}, },
{ {
"name": "symfony/expression-language", "name": "symfony/expression-language",
@@ -6456,22 +6456,22 @@
}, },
{ {
"name": "symfony/http-client", "name": "symfony/http-client",
"version": "v7.0.5", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-client.git", "url": "https://github.com/symfony/http-client.git",
"reference": "425f462a59d8030703ee04a9e1c666575ed5db3b" "reference": "6e70473909f46fe5dd3b994a0f1b20ecb6b2f858"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/425f462a59d8030703ee04a9e1c666575ed5db3b", "url": "https://api.github.com/repos/symfony/http-client/zipball/6e70473909f46fe5dd3b994a0f1b20ecb6b2f858",
"reference": "425f462a59d8030703ee04a9e1c666575ed5db3b", "reference": "6e70473909f46fe5dd3b994a0f1b20ecb6b2f858",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.2", "php": ">=8.2",
"psr/log": "^1|^2|^3", "psr/log": "^1|^2|^3",
"symfony/http-client-contracts": "^3", "symfony/http-client-contracts": "^3.4.1",
"symfony/service-contracts": "^2.5|^3" "symfony/service-contracts": "^2.5|^3"
}, },
"conflict": { "conflict": {
@@ -6489,7 +6489,7 @@
"amphp/http-client": "^4.2.1", "amphp/http-client": "^4.2.1",
"amphp/http-tunnel": "^1.0", "amphp/http-tunnel": "^1.0",
"amphp/socket": "^1.1", "amphp/socket": "^1.1",
"guzzlehttp/promises": "^1.4", "guzzlehttp/promises": "^1.4|^2.0",
"nyholm/psr7": "^1.0", "nyholm/psr7": "^1.0",
"php-http/httplug": "^1.0|^2.0", "php-http/httplug": "^1.0|^2.0",
"psr/http-client": "^1.0", "psr/http-client": "^1.0",
@@ -6528,7 +6528,7 @@
"http" "http"
], ],
"support": { "support": {
"source": "https://github.com/symfony/http-client/tree/v7.0.5" "source": "https://github.com/symfony/http-client/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -6544,20 +6544,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-03-02T12:46:12+00:00" "time": "2024-04-01T20:49:44+00:00"
}, },
{ {
"name": "symfony/http-client-contracts", "name": "symfony/http-client-contracts",
"version": "v3.4.0", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-client-contracts.git", "url": "https://github.com/symfony/http-client-contracts.git",
"reference": "1ee70e699b41909c209a0c930f11034b93578654" "reference": "b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/1ee70e699b41909c209a0c930f11034b93578654", "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e",
"reference": "1ee70e699b41909c209a0c930f11034b93578654", "reference": "b6b5c876b3a4ed74460e2c5ac53bbce2f12e2a7e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6606,7 +6606,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/http-client-contracts/tree/v3.4.0" "source": "https://github.com/symfony/http-client-contracts/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@@ -6622,20 +6622,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-07-30T20:28:31+00:00" "time": "2024-04-01T18:51:09+00:00"
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v7.0.4", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "439fdfdd344943254b1ef6278613e79040548045" "reference": "8789625dcf36e5fbf753014678a1e090f1bc759c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/439fdfdd344943254b1ef6278613e79040548045", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8789625dcf36e5fbf753014678a1e090f1bc759c",
"reference": "439fdfdd344943254b1ef6278613e79040548045", "reference": "8789625dcf36e5fbf753014678a1e090f1bc759c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6683,7 +6683,7 @@
"description": "Defines an object-oriented layer for the HTTP specification", "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.0.4" "source": "https://github.com/symfony/http-foundation/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -6699,20 +6699,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-08T19:22:56+00:00" "time": "2024-03-19T11:46:48+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v7.0.5", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "37c24ca28f65e3121a68f3dd4daeb36fb1fa2a72" "reference": "34c872391046d59af804af62d4573b829cfe4824"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/37c24ca28f65e3121a68f3dd4daeb36fb1fa2a72", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/34c872391046d59af804af62d4573b829cfe4824",
"reference": "37c24ca28f65e3121a68f3dd4daeb36fb1fa2a72", "reference": "34c872391046d59af804af62d4573b829cfe4824",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6795,7 +6795,7 @@
"description": "Provides a structured process for converting a Request into a Response", "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-kernel/tree/v7.0.5" "source": "https://github.com/symfony/http-kernel/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -6811,20 +6811,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-03-04T21:05:24+00:00" "time": "2024-04-03T06:12:25+00:00"
}, },
{ {
"name": "symfony/mailer", "name": "symfony/mailer",
"version": "v7.0.4", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mailer.git", "url": "https://github.com/symfony/mailer.git",
"reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85" "reference": "eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mailer/zipball/72e16d87bf50a3ce195b9470c06bb9d7b816ea85", "url": "https://api.github.com/repos/symfony/mailer/zipball/eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0",
"reference": "72e16d87bf50a3ce195b9470c06bb9d7b816ea85", "reference": "eb0c3187c7ddfde12d8aa0e1fa5fb29e730a41e0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6875,7 +6875,7 @@
"description": "Helps sending emails", "description": "Helps sending emails",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/mailer/tree/v7.0.4" "source": "https://github.com/symfony/mailer/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -6891,7 +6891,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-03T21:34:19+00:00" "time": "2024-03-28T09:20:36+00:00"
}, },
{ {
"name": "symfony/mailgun-mailer", "name": "symfony/mailgun-mailer",
@@ -6964,16 +6964,16 @@
}, },
{ {
"name": "symfony/mime", "name": "symfony/mime",
"version": "v7.0.3", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mime.git", "url": "https://github.com/symfony/mime.git",
"reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716" "reference": "99362408c9abdf8c7cadcf0529b6fc8b16f5ace2"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716", "url": "https://api.github.com/repos/symfony/mime/zipball/99362408c9abdf8c7cadcf0529b6fc8b16f5ace2",
"reference": "c1ffe24ba6fdc3e3f0f3fcb93519103b326a3716", "reference": "99362408c9abdf8c7cadcf0529b6fc8b16f5ace2",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -6993,6 +6993,7 @@
"league/html-to-markdown": "^5.0", "league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
"symfony/dependency-injection": "^6.4|^7.0", "symfony/dependency-injection": "^6.4|^7.0",
"symfony/process": "^6.4|^7.0",
"symfony/property-access": "^6.4|^7.0", "symfony/property-access": "^6.4|^7.0",
"symfony/property-info": "^6.4|^7.0", "symfony/property-info": "^6.4|^7.0",
"symfony/serializer": "^6.4|^7.0" "symfony/serializer": "^6.4|^7.0"
@@ -7027,7 +7028,7 @@
"mime-type" "mime-type"
], ],
"support": { "support": {
"source": "https://github.com/symfony/mime/tree/v7.0.3" "source": "https://github.com/symfony/mime/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -7043,7 +7044,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-30T08:34:29+00:00" "time": "2024-03-21T19:37:36+00:00"
}, },
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
@@ -7819,16 +7820,16 @@
}, },
{ {
"name": "symfony/psr-http-message-bridge", "name": "symfony/psr-http-message-bridge",
"version": "v7.0.3", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/psr-http-message-bridge.git", "url": "https://github.com/symfony/psr-http-message-bridge.git",
"reference": "d9fadaf9541d7c01c307e48905d7ce1dbee6bf38" "reference": "fbc500cbcb64d3ea7469f019ab7aa717b320ff3f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/d9fadaf9541d7c01c307e48905d7ce1dbee6bf38", "url": "https://api.github.com/repos/symfony/psr-http-message-bridge/zipball/fbc500cbcb64d3ea7469f019ab7aa717b320ff3f",
"reference": "d9fadaf9541d7c01c307e48905d7ce1dbee6bf38", "reference": "fbc500cbcb64d3ea7469f019ab7aa717b320ff3f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7882,7 +7883,7 @@
"psr-7" "psr-7"
], ],
"support": { "support": {
"source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.0.3" "source": "https://github.com/symfony/psr-http-message-bridge/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -7898,20 +7899,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-01-23T15:02:46+00:00" "time": "2024-03-28T09:20:36+00:00"
}, },
{ {
"name": "symfony/routing", "name": "symfony/routing",
"version": "v7.0.5", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/routing.git", "url": "https://github.com/symfony/routing.git",
"reference": "ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19" "reference": "cded64e5bbf9f31786f1055fcc76718fdd77519c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19", "url": "https://api.github.com/repos/symfony/routing/zipball/cded64e5bbf9f31786f1055fcc76718fdd77519c",
"reference": "ba6bf07d43289c6a4b4591ddb75bc3bc5f069c19", "reference": "cded64e5bbf9f31786f1055fcc76718fdd77519c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -7963,7 +7964,7 @@
"url" "url"
], ],
"support": { "support": {
"source": "https://github.com/symfony/routing/tree/v7.0.5" "source": "https://github.com/symfony/routing/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -7979,20 +7980,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-27T12:34:35+00:00" "time": "2024-03-28T21:02:11+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
"version": "v3.4.1", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/service-contracts.git", "url": "https://github.com/symfony/service-contracts.git",
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0" "reference": "11bbf19a0fb7b36345861e85c5768844c552906e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/fe07cbc8d837f60caf7018068e350cc5163681a0", "url": "https://api.github.com/repos/symfony/service-contracts/zipball/11bbf19a0fb7b36345861e85c5768844c552906e",
"reference": "fe07cbc8d837f60caf7018068e350cc5163681a0", "reference": "11bbf19a0fb7b36345861e85c5768844c552906e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -8045,7 +8046,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/service-contracts/tree/v3.4.1" "source": "https://github.com/symfony/service-contracts/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@@ -8061,7 +8062,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-12-26T14:02:43+00:00" "time": "2023-12-19T21:51:00+00:00"
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
@@ -8245,16 +8246,16 @@
}, },
{ {
"name": "symfony/translation-contracts", "name": "symfony/translation-contracts",
"version": "v3.4.1", "version": "v3.4.2",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/translation-contracts.git", "url": "https://github.com/symfony/translation-contracts.git",
"reference": "06450585bf65e978026bda220cdebca3f867fde7" "reference": "43810bdb2ddb5400e5c5e778e27b210a0ca83b6b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/translation-contracts/zipball/06450585bf65e978026bda220cdebca3f867fde7", "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/43810bdb2ddb5400e5c5e778e27b210a0ca83b6b",
"reference": "06450585bf65e978026bda220cdebca3f867fde7", "reference": "43810bdb2ddb5400e5c5e778e27b210a0ca83b6b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -8303,7 +8304,7 @@
"standards" "standards"
], ],
"support": { "support": {
"source": "https://github.com/symfony/translation-contracts/tree/v3.4.1" "source": "https://github.com/symfony/translation-contracts/tree/v3.4.2"
}, },
"funding": [ "funding": [
{ {
@@ -8319,7 +8320,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2023-12-26T14:02:43+00:00" "time": "2024-01-23T14:51:35+00:00"
}, },
{ {
"name": "symfony/uid", "name": "symfony/uid",
@@ -8397,16 +8398,16 @@
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
"version": "v7.0.4", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-dumper.git", "url": "https://github.com/symfony/var-dumper.git",
"reference": "e03ad7c1535e623edbb94c22cc42353e488c6670" "reference": "66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/e03ad7c1535e623edbb94c22cc42353e488c6670", "url": "https://api.github.com/repos/symfony/var-dumper/zipball/66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb",
"reference": "e03ad7c1535e623edbb94c22cc42353e488c6670", "reference": "66d13dc207d5dab6b4f4c2b5460efe1bea29dbfb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -8460,7 +8461,7 @@
"dump" "dump"
], ],
"support": { "support": {
"source": "https://github.com/symfony/var-dumper/tree/v7.0.4" "source": "https://github.com/symfony/var-dumper/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -8476,26 +8477,28 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-15T11:33:06+00:00" "time": "2024-03-19T11:57:22+00:00"
}, },
{ {
"name": "symfony/var-exporter", "name": "symfony/var-exporter",
"version": "v7.0.4", "version": "v7.0.6",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/var-exporter.git", "url": "https://github.com/symfony/var-exporter.git",
"reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41" "reference": "c74c568d2a15a1d407cf40d61ea82bc2d521e27b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/var-exporter/zipball/dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41", "url": "https://api.github.com/repos/symfony/var-exporter/zipball/c74c568d2a15a1d407cf40d61ea82bc2d521e27b",
"reference": "dfb0acb6803eb714f05d97dd4c5abe6d5fa9fe41", "reference": "c74c568d2a15a1d407cf40d61ea82bc2d521e27b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=8.2" "php": ">=8.2"
}, },
"require-dev": { "require-dev": {
"symfony/property-access": "^6.4|^7.0",
"symfony/serializer": "^6.4|^7.0",
"symfony/var-dumper": "^6.4|^7.0" "symfony/var-dumper": "^6.4|^7.0"
}, },
"type": "library", "type": "library",
@@ -8534,7 +8537,7 @@
"serialize" "serialize"
], ],
"support": { "support": {
"source": "https://github.com/symfony/var-exporter/tree/v7.0.4" "source": "https://github.com/symfony/var-exporter/tree/v7.0.6"
}, },
"funding": [ "funding": [
{ {
@@ -8550,7 +8553,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-02-26T10:35:24+00:00" "time": "2024-03-20T21:25:22+00:00"
}, },
{ {
"name": "tijsverkoyen/css-to-inline-styles", "name": "tijsverkoyen/css-to-inline-styles",
@@ -8897,23 +8900,23 @@
"packages-dev": [ "packages-dev": [
{ {
"name": "barryvdh/laravel-debugbar", "name": "barryvdh/laravel-debugbar",
"version": "v3.12.2", "version": "v3.13.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git", "url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "43555503052443964ce2c1c1f3b0378e58219eb8" "reference": "241e9bddb04ab42a04a5fe8b2b9654374c864229"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/43555503052443964ce2c1c1f3b0378e58219eb8", "url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/241e9bddb04ab42a04a5fe8b2b9654374c864229",
"reference": "43555503052443964ce2c1c1f3b0378e58219eb8", "reference": "241e9bddb04ab42a04a5fe8b2b9654374c864229",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"illuminate/routing": "^9|^10|^11", "illuminate/routing": "^9|^10|^11",
"illuminate/session": "^9|^10|^11", "illuminate/session": "^9|^10|^11",
"illuminate/support": "^9|^10|^11", "illuminate/support": "^9|^10|^11",
"maximebf/debugbar": "~1.21.0", "maximebf/debugbar": "~1.22.0",
"php": "^8.0", "php": "^8.0",
"symfony/finder": "^6|^7" "symfony/finder": "^6|^7"
}, },
@@ -8926,7 +8929,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "3.10-dev" "dev-master": "3.13-dev"
}, },
"laravel": { "laravel": {
"providers": [ "providers": [
@@ -8965,7 +8968,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues", "issues": "https://github.com/barryvdh/laravel-debugbar/issues",
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.12.2" "source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.13.3"
}, },
"funding": [ "funding": [
{ {
@@ -8977,7 +8980,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-03-13T09:50:34+00:00" "time": "2024-04-04T02:42:49+00:00"
}, },
{ {
"name": "barryvdh/laravel-ide-helper", "name": "barryvdh/laravel-ide-helper",
@@ -9606,25 +9609,27 @@
}, },
{ {
"name": "maximebf/debugbar", "name": "maximebf/debugbar",
"version": "v1.21.3", "version": "v1.22.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/maximebf/php-debugbar.git", "url": "https://github.com/maximebf/php-debugbar.git",
"reference": "0b407703b08ea0cf6ebc61e267cc96ff7000911b" "reference": "7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/0b407703b08ea0cf6ebc61e267cc96ff7000911b", "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96",
"reference": "0b407703b08ea0cf6ebc61e267cc96ff7000911b", "reference": "7aa9a27a0b1158ed5ad4e7175e8d3aee9a818b96",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.1|^8", "php": "^7.2|^8",
"psr/log": "^1|^2|^3", "psr/log": "^1|^2|^3",
"symfony/var-dumper": "^4|^5|^6|^7" "symfony/var-dumper": "^4|^5|^6|^7"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": ">=7.5.20 <10.0", "dbrekelmans/bdi": "^1",
"phpunit/phpunit": "^8|^9",
"symfony/panther": "^1|^2.1",
"twig/twig": "^1.38|^2.7|^3.0" "twig/twig": "^1.38|^2.7|^3.0"
}, },
"suggest": { "suggest": {
@@ -9635,7 +9640,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "1.21-dev" "dev-master": "1.22-dev"
} }
}, },
"autoload": { "autoload": {
@@ -9666,9 +9671,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/maximebf/php-debugbar/issues", "issues": "https://github.com/maximebf/php-debugbar/issues",
"source": "https://github.com/maximebf/php-debugbar/tree/v1.21.3" "source": "https://github.com/maximebf/php-debugbar/tree/v1.22.3"
}, },
"time": "2024-03-12T14:23:07+00:00" "time": "2024-04-03T19:39:26+00:00"
}, },
{ {
"name": "mockery/mockery", "name": "mockery/mockery",
@@ -10233,16 +10238,16 @@
}, },
{ {
"name": "phpstan/phpdoc-parser", "name": "phpstan/phpdoc-parser",
"version": "1.27.0", "version": "1.28.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git", "url": "https://github.com/phpstan/phpdoc-parser.git",
"reference": "86e4d5a4b036f8f0be1464522f4c6b584c452757" "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/86e4d5a4b036f8f0be1464522f4c6b584c452757", "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb",
"reference": "86e4d5a4b036f8f0be1464522f4c6b584c452757", "reference": "cd06d6b1a1b3c75b0b83f97577869fd85a3cd4fb",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -10274,9 +10279,9 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types", "description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": { "support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues", "issues": "https://github.com/phpstan/phpdoc-parser/issues",
"source": "https://github.com/phpstan/phpdoc-parser/tree/1.27.0" "source": "https://github.com/phpstan/phpdoc-parser/tree/1.28.0"
}, },
"time": "2024-03-21T13:14:53+00:00" "time": "2024-04-03T18:51:33+00:00"
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
@@ -10390,21 +10395,21 @@
}, },
{ {
"name": "phpstan/phpstan-strict-rules", "name": "phpstan/phpstan-strict-rules",
"version": "1.5.2", "version": "1.5.3",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git", "url": "https://github.com/phpstan/phpstan-strict-rules.git",
"reference": "7a50e9662ee9f3942e4aaaf3d603653f60282542" "reference": "568210bd301f94a0d4b1e5a0808c374c1b9cf11b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/7a50e9662ee9f3942e4aaaf3d603653f60282542", "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/568210bd301f94a0d4b1e5a0808c374c1b9cf11b",
"reference": "7a50e9662ee9f3942e4aaaf3d603653f60282542", "reference": "568210bd301f94a0d4b1e5a0808c374c1b9cf11b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": "^7.2 || ^8.0", "php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.10.34" "phpstan/phpstan": "^1.10.60"
}, },
"require-dev": { "require-dev": {
"nikic/php-parser": "^4.13.0", "nikic/php-parser": "^4.13.0",
@@ -10433,9 +10438,9 @@
"description": "Extra strict and opinionated rules for PHPStan", "description": "Extra strict and opinionated rules for PHPStan",
"support": { "support": {
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues", "issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.2" "source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.5.3"
}, },
"time": "2023-10-30T14:35:06+00:00" "time": "2024-04-06T07:43:25+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
@@ -10760,16 +10765,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "10.5.16", "version": "10.5.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd" "reference": "c1f736a473d21957ead7e94fcc029f571895abf5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c1f736a473d21957ead7e94fcc029f571895abf5",
"reference": "18f8d4a5f52b61fdd9370aaae3167daa0eeb69cd", "reference": "c1f736a473d21957ead7e94fcc029f571895abf5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -10841,7 +10846,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.16" "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.17"
}, },
"funding": [ "funding": [
{ {
@@ -10857,7 +10862,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-03-28T10:08:10+00:00" "time": "2024-04-05T04:39:01+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",

View File

@@ -117,9 +117,9 @@ return [
'expression_engine' => false, 'expression_engine' => false,
// see cer.php for exchange rates feature flag. // see cer.php for exchange rates feature flag.
], ],
'version' => 'develop/2024-03-31', 'version' => 'develop/2024-04-08',
'api_version' => '2.0.13', 'api_version' => '2.0.13',
'db_version' => 23, 'db_version' => 24,
// generic settings // generic settings
'maxUploadSize' => 1073741824, // 1 GB 'maxUploadSize' => 1073741824, // 1 GB
@@ -215,11 +215,14 @@ return [
'zoom_level' => env('MAP_DEFAULT_ZOOM', '6'), 'zoom_level' => env('MAP_DEFAULT_ZOOM', '6'),
], ],
// administration specific preferences
'admin_specific_prefs' => ['frontpageAccounts', 'lastActivity'],
// default user-related values // default user-related values
'darkMode' => 'browser', 'darkMode' => 'browser',
'list_length' => 10, // to be removed if v1 is cancelled. 'list_length' => 10, // to be removed if v1 is cancelled.
'default_preferences' => [ 'default_preferences' => [
'frontPageAccounts' => [], 'frontpageAccounts' => [],
'listPageSize' => 50, 'listPageSize' => 50,
'currencyPreference' => 'EUR', 'currencyPreference' => 'EUR',
'language' => 'en_US', 'language' => 'en_US',

302
config/translations.php Normal file
View File

@@ -0,0 +1,302 @@
<?php
/*
* translations.php
* Copyright (c) 2024 james@firefly-iii.org.
*
* This file is part of Firefly III (https://github.com/firefly-iii).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://www.gnu.org/licenses/.
*/
declare(strict_types=1);
return [
'json' => [
'v2' => [
'config' => [
'html_language',
'date_time_fns',
'month_and_day_fns',
'does_not_exist', // on purpose
'date_time_fns_short',
],
'form' => [
'title',
],
'validation' => [
'bad_type_source',
'bad_type_destination',
],
'firefly' => [
'spent',
'administration_owner',
'administration_you',
'administration_role_owner',
'administration_role_ro',
'administration_role_mng_trx',
'administration_role_mng_meta',
'administration_role_mng_budgets',
'administration_role_mng_piggies',
'administration_role_mng_subscriptions',
'administration_role_mng_rules',
'administration_role_mng_recurring',
'administration_role_mng_webhooks',
'administration_role_mng_currencies',
'administration_role_view_reports',
'administration_role_full',
'new_administration_created',
'left',
'paid',
'errors_submission_v2',
'unpaid',
'default_group_title_name_plain',
'subscriptions_in_group',
'subscr_expected_x_times',
'overspent',
'money_flowing_in',
'money_flowing_out',
'category',
'unknown_category_plain',
'all_money',
'unknown_source_plain',
'unknown_dest_plain',
'unknown_any_plain',
'unknown_budget_plain',
'stored_journal_js',
'wait_loading_transaction',
'nothing_found',
'wait_loading_data',
'Transfer',
'Withdrawal',
'Deposit',
'expense_account',
'revenue_account',
'budget',
'account_type_Asset account',
'account_type_Expense account',
'account_type_Revenue account',
'account_type_Debt',
'account_type_Loan',
'account_type_Mortgage',
'account_role_defaultAsset',
'account_role_sharedAsset',
'account_role_savingAsset',
'account_role_ccAsset',
'account_role_cashWalletAsset',
],
],
'v1' => [
'firefly' => [
'welcome_back',
'flash_error',
'flash_warning',
'flash_success',
'close',
'select_dest_account',
'select_source_account',
'split_transaction_title',
'errors_submission',
'split',
'single_split',
'transaction_stored_link',
'webhook_stored_link',
'webhook_updated_link',
'transaction_updated_link',
'transaction_new_stored_link',
'transaction_journal_information',
'submission_options',
'apply_rules_checkbox',
'fire_webhooks_checkbox',
'no_budget_pointer',
'no_bill_pointer',
'source_account',
'hidden_fields_preferences',
'destination_account',
'add_another_split',
'submission',
'stored_journal',
'create_another',
'reset_after',
'submit',
'amount',
'date',
'is_reconciled_fields_dropped',
'tags',
'no_budget',
'no_bill',
'category',
'attachments',
'notes',
'external_url',
'update_transaction',
'after_update_create_another',
'store_as_new',
'reset_after',
'split_title_help',
'none_in_select_list',
'no_piggy_bank',
'description',
'split_transaction_title_help',
'destination_account_reconciliation',
'source_account_reconciliation',
'budget',
'bill',
'you_create_withdrawal',
'you_create_transfer',
'you_create_deposit',
'edit',
'delete',
'name',
'profile_whoops',
'profile_something_wrong',
'profile_try_again',
'profile_oauth_clients',
'profile_oauth_no_clients',
'profile_oauth_clients_header',
'profile_oauth_client_id',
'profile_oauth_client_name',
'profile_oauth_client_secret',
'profile_oauth_create_new_client',
'profile_oauth_create_client',
'profile_oauth_edit_client',
'profile_oauth_name_help',
'profile_oauth_redirect_url',
'profile_oauth_clients_external_auth',
'profile_oauth_redirect_url_help',
'profile_authorized_apps',
'profile_authorized_clients',
'profile_scopes',
'profile_revoke',
'profile_personal_access_tokens',
'profile_personal_access_token',
'profile_personal_access_token_explanation',
'profile_no_personal_access_token',
'profile_create_new_token',
'profile_create_token',
'profile_create',
'profile_save_changes',
'default_group_title_name',
'piggy_bank',
'profile_oauth_client_secret_title',
'profile_oauth_client_secret_expl',
'profile_oauth_confidential',
'profile_oauth_confidential_help',
'multi_account_warning_unknown',
'multi_account_warning_withdrawal',
'multi_account_warning_deposit',
'multi_account_warning_transfer',
'webhook_trigger_STORE_TRANSACTION',
'webhook_trigger_UPDATE_TRANSACTION',
'webhook_trigger_DESTROY_TRANSACTION',
'webhook_response_TRANSACTIONS',
'webhook_response_ACCOUNTS',
'webhook_response_none_NONE',
'webhook_delivery_JSON',
'actions',
'meta_data',
'webhook_messages',
'inactive',
'no_webhook_messages',
'inspect',
'edit',
'delete',
'create_new_webhook',
'webhooks',
'webhook_trigger_form_help',
'webhook_response_form_help',
'webhook_delivery_form_help',
'webhook_active_form_help',
'edit_webhook_js',
'webhook_was_triggered',
'view_message',
'view_attempts',
'message_content_title',
'message_content_help',
'attempt_content_title',
'attempt_content_help',
'no_attempts',
'webhook_attempt_at',
'logs',
'response',
'visit_webhook_url',
'reset_webhook_secret',
],
'form' => [
'url',
'active',
'interest_date',
'title',
'book_date',
'process_date',
'due_date',
'foreign_amount',
'payment_date',
'invoice_date',
'internal_reference',
'webhook_response',
'webhook_trigger',
'webhook_delivery',
],
'list' => [
'active',
'trigger',
'response',
'delivery',
'url',
'secret',
],
'config' => [
'html_language',
'date_time_fns',
],
],
],
// TODO duplicate with firefly.php
'languages' => [
// currently enabled languages
'bg_BG',
'cs_CZ',
'da_DK',
'de_DE',
'el_GR',
'en_GB',
'en_US',
'es_ES',
'ca_ES',
'fi_FI',
'fr_FR',
'hu_HU',
'id_ID',
'it_IT',
'ja_JP',
'ko_KR',
'nb_NO',
'nn_NO',
'nl_NL',
'pl_PL',
'pt_BR',
'pt_PT',
'ro_RO',
'ru_RU',
'sk_SK',
'sl_SI',
'sv_SE',
'tr_TR',
'uk_UA',
'vi_VN',
'zh_TW',
'zh_CN',
],
];

View File

@@ -39,7 +39,7 @@ return [
| the usual Laravel view path has already been registered for you. | the usual Laravel view path has already been registered for you.
| |
*/ */
'layout' => env('FIREFLY_III_LAYOUT', 'v1'),
'paths' => $paths, 'paths' => $paths,
/* /*

View File

@@ -21,7 +21,6 @@
*/ */
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -46,7 +45,7 @@ class ExpandTransactionsTable extends Migration
$table->dropColumn('identifier'); $table->dropColumn('identifier');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not drop column "identifier": %s', $e->getMessage())); app('log')->error(sprintf('Could not drop column "identifier": %s', $e->getMessage()));
app('log')->error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column does not exist, this is not an problem. Otherwise, please open a GitHub discussion.');
} }

View File

@@ -21,7 +21,6 @@
*/ */
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -74,7 +73,7 @@ class ChangesForV431 extends Migration
$table->renameColumn('start_date', 'startdate'); $table->renameColumn('start_date', 'startdate');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
@@ -89,7 +88,7 @@ class ChangesForV431 extends Migration
$table->dropColumn('end_date'); $table->dropColumn('end_date');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
@@ -103,7 +102,7 @@ class ChangesForV431 extends Migration
$table->dropColumn('decimal_places'); $table->dropColumn('decimal_places');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
@@ -141,7 +140,7 @@ class ChangesForV431 extends Migration
$table->renameColumn('startdate', 'start_date'); $table->renameColumn('startdate', 'start_date');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
@@ -171,7 +170,7 @@ class ChangesForV431 extends Migration
$table->dropColumn('repeats'); $table->dropColumn('repeats');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
@@ -184,7 +183,7 @@ class ChangesForV431 extends Migration
$table->dropColumn('repeat_freq'); $table->dropColumn('repeat_freq');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }

View File

@@ -21,7 +21,6 @@
*/ */
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -53,7 +52,7 @@ class ChangesForV440 extends Migration
} }
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }

View File

@@ -21,7 +21,6 @@
*/ */
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -47,7 +46,7 @@ class ChangesForV450 extends Migration
$table->dropColumn('foreign_amount'); $table->dropColumn('foreign_amount');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
@@ -75,7 +74,7 @@ class ChangesForV450 extends Migration
$table->dropColumn('foreign_currency_id'); $table->dropColumn('foreign_currency_id');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }

View File

@@ -21,7 +21,6 @@
*/ */
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -47,7 +46,7 @@ class ChangesForV470a extends Migration
$table->dropColumn('reconciled'); $table->dropColumn('reconciled');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }

View File

@@ -22,7 +22,6 @@
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -61,7 +60,7 @@ class ChangesForV472 extends Migration
$table->dropColumn('order'); $table->dropColumn('order');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
@@ -83,7 +82,7 @@ class ChangesForV472 extends Migration
$table->dropColumn('notes'); $table->dropColumn('notes');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }

View File

@@ -22,7 +22,6 @@
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -52,7 +51,7 @@ class ChangesForV473 extends Migration
$table->dropColumn('transaction_currency_id'); $table->dropColumn('transaction_currency_id');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }
@@ -66,7 +65,7 @@ class ChangesForV473 extends Migration
$table->dropColumn('strict'); $table->dropColumn('strict');
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }

View File

@@ -22,7 +22,6 @@
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -52,7 +51,7 @@ class ChangesForV477 extends Migration
$table->dropColumn(['transaction_currency_id']); $table->dropColumn(['transaction_currency_id']);
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }

View File

@@ -22,7 +22,6 @@
declare(strict_types=1); declare(strict_types=1);
use Doctrine\DBAL\Schema\Exception\ColumnDoesNotExist;
use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\QueryException; use Illuminate\Database\QueryException;
use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Blueprint;
@@ -47,7 +46,7 @@ class ChangesForV479 extends Migration
$table->dropColumn(['enabled']); $table->dropColumn(['enabled']);
} }
); );
} catch (ColumnDoesNotExist|QueryException $e) { } catch (QueryException $e) {
app('log')->error(sprintf('Could not execute query: %s', $e->getMessage())); app('log')->error(sprintf('Could not execute query: %s', $e->getMessage()));
app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.'); app('log')->error('If the column or index already exists (see error), this is not an problem. Otherwise, please open a GitHub discussion.');
} }

Some files were not shown because too many files have changed in this diff Show More