Release 2.16 (#4780)
This commit is contained in:
@@ -23,6 +23,7 @@ import {
|
||||
Legend,
|
||||
Title,
|
||||
Tooltip,
|
||||
Colors,
|
||||
// SubTitle
|
||||
} from 'chart.js';
|
||||
|
||||
@@ -50,6 +51,7 @@ Chart.register(
|
||||
Legend,
|
||||
Title,
|
||||
Tooltip,
|
||||
Colors
|
||||
// SubTitle
|
||||
);
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ export default class KimaiAPI extends KimaiPlugin {
|
||||
|
||||
_headers() {
|
||||
const headers = new Headers();
|
||||
headers.append('X-AUTH-SESSION', '1');
|
||||
headers.append('Content-Type', 'application/json');
|
||||
|
||||
return headers;
|
||||
|
||||
@@ -198,9 +198,6 @@
|
||||
"symfony/symfony": "*"
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-main": "2.0.x-dev"
|
||||
},
|
||||
"symfony": {
|
||||
"id": "01C3FWRDJJEX9K6Y3A4XDFXPBR",
|
||||
"allow-contrib": true,
|
||||
|
||||
1096
composer.lock
generated
1096
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -386,8 +386,8 @@
|
||||
],
|
||||
'en_ID' =>
|
||||
[
|
||||
'date' => 'M/d/yy',
|
||||
'time' => 'HH:mm',
|
||||
'date' => 'dd/MM/y',
|
||||
'time' => 'HH.mm',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -603,7 +603,7 @@
|
||||
],
|
||||
'en_NZ' =>
|
||||
[
|
||||
'date' => 'd/MM/yy',
|
||||
'date' => 'dd/MM/y',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
@@ -870,14 +870,14 @@
|
||||
'es_AR' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
'es_BO' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -898,7 +898,7 @@
|
||||
'es_CL' =>
|
||||
[
|
||||
'date' => 'dd-MM-yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -912,14 +912,14 @@
|
||||
'es_CR' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
'es_CU' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -933,7 +933,7 @@
|
||||
'es_EC' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -954,28 +954,28 @@
|
||||
'es_GT' =>
|
||||
[
|
||||
'date' => 'd/MM/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
'es_HN' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
'es_MX' =>
|
||||
[
|
||||
'date' => 'dd/MM/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
'es_NI' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -989,7 +989,7 @@
|
||||
'es_PE' =>
|
||||
[
|
||||
'date' => 'd/MM/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -1010,14 +1010,14 @@
|
||||
'es_PY' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
'es_SV' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -1031,7 +1031,7 @@
|
||||
'es_UY' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
@@ -1835,7 +1835,7 @@
|
||||
],
|
||||
'sl' =>
|
||||
[
|
||||
'date' => 'd. MM. yy',
|
||||
'date' => 'd. M. yy',
|
||||
'time' => 'HH:mm',
|
||||
'rtl' => false,
|
||||
'translation' => true,
|
||||
@@ -1905,14 +1905,14 @@
|
||||
],
|
||||
'vi' =>
|
||||
[
|
||||
'date' => 'dd/MM/y',
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'rtl' => false,
|
||||
'translation' => true,
|
||||
],
|
||||
'vi_VN' =>
|
||||
[
|
||||
'date' => 'dd/MM/y',
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'HH:mm',
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
@@ -1931,4 +1931,11 @@
|
||||
'rtl' => false,
|
||||
'translation' => true,
|
||||
],
|
||||
'zh_Hant_TW' =>
|
||||
[
|
||||
'date' => 'y/M/d',
|
||||
'time' => 'Bh:mm',
|
||||
'rtl' => false,
|
||||
'translation' => true,
|
||||
],
|
||||
];
|
||||
@@ -22,6 +22,7 @@ doctrine:
|
||||
|
||||
types:
|
||||
datetime: App\Doctrine\UTCDateTimeType
|
||||
datetime_immutable: App\Doctrine\UTCDateTimeImmutableType
|
||||
orm:
|
||||
controller_resolver:
|
||||
auto_mapping: true
|
||||
|
||||
7
config/packages/rate_limiter.yaml
Normal file
7
config/packages/rate_limiter.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
framework:
|
||||
rate_limiter:
|
||||
session_prediction:
|
||||
policy: 'fixed_window'
|
||||
limit: 250
|
||||
interval: '1 hour'
|
||||
lock_factory: null
|
||||
@@ -63,7 +63,7 @@ security:
|
||||
logout:
|
||||
path: logout
|
||||
target: homepage
|
||||
enable_csrf: true
|
||||
enable_csrf: false
|
||||
|
||||
login_throttling:
|
||||
max_attempts: 5
|
||||
@@ -76,6 +76,7 @@ security:
|
||||
max_uses: 1
|
||||
|
||||
access_decision_manager:
|
||||
# only grants access if there is no voter denying access
|
||||
strategy: unanimous
|
||||
allow_if_all_abstain: false
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ tabler:
|
||||
search: fas fa-search
|
||||
settings: fas fa-cog
|
||||
shop: fas fa-shopping-cart
|
||||
spinner: fas fa-spinner fa-pulse
|
||||
spinner: fas fa-spinner
|
||||
start: fas fa-play
|
||||
start-small: far fa-play-circle
|
||||
stop: fas fa-stop
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
parameters:
|
||||
locale: en
|
||||
# can be regenerated with "bin/console kimai:reset:locales"
|
||||
app_locales: ar|cs|da|de|de_CH|el|en|eo|es|eu|fa|fi|fo|fr|he|hr|hu|id|it|ja|ko|nb_NO|nl|pa|pl|pt|pt_BR|ro|ru|sk|sl|sv|tr|uk|vi|zh_CN|zh_Hant|cs_CZ|da_DK|da_GL|de_AT|de_BE|de_CH|de_DE|de_IT|de_LI|de_LU|el_CY|el_GR|en_AE|en_AG|en_AI|en_AS|en_AT|en_AU|en_BB|en_BE|en_BI|en_BM|en_BS|en_BW|en_BZ|en_CA|en_CC|en_CH|en_CK|en_CM|en_CX|en_CY|en_DE|en_DG|en_DK|en_DM|en_ER|en_FI|en_FJ|en_FK|en_FM|en_GB|en_GD|en_GG|en_GH|en_GI|en_GM|en_GU|en_GY|en_HK|en_ID|en_IE|en_IL|en_IM|en_IN|en_IO|en_JE|en_JM|en_KE|en_KI|en_KN|en_KY|en_LC|en_LR|en_LS|en_MG|en_MH|en_MO|en_MP|en_MS|en_MT|en_MU|en_MV|en_MW|en_MY|en_NA|en_NF|en_NG|en_NH|en_NL|en_NR|en_NU|en_NZ|en_PG|en_PH|en_PK|en_PN|en_PR|en_PW|en_RH|en_RW|en_SB|en_SC|en_SD|en_SE|en_SG|en_SH|en_SI|en_SL|en_SS|en_SX|en_SZ|en_TC|en_TK|en_TO|en_TT|en_TV|en_TZ|en_UG|en_UM|en_US|en_VC|en_VG|en_VI|en_VU|en_WS|en_ZA|en_ZM|en_ZW|es_AR|es_BO|es_BR|es_BZ|es_CL|es_CO|es_CR|es_CU|es_DO|es_EA|es_EC|es_ES|es_GQ|es_GT|es_HN|es_IC|es_MX|es_NI|es_PA|es_PE|es_PH|es_PR|es_PY|es_SV|es_US|es_UY|es_VE|eu_ES|fa_AF|fa_IR|fi_FI|fo_DK|fo_FO|fr_BE|fr_BF|fr_BI|fr_BJ|fr_BL|fr_CA|fr_CD|fr_CF|fr_CG|fr_CH|fr_CI|fr_CM|fr_DJ|fr_DZ|fr_FR|fr_GA|fr_GF|fr_GN|fr_GP|fr_GQ|fr_HT|fr_KM|fr_LU|fr_MA|fr_MC|fr_MF|fr_MG|fr_ML|fr_MQ|fr_MR|fr_MU|fr_NC|fr_NE|fr_PF|fr_PM|fr_RE|fr_RW|fr_SC|fr_SN|fr_SY|fr_TD|fr_TG|fr_TN|fr_VU|fr_WF|fr_YT|he_IL|hr_BA|hr_HR|hu_HU|it_CH|it_IT|it_SM|it_VA|ja_JP|ko_CN|ko_KP|ko_KR|nl_AW|nl_BE|nl_BQ|nl_CW|nl_NL|nl_SR|nl_SX|pl_PL|pt_AO|pt_BR|pt_CH|pt_CV|pt_GQ|pt_GW|pt_LU|pt_MO|pt_MZ|pt_PT|pt_ST|pt_TL|ro_MD|ro_RO|ru_BY|ru_KG|ru_KZ|ru_MD|ru_RU|ru_UA|sk_SK|sv_AX|sv_FI|sv_SE|tr_CY|tr_TR|uk_UA|vi_VN
|
||||
app_locales: ar|cs|da|de|de_CH|el|en|eo|es|eu|fa|fi|fo|fr|he|hr|hu|id|it|ja|ko|nb_NO|nl|pa|pl|pt|pt_BR|ro|ru|sk|sl|sv|tr|uk|vi|zh_CN|zh_Hant|zh_Hant_TW|cs_CZ|da_DK|da_GL|de_AT|de_BE|de_CH|de_DE|de_IT|de_LI|de_LU|el_CY|el_GR|en_AE|en_AG|en_AI|en_AS|en_AT|en_AU|en_BB|en_BE|en_BI|en_BM|en_BS|en_BW|en_BZ|en_CA|en_CC|en_CH|en_CK|en_CM|en_CX|en_CY|en_DE|en_DG|en_DK|en_DM|en_ER|en_FI|en_FJ|en_FK|en_FM|en_GB|en_GD|en_GG|en_GH|en_GI|en_GM|en_GU|en_GY|en_HK|en_ID|en_IE|en_IL|en_IM|en_IN|en_IO|en_JE|en_JM|en_KE|en_KI|en_KN|en_KY|en_LC|en_LR|en_LS|en_MG|en_MH|en_MO|en_MP|en_MS|en_MT|en_MU|en_MV|en_MW|en_MY|en_NA|en_NF|en_NG|en_NH|en_NL|en_NR|en_NU|en_NZ|en_PG|en_PH|en_PK|en_PN|en_PR|en_PW|en_RH|en_RW|en_SB|en_SC|en_SD|en_SE|en_SG|en_SH|en_SI|en_SL|en_SS|en_SX|en_SZ|en_TC|en_TK|en_TO|en_TT|en_TV|en_TZ|en_UG|en_UM|en_US|en_VC|en_VG|en_VI|en_VU|en_WS|en_ZA|en_ZM|en_ZW|es_AR|es_BO|es_BR|es_BZ|es_CL|es_CO|es_CR|es_CU|es_DO|es_EA|es_EC|es_ES|es_GQ|es_GT|es_HN|es_IC|es_MX|es_NI|es_PA|es_PE|es_PH|es_PR|es_PY|es_SV|es_US|es_UY|es_VE|eu_ES|fa_AF|fa_IR|fi_FI|fo_DK|fo_FO|fr_BE|fr_BF|fr_BI|fr_BJ|fr_BL|fr_CA|fr_CD|fr_CF|fr_CG|fr_CH|fr_CI|fr_CM|fr_DJ|fr_DZ|fr_FR|fr_GA|fr_GF|fr_GN|fr_GP|fr_GQ|fr_HT|fr_KM|fr_LU|fr_MA|fr_MC|fr_MF|fr_MG|fr_ML|fr_MQ|fr_MR|fr_MU|fr_NC|fr_NE|fr_PF|fr_PM|fr_RE|fr_RW|fr_SC|fr_SN|fr_SY|fr_TD|fr_TG|fr_TN|fr_VU|fr_WF|fr_YT|he_IL|hr_BA|hr_HR|hu_HU|it_CH|it_IT|it_SM|it_VA|ja_JP|ko_CN|ko_KP|ko_KR|nl_AW|nl_BE|nl_BQ|nl_CW|nl_NL|nl_SR|nl_SX|pl_PL|pt_AO|pt_BR|pt_CH|pt_CV|pt_GQ|pt_GW|pt_LU|pt_MO|pt_MZ|pt_PT|pt_ST|pt_TL|ro_MD|ro_RO|ru_BY|ru_KG|ru_KZ|ru_MD|ru_RU|ru_UA|sk_SK|sv_AX|sv_FI|sv_SE|tr_CY|tr_TR|uk_UA|vi_VN
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
|
||||
16
package.json
16
package.json
@@ -24,10 +24,10 @@
|
||||
],
|
||||
"packageManager": "yarn@3.2.1",
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.19.6",
|
||||
"@babel/eslint-parser": "^7.18.2",
|
||||
"@babel/preset-env": "^7.19.4",
|
||||
"@fortawesome/fontawesome-free": "^6.5.0",
|
||||
"@babel/core": "^7.19",
|
||||
"@babel/eslint-parser": "^7.19",
|
||||
"@babel/preset-env": "^7.19",
|
||||
"@fortawesome/fontawesome-free": "^6.5",
|
||||
"@fullcalendar/bootstrap5": "^5.11",
|
||||
"@fullcalendar/core": "^5.11",
|
||||
"@fullcalendar/daygrid": "^5.11",
|
||||
@@ -37,17 +37,17 @@
|
||||
"@fullcalendar/timegrid": "^5.11",
|
||||
"@symfony/webpack-encore": "^4.0",
|
||||
"@tabler/core": "1.0.0-beta19",
|
||||
"chart.js": "^3.9",
|
||||
"chart.js": "^4.0",
|
||||
"core-js": "^3.6",
|
||||
"eslint": "^8.0",
|
||||
"eslint-webpack-plugin": "^3.0",
|
||||
"gridstack": "^7.1",
|
||||
"litepicker": "^2.0",
|
||||
"luxon": "^3.3",
|
||||
"sass": "^1.62.1",
|
||||
"sass": "^1.62",
|
||||
"sass-loader": "^13.2",
|
||||
"tom-select": "^2.2",
|
||||
"webpack": "^5.74.0",
|
||||
"webpack-cli": "^4.10.0"
|
||||
"webpack": "^5.91",
|
||||
"webpack-cli": "^4.10"
|
||||
}
|
||||
}
|
||||
|
||||
14
phpstan.neon
14
phpstan.neon
@@ -1253,11 +1253,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Doctrine/TimesheetSubscriber.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$datetime of static method DateTime\\:\\:createFromFormat\\(\\) expects string, mixed given\\.$#"
|
||||
count: 1
|
||||
path: src/Doctrine/UTCDateTimeType.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Entity\\\\Activity\\:\\:__toString\\(\\) should return string but returns string\\|null\\.$#"
|
||||
count: 1
|
||||
@@ -3280,7 +3275,7 @@ parameters:
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$inputTimezone of class Symfony\\\\Component\\\\Form\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToLocalizedStringTransformer constructor expects string\\|null, mixed given\\.$#"
|
||||
count: 1
|
||||
count: 2
|
||||
path: src/Form/Type/DateRangeType.php
|
||||
|
||||
-
|
||||
@@ -3290,7 +3285,7 @@ parameters:
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#2 \\$outputTimezone of class Symfony\\\\Component\\\\Form\\\\Extension\\\\Core\\\\DataTransformer\\\\DateTimeToLocalizedStringTransformer constructor expects string\\|null, mixed given\\.$#"
|
||||
count: 1
|
||||
count: 2
|
||||
path: src/Form/Type/DateRangeType.php
|
||||
|
||||
-
|
||||
@@ -3778,11 +3773,6 @@ parameters:
|
||||
count: 2
|
||||
path: src/Kernel.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Kernel\\:\\:configureContainer\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Kernel.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Kernel\\:\\:getBundleClasses\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
(self.webpackChunkkimai2=self.webpackChunkkimai2||[]).push([[535],{1548:function(i,n,u){u(846)},846:function(i,n,u){"use strict";u.r(n)}},function(i){var n;n=1548,i(i.s=n)}]);
|
||||
1
public/build/app-rtl.97153087.js
Normal file
1
public/build/app-rtl.97153087.js
Normal file
@@ -0,0 +1 @@
|
||||
(self.webpackChunkkimai2=self.webpackChunkkimai2||[]).push([[113],{2395:function(i,n,u){u(3865)},3865:function(i,n,u){"use strict";u.r(n)}},function(i){var n;n=2395,i(i.s=n)}]);
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
public/build/app.cde83469.js
Normal file
2
public/build/app.cde83469.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
public/build/calendar.bb629e51.js
Normal file
2
public/build/calendar.bb629e51.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
public/build/chart.80ee190c.js
Normal file
2
public/build/chart.80ee190c.js
Normal file
File diff suppressed because one or more lines are too long
@@ -1,13 +1,13 @@
|
||||
/*!
|
||||
* @kurkle/color v0.2.1
|
||||
* @kurkle/color v0.3.2
|
||||
* https://github.com/kurkle/color#readme
|
||||
* (c) 2022 Jukka Kurkela
|
||||
* (c) 2023 Jukka Kurkela
|
||||
* Released under the MIT License
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Chart.js v3.9.1
|
||||
* Chart.js v4.4.2
|
||||
* https://www.chartjs.org
|
||||
* (c) 2022 Chart.js Contributors
|
||||
* (c) 2024 Chart.js Contributors
|
||||
* Released under the MIT License
|
||||
*/
|
||||
File diff suppressed because one or more lines are too long
2
public/build/dashboard.10118fb0.js
Normal file
2
public/build/dashboard.10118fb0.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -2,26 +2,26 @@
|
||||
"entrypoints": {
|
||||
"app": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/app.6450be5e.js"
|
||||
"/build/runtime.74179306.js",
|
||||
"/build/app.cde83469.js"
|
||||
],
|
||||
"css": [
|
||||
"/build/app.3501ccee.css"
|
||||
"/build/app.ee4f7e19.css"
|
||||
]
|
||||
},
|
||||
"app-rtl": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/app-rtl.3d445498.js"
|
||||
"/build/runtime.74179306.js",
|
||||
"/build/app-rtl.97153087.js"
|
||||
],
|
||||
"css": [
|
||||
"/build/app-rtl.670658da.css"
|
||||
"/build/app-rtl.db588f2b.css"
|
||||
]
|
||||
},
|
||||
"export-pdf": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/export-pdf.d367a32e.js"
|
||||
"/build/runtime.74179306.js",
|
||||
"/build/export-pdf.1442bee7.js"
|
||||
],
|
||||
"css": [
|
||||
"/build/export-pdf.d8a6c23b.css"
|
||||
@@ -29,8 +29,8 @@
|
||||
},
|
||||
"invoice": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/invoice.2604495e.js"
|
||||
"/build/runtime.74179306.js",
|
||||
"/build/invoice.7ef8a0c8.js"
|
||||
],
|
||||
"css": [
|
||||
"/build/invoice.5bea118e.css"
|
||||
@@ -38,8 +38,8 @@
|
||||
},
|
||||
"invoice-pdf": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/invoice-pdf.ce9aace0.js"
|
||||
"/build/runtime.74179306.js",
|
||||
"/build/invoice-pdf.6091a528.js"
|
||||
],
|
||||
"css": [
|
||||
"/build/invoice-pdf.2b749265.css"
|
||||
@@ -47,14 +47,14 @@
|
||||
},
|
||||
"chart": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/chart.f5becfac.js"
|
||||
"/build/runtime.74179306.js",
|
||||
"/build/chart.80ee190c.js"
|
||||
]
|
||||
},
|
||||
"calendar": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/calendar.d45e4af5.js"
|
||||
"/build/runtime.74179306.js",
|
||||
"/build/calendar.bb629e51.js"
|
||||
],
|
||||
"css": [
|
||||
"/build/calendar.bb473428.css"
|
||||
@@ -62,8 +62,8 @@
|
||||
},
|
||||
"dashboard": {
|
||||
"js": [
|
||||
"/build/runtime.f0079159.js",
|
||||
"/build/dashboard.6774a712.js"
|
||||
"/build/runtime.74179306.js",
|
||||
"/build/dashboard.10118fb0.js"
|
||||
],
|
||||
"css": [
|
||||
"/build/dashboard.18f5a8b7.css"
|
||||
@@ -71,21 +71,21 @@
|
||||
}
|
||||
},
|
||||
"integrity": {
|
||||
"/build/runtime.f0079159.js": "sha384-H22sAW1aTvyIPqvHOvGXWSWTxf0y6mptp+MsVmyXCfjx/WJjBbhX9gbUZ+qIuihV",
|
||||
"/build/app.6450be5e.js": "sha384-P5Qc8Rav736nZcS2vqM2rBRZpr3bwMsk4SJENBsOMDPdfEjDX7M8WMpwhjzxj0PQ",
|
||||
"/build/app.3501ccee.css": "sha384-3chwmsldxvcA6ldtsAftB9R2/bSNCi17vSW9ycC0FqLNNM+IdnMorRBXh/zTW1NF",
|
||||
"/build/app-rtl.3d445498.js": "sha384-D5VYIVdHCPGzAPnMAIkRN1Ri9H4DxdwGts1BgG40JXJuOamq6UQXblaDBSpszOZ0",
|
||||
"/build/app-rtl.670658da.css": "sha384-Mo5HQ+W9EWDGM1gOyEZ7aScXNltzBMQa4cWC1HtShvs4XPMNUwzOb97jcXf34qSD",
|
||||
"/build/export-pdf.d367a32e.js": "sha384-Z5baqnzjI636nYFs4g63ViIKBZKRW4Jhv/7PQmTEQlqhfA7eK0vUMUtiyy0R5A9u",
|
||||
"/build/runtime.74179306.js": "sha384-OC1hTNUXUalKJcvmzrZ0TMCOIwnhxCxgG9dQkbcwR7WcBBCkl2H8bs3giiT2pAwG",
|
||||
"/build/app.cde83469.js": "sha384-829jYMX4FgmjcB0IV2HWYYOEviCyDD55lOX4fXXWUmUgDuDXXFZMyPFEEcK93dWR",
|
||||
"/build/app.ee4f7e19.css": "sha384-7E3ujVsOCkGatHu6khaWWqYhPkc85k22zuXZOwOVo1MlWcPSEBhS65Y0qbeWXdAp",
|
||||
"/build/app-rtl.97153087.js": "sha384-jX7jRUAa8rH29Eg8jLIUKGfGcOT6RBz/P90plXmZPadf2CXKUBdcNGrspaejCHkr",
|
||||
"/build/app-rtl.db588f2b.css": "sha384-OwYS82WpkkoVqI38n3gGpvMTiTFT+dUscgVglMw2vcDvIxAe2B3IcXMjHoCGm/gl",
|
||||
"/build/export-pdf.1442bee7.js": "sha384-C6agvjJnQUsMCxaZ/J7dUZU3cpC7uHKI9ZtnfGpRqYbjyw91YLy1oV3iNYgwYyCF",
|
||||
"/build/export-pdf.d8a6c23b.css": "sha384-ztepocHE4rnGE9eKZ4kL6jTKaePUyiwiB9TjJjstjpf/ckcKg1HedrEOOk/8ElJg",
|
||||
"/build/invoice.2604495e.js": "sha384-D6JvhGSqlx7z72b/qD3nF3QDXPy+XsCSRGtWfs1icjDKOcd2UzuXwuSa/E1Fg2TJ",
|
||||
"/build/invoice.7ef8a0c8.js": "sha384-z4lZ1Ig3+NPigrRyGPZoff0gG3n5PnCjaDJ73ATnzdUYk0lOCEtNV9fg35VRD0vG",
|
||||
"/build/invoice.5bea118e.css": "sha384-KNyGdZSTXnAi8Tn2WqrxJnCP18yRK7BrZTHKCAGAEtl5/4S/XAe4IHKpM5gfsmB7",
|
||||
"/build/invoice-pdf.ce9aace0.js": "sha384-mtZkXrpsXFMX2YvmmTlCm91QgsTlZLzLJnDAFcTuBDtDZ7TNkqLYkfCeLzFLVfwb",
|
||||
"/build/invoice-pdf.6091a528.js": "sha384-yJz/MDBgBpNHNxF7DuSyFbJN9EL7oDJjraoPRB7VYlHMdb1T0ZfTcI0L8VMDB46U",
|
||||
"/build/invoice-pdf.2b749265.css": "sha384-DXXgkz2WWnrWnfBnXX5fmfPQSPb98upMnWxYKwTGYS04EhrPIWfDCutB2unIrWh7",
|
||||
"/build/chart.f5becfac.js": "sha384-GSqETm8wULiVXyizvwRompfwu63r/C0Qd/AvrHDE4cqAKiIGCssb3QyBtGu1WN+W",
|
||||
"/build/calendar.d45e4af5.js": "sha384-wi3/ek3Msn+rk9jebeJnzEXaHUUWlzxkOZwhZyJP5Cg+AKWtolWAXD/hCXQAg0kq",
|
||||
"/build/chart.80ee190c.js": "sha384-KrQszq859PR0u+KHpGy+RO6K1rcMqCFZx+sNiLVNVZHwEi7RwTXqnYbu8zvfWzUI",
|
||||
"/build/calendar.bb629e51.js": "sha384-uihkC7VSrD8l4gSiveJxM2g8dLFCR9+VQwVmcIb2LlNmA2PKDQ/uV0TN5gzmgpo+",
|
||||
"/build/calendar.bb473428.css": "sha384-900W9o8666Qpw21rLP7hn5Ql8tWd40k0IcE3QpFm7E7V6bKva7xQgGlyzVuuh4GK",
|
||||
"/build/dashboard.6774a712.js": "sha384-lBwkNqUPv+IBbznagiFakY2BOIueq/Bg89wHO2XeM9YAZ51rPkrvdMd+XmFupHsM",
|
||||
"/build/dashboard.10118fb0.js": "sha384-pasZR1GYf8/7lMFS9OrsxX8nJ9tSlRYr32fWKUhGoF2mNAGrokLEWdgtbYMRHgFB",
|
||||
"/build/dashboard.18f5a8b7.css": "sha384-PBD8ftb2yBoSjRe2sN5Xb4dEz045kOEUfcIufdSis+tWoWdAx5j4Yic+F/6CYbrP"
|
||||
}
|
||||
}
|
||||
1
public/build/export-pdf.1442bee7.js
Normal file
1
public/build/export-pdf.1442bee7.js
Normal file
@@ -0,0 +1 @@
|
||||
(self.webpackChunkkimai2=self.webpackChunkkimai2||[]).push([[872],{878:function(i,n,u){u(6154)},6154:function(i,n,u){"use strict";u.r(n)}},function(i){var n;n=878,i(i.s=n)}]);
|
||||
@@ -1 +0,0 @@
|
||||
(self.webpackChunkkimai2=self.webpackChunkkimai2||[]).push([[185],{8810:function(i,n,u){u(9508)},9508:function(i,n,u){"use strict";u.r(n)}},function(i){var n;n=8810,i(i.s=n)}]);
|
||||
BIN
public/build/fonts/fa-brands-400.455ea818.woff2
Normal file
BIN
public/build/fonts/fa-brands-400.455ea818.woff2
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/build/fonts/fa-regular-400.21cb8f55.woff2
Normal file
BIN
public/build/fonts/fa-regular-400.21cb8f55.woff2
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
public/build/fonts/fa-solid-900.4d986b00.woff2
Normal file
BIN
public/build/fonts/fa-solid-900.4d986b00.woff2
Normal file
Binary file not shown.
Binary file not shown.
1
public/build/invoice-pdf.6091a528.js
Normal file
1
public/build/invoice-pdf.6091a528.js
Normal file
@@ -0,0 +1 @@
|
||||
(self.webpackChunkkimai2=self.webpackChunkkimai2||[]).push([[117],{1555:function(i,n,u){u(8837)},8837:function(i,n,u){"use strict";u.r(n)}},function(i){var n;n=1555,i(i.s=n)}]);
|
||||
@@ -1 +0,0 @@
|
||||
(self.webpackChunkkimai2=self.webpackChunkkimai2||[]).push([[266],{35:function(i,n,u){u(6197)},6197:function(i,n,u){"use strict";u.r(n)}},function(i){var n;n=35,i(i.s=n)}]);
|
||||
@@ -1 +0,0 @@
|
||||
(self.webpackChunkkimai2=self.webpackChunkkimai2||[]).push([[149],{474:function(i,n,u){u(9822)},9822:function(i,n,u){"use strict";u.r(n)}},function(i){var n;n=474,i(i.s=n)}]);
|
||||
1
public/build/invoice.7ef8a0c8.js
Normal file
1
public/build/invoice.7ef8a0c8.js
Normal file
@@ -0,0 +1 @@
|
||||
(self.webpackChunkkimai2=self.webpackChunkkimai2||[]).push([[896],{4820:function(i,n,u){u(5650)},5650:function(i,n,u){"use strict";u.r(n)}},function(i){var n;n=4820,i(i.s=n)}]);
|
||||
@@ -1,24 +1,24 @@
|
||||
{
|
||||
"build/app.css": "/build/app.3501ccee.css",
|
||||
"build/app.js": "/build/app.6450be5e.js",
|
||||
"build/app-rtl.css": "/build/app-rtl.670658da.css",
|
||||
"build/app-rtl.js": "/build/app-rtl.3d445498.js",
|
||||
"build/app.css": "/build/app.ee4f7e19.css",
|
||||
"build/app.js": "/build/app.cde83469.js",
|
||||
"build/app-rtl.css": "/build/app-rtl.db588f2b.css",
|
||||
"build/app-rtl.js": "/build/app-rtl.97153087.js",
|
||||
"build/export-pdf.css": "/build/export-pdf.d8a6c23b.css",
|
||||
"build/export-pdf.js": "/build/export-pdf.d367a32e.js",
|
||||
"build/export-pdf.js": "/build/export-pdf.1442bee7.js",
|
||||
"build/invoice.css": "/build/invoice.5bea118e.css",
|
||||
"build/invoice.js": "/build/invoice.2604495e.js",
|
||||
"build/invoice.js": "/build/invoice.7ef8a0c8.js",
|
||||
"build/invoice-pdf.css": "/build/invoice-pdf.2b749265.css",
|
||||
"build/invoice-pdf.js": "/build/invoice-pdf.ce9aace0.js",
|
||||
"build/chart.js": "/build/chart.f5becfac.js",
|
||||
"build/invoice-pdf.js": "/build/invoice-pdf.6091a528.js",
|
||||
"build/chart.js": "/build/chart.80ee190c.js",
|
||||
"build/calendar.css": "/build/calendar.bb473428.css",
|
||||
"build/calendar.js": "/build/calendar.d45e4af5.js",
|
||||
"build/calendar.js": "/build/calendar.bb629e51.js",
|
||||
"build/dashboard.css": "/build/dashboard.18f5a8b7.css",
|
||||
"build/dashboard.js": "/build/dashboard.6774a712.js",
|
||||
"build/runtime.js": "/build/runtime.f0079159.js",
|
||||
"build/fonts/fa-solid-900.ttf": "/build/fonts/fa-solid-900.bb5be820.ttf",
|
||||
"build/fonts/fa-brands-400.ttf": "/build/fonts/fa-brands-400.4c05cd9b.ttf",
|
||||
"build/fonts/fa-solid-900.woff2": "/build/fonts/fa-solid-900.4cbe3db2.woff2",
|
||||
"build/fonts/fa-brands-400.woff2": "/build/fonts/fa-brands-400.498f4d22.woff2",
|
||||
"build/fonts/fa-regular-400.ttf": "/build/fonts/fa-regular-400.96e19e1a.ttf",
|
||||
"build/fonts/fa-regular-400.woff2": "/build/fonts/fa-regular-400.83824cd5.woff2"
|
||||
"build/dashboard.js": "/build/dashboard.10118fb0.js",
|
||||
"build/runtime.js": "/build/runtime.74179306.js",
|
||||
"build/fonts/fa-solid-900.ttf": "/build/fonts/fa-solid-900.bacd5de6.ttf",
|
||||
"build/fonts/fa-brands-400.ttf": "/build/fonts/fa-brands-400.60127e35.ttf",
|
||||
"build/fonts/fa-solid-900.woff2": "/build/fonts/fa-solid-900.4d986b00.woff2",
|
||||
"build/fonts/fa-brands-400.woff2": "/build/fonts/fa-brands-400.455ea818.woff2",
|
||||
"build/fonts/fa-regular-400.ttf": "/build/fonts/fa-regular-400.eb91f7b9.ttf",
|
||||
"build/fonts/fa-regular-400.woff2": "/build/fonts/fa-regular-400.21cb8f55.woff2"
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
!function(){"use strict";var e,r={},n={};function t(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={id:e,loaded:!1,exports:{}};return r[e].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}t.m=r,t.amdO={},e=[],t.O=function(r,n,o,i){if(!n){var u=1/0;for(l=0;l<e.length;l++){n=e[l][0],o=e[l][1],i=e[l][2];for(var f=!0,a=0;a<n.length;a++)(!1&i||u>=i)&&Object.keys(t.O).every((function(e){return t.O[e](n[a])}))?n.splice(a--,1):(f=!1,i<u&&(u=i));if(f){e.splice(l--,1);var c=o();void 0!==c&&(r=c)}}return r}i=i||0;for(var l=e.length;l>0&&e[l-1][2]>i;l--)e[l]=e[l-1];e[l]=[n,o,i]},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,{a:r}),r},t.d=function(e,r){for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),t.hmd=function(e){return(e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},function(){var e={666:0};t.O.j=function(r){return 0===e[r]};var r=function(r,n){var o,i,u=n[0],f=n[1],a=n[2],c=0;if(u.some((function(r){return 0!==e[r]}))){for(o in f)t.o(f,o)&&(t.m[o]=f[o]);if(a)var l=a(t)}for(r&&r(n);c<u.length;c++)i=u[c],t.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return t.O(l)},n=self.webpackChunkkimai2=self.webpackChunkkimai2||[];n.forEach(r.bind(null,0)),n.push=r.bind(null,n.push.bind(n))}()}();
|
||||
!function(){"use strict";var e,r={},n={};function t(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={id:e,loaded:!1,exports:{}};return r[e].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}t.m=r,t.amdO={},e=[],t.O=function(r,n,o,i){if(!n){var u=1/0;for(l=0;l<e.length;l++){n=e[l][0],o=e[l][1],i=e[l][2];for(var f=!0,a=0;a<n.length;a++)(!1&i||u>=i)&&Object.keys(t.O).every((function(e){return t.O[e](n[a])}))?n.splice(a--,1):(f=!1,i<u&&(u=i));if(f){e.splice(l--,1);var c=o();void 0!==c&&(r=c)}}return r}i=i||0;for(var l=e.length;l>0&&e[l-1][2]>i;l--)e[l]=e[l-1];e[l]=[n,o,i]},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,{a:r}),r},t.d=function(e,r){for(var n in r)t.o(r,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:r[n]})},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),t.hmd=function(e){return(e=Object.create(e)).children||(e.children=[]),Object.defineProperty(e,"exports",{enumerable:!0,set:function(){throw new Error("ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: "+e.id)}}),e},t.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},t.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},function(){var e={121:0};t.O.j=function(r){return 0===e[r]};var r=function(r,n){var o,i,u=n[0],f=n[1],a=n[2],c=0;if(u.some((function(r){return 0!==e[r]}))){for(o in f)t.o(f,o)&&(t.m[o]=f[o]);if(a)var l=a(t)}for(r&&r(n);c<u.length;c++)i=u[c],t.o(e,i)&&e[i]&&e[i][0](),e[i]=0;return t.O(l)},n=self.webpackChunkkimai2=self.webpackChunkkimai2||[];n.forEach(r.bind(null,0)),n.push=r.bind(null,n.push.bind(n))}()}();
|
||||
@@ -27,7 +27,8 @@ final class ApiRequestMatcher implements RequestMatcherInterface
|
||||
}
|
||||
|
||||
// let's use this firewall if a Bearer token is set in the header
|
||||
if ($request->headers->has('Authorization')) {
|
||||
// other cases like "bearer" are rejected earlier
|
||||
if (($auth = $request->headers->get('Authorization')) !== null && str_starts_with($auth, 'Bearer ')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -232,7 +232,7 @@ final class UserController extends BaseApiController
|
||||
throw $this->createAccessDeniedException('User has no access to API tokens');
|
||||
}
|
||||
|
||||
if ($accessToken->getUser() !== $user) {
|
||||
if (!$this->isGranted('api-token', $accessToken->getUser())) {
|
||||
throw $this->createAccessDeniedException('You are not allowed to delete this access token');
|
||||
}
|
||||
|
||||
|
||||
@@ -40,6 +40,12 @@ final class RegenerateLocalesCommand extends Command
|
||||
* @var string[]
|
||||
*/
|
||||
private array $noRegionCode = ['ar', 'id', 'pa', 'sl'];
|
||||
/**
|
||||
* A list of locales that will be activated, not matter if translation files exist for them.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private array $addLocaleToList = ['zh_Hant_TW'];
|
||||
|
||||
public function __construct(
|
||||
private readonly string $projectDirectory,
|
||||
@@ -74,8 +80,8 @@ final class RegenerateLocalesCommand extends Command
|
||||
foreach ($translationFilenames as $file) {
|
||||
$firstLevelLocales[] = explode('.', basename($file))[1];
|
||||
}
|
||||
$firstLevelLocales = array_unique($firstLevelLocales);
|
||||
$io->title('Locales found from translation files');
|
||||
$firstLevelLocales = array_unique(array_merge($firstLevelLocales, $this->addLocaleToList));
|
||||
$io->title('First level locales found');
|
||||
$io->writeln(implode('|', $firstLevelLocales));
|
||||
|
||||
$secondLevel = [];
|
||||
@@ -95,7 +101,7 @@ final class RegenerateLocalesCommand extends Command
|
||||
sort($firstLevelLocales);
|
||||
sort($secondLevel);
|
||||
|
||||
// keep the locales that have translation filesat the begin
|
||||
// keep the locales that have translation files at the beginning
|
||||
// the config is than easier to read and the locales will be sorted in the UI anyway
|
||||
$locales = array_merge($firstLevelLocales, $secondLevel);
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ class Constants
|
||||
/**
|
||||
* The current release version
|
||||
*/
|
||||
public const VERSION = '2.15.0';
|
||||
public const VERSION = '2.16.0';
|
||||
/**
|
||||
* The current release: major * 10000 + minor * 100 + patch
|
||||
*/
|
||||
public const VERSION_ID = 21500;
|
||||
public const VERSION_ID = 21600;
|
||||
/**
|
||||
* The software name
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace App\Controller;
|
||||
use App\Constants;
|
||||
use App\Utils\PageSetup;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route(path: '/about')]
|
||||
final class AboutController extends AbstractController
|
||||
|
||||
@@ -42,7 +42,7 @@ use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@ use App\Saml\SamlAuthFactory;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Http\SecurityRequestAttributes;
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ use App\Repository\BookmarkRepository;
|
||||
use App\Utils\ProfileManager;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Core\Exception\RuntimeException;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
|
||||
@@ -17,7 +17,7 @@ use App\Timesheet\TrackingModeService;
|
||||
use App\Utils\PageSetup;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,7 +19,7 @@ use App\WorkingTime\WorkingTimeService;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
/**
|
||||
* Users can control their working time statistics
|
||||
|
||||
@@ -43,7 +43,7 @@ use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -21,7 +21,7 @@ use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@ use App\Utils\PageSetup;
|
||||
use App\Utils\ReleaseVersion;
|
||||
use Composer\InstalledVersions;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -19,7 +19,7 @@ use App\Utils\PageSetup;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace App\Controller;
|
||||
use App\Entity\Timesheet;
|
||||
use App\Timesheet\FavoriteRecordService;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/favorite')]
|
||||
|
||||
@@ -19,7 +19,7 @@ use Pagerfanta\Adapter\ArrayAdapter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Intl\Locales;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/help')]
|
||||
|
||||
@@ -16,7 +16,7 @@ use App\Repository\UserRepository;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,7 +45,7 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -27,7 +27,7 @@ use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace App\Controller;
|
||||
use App\Plugin\PluginManager;
|
||||
use App\Utils\PageSetup;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
@@ -43,7 +43,7 @@ use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
@@ -173,7 +173,7 @@ final class ProfileController extends AbstractController
|
||||
$this->flashSuccess('action.update.success');
|
||||
$request->getSession()->set('_show_access_token', $accessToken->getId());
|
||||
|
||||
return new Response();
|
||||
return $this->redirectToRoute('user_profile_api_token', ['username' => $profile->getUserIdentifier()]);
|
||||
}
|
||||
|
||||
return $this->render('user/access-token.html.twig', [
|
||||
|
||||
@@ -47,7 +47,7 @@ use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Csrf\CsrfToken;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -19,7 +19,7 @@ use App\Timesheet\TimesheetService;
|
||||
use App\Utils\PageSetup;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,7 +21,7 @@ use App\Repository\UserRepository;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/reporting/customer/monthly_projects')]
|
||||
|
||||
@@ -18,7 +18,7 @@ use App\Reporting\ProjectDateRange\ProjectDateRangeQuery;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
final class ProjectDateRangeController extends AbstractController
|
||||
|
||||
@@ -17,7 +17,7 @@ use App\Utils\PageSetup;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
final class ProjectDetailsController extends AbstractController
|
||||
|
||||
@@ -16,7 +16,7 @@ use App\Reporting\ProjectInactive\ProjectInactiveQuery;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
final class ProjectInactiveController extends AbstractController
|
||||
|
||||
@@ -16,7 +16,7 @@ use App\Reporting\ProjectView\ProjectViewQuery;
|
||||
use Symfony\Component\ExpressionLanguage\Expression;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
final class ProjectViewController extends AbstractController
|
||||
|
||||
@@ -23,7 +23,7 @@ use App\Timesheet\TimesheetStatisticService;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/reporting/users')]
|
||||
|
||||
@@ -23,7 +23,7 @@ use App\Timesheet\TimesheetStatisticService;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/reporting/users')]
|
||||
|
||||
@@ -24,7 +24,7 @@ use App\Timesheet\TimesheetStatisticService;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/reporting/users')]
|
||||
|
||||
@@ -19,7 +19,7 @@ use Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -113,6 +113,8 @@ final class UserMonthController extends AbstractUserReportController
|
||||
'current' => $start,
|
||||
'next' => $nextMonth,
|
||||
'previous' => $previousMonth,
|
||||
'begin' => $start,
|
||||
'end' => $end,
|
||||
'export_route' => 'report_user_month_export',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ use Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -106,6 +106,8 @@ final class UserWeekController extends AbstractUserReportController
|
||||
'current' => $start,
|
||||
'next' => $next,
|
||||
'previous' => $previous,
|
||||
'begin' => $start,
|
||||
'end' => $end,
|
||||
'export_route' => 'report_user_week_export',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ use Exception;
|
||||
use PhpOffice\PhpSpreadsheet\Reader\Html;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Core\Exception\AccessDeniedException;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
@@ -122,6 +122,8 @@ final class UserYearController extends AbstractUserReportController
|
||||
'current' => $start,
|
||||
'next' => $next,
|
||||
'previous' => $previous,
|
||||
'begin' => $start,
|
||||
'end' => $end,
|
||||
'export_route' => 'report_user_year_export',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace App\Controller;
|
||||
use App\Reporting\ReportingService;
|
||||
use App\Utils\PageSetup;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace App\Controller\Security;
|
||||
|
||||
use App\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
#[Route(path: '/auth/link')]
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace App\Controller\Security;
|
||||
use App\Configuration\SamlConfigurationInterface;
|
||||
use App\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface;
|
||||
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||
use Symfony\Component\Mime\Address;
|
||||
use Symfony\Component\Mime\Email;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
@@ -45,7 +45,7 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
use Symfony\Component\Validator\Constraints\GreaterThanOrEqual;
|
||||
use Symfony\Component\Validator\Constraints\NotBlank;
|
||||
|
||||
@@ -21,7 +21,7 @@ use App\Utils\PageSetup;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/admin/tags')]
|
||||
|
||||
@@ -22,7 +22,7 @@ use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/admin/teams')]
|
||||
|
||||
@@ -16,7 +16,7 @@ use App\Form\TimesheetEditForm;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -24,7 +24,7 @@ use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -30,7 +30,7 @@ use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
/**
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/widgets')]
|
||||
|
||||
@@ -20,7 +20,7 @@ use App\User\UserService;
|
||||
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
|
||||
#[Route(path: '/wizard')]
|
||||
@@ -28,7 +28,6 @@ use Symfony\Component\Security\Http\Attribute\IsGranted;
|
||||
final class WizardController extends AbstractController
|
||||
{
|
||||
#[Route(path: '/{wizard}', name: 'wizard', methods: ['GET', 'POST'])]
|
||||
#[IsGranted('view_own_timesheet')]
|
||||
public function wizard(Request $request, UserService $userService, string $wizard): Response
|
||||
{
|
||||
$user = $this->getUser();
|
||||
|
||||
77
src/Doctrine/UTCDateTimeImmutableType.php
Normal file
77
src/Doctrine/UTCDateTimeImmutableType.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Doctrine;
|
||||
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
use Doctrine\DBAL\Types\ConversionException;
|
||||
use Doctrine\DBAL\Types\DateTimeImmutableType;
|
||||
use Doctrine\DBAL\Types\Types;
|
||||
|
||||
final class UTCDateTimeImmutableType extends DateTimeImmutableType
|
||||
{
|
||||
/**
|
||||
* @var \DateTimeZone|null
|
||||
*/
|
||||
private static ?\DateTimeZone $utc = null;
|
||||
|
||||
/**
|
||||
* @param T $value
|
||||
* @return (T is null ? null : string)
|
||||
* @template T<\DateTimeImmutable>
|
||||
* @throws ConversionException
|
||||
*/
|
||||
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
|
||||
{
|
||||
if ($value instanceof \DateTimeImmutable) {
|
||||
$value = clone $value;
|
||||
$value = $value->setTimezone(self::getUtc());
|
||||
}
|
||||
|
||||
return parent::convertToDatabaseValue($value, $platform);
|
||||
}
|
||||
|
||||
public static function getUtc(): \DateTimeZone
|
||||
{
|
||||
if (self::$utc === null) {
|
||||
self::$utc = new \DateTimeZone('UTC');
|
||||
}
|
||||
|
||||
return self::$utc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @throws ConversionException
|
||||
*/
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform): ?\DateTimeImmutable
|
||||
{
|
||||
if (null === $value || $value instanceof \DateTimeImmutable) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
if (\is_string($value)) {
|
||||
$converted = \DateTimeImmutable::createFromFormat(
|
||||
$platform->getDateTimeFormatString(),
|
||||
$value,
|
||||
self::getUtc()
|
||||
);
|
||||
|
||||
if ($converted !== false) {
|
||||
return $converted;
|
||||
}
|
||||
}
|
||||
|
||||
throw ConversionException::conversionFailedFormat(
|
||||
$value,
|
||||
Types::DATETIME_IMMUTABLE,
|
||||
$platform->getDateTimeFormatString()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -49,8 +49,6 @@ final class UTCDateTimeType extends DateTimeType
|
||||
|
||||
/**
|
||||
* @param mixed $value
|
||||
* @param AbstractPlatform $platform
|
||||
* @return null|\DateTime
|
||||
* @throws ConversionException
|
||||
*/
|
||||
public function convertToPHPValue($value, AbstractPlatform $platform): ?\DateTime
|
||||
@@ -59,20 +57,22 @@ final class UTCDateTimeType extends DateTimeType
|
||||
return $value;
|
||||
}
|
||||
|
||||
$converted = \DateTime::createFromFormat(
|
||||
$platform->getDateTimeFormatString(),
|
||||
$value,
|
||||
self::getUtc()
|
||||
);
|
||||
|
||||
if (!$converted) {
|
||||
throw ConversionException::conversionFailedFormat(
|
||||
if (\is_string($value)) {
|
||||
$converted = \DateTime::createFromFormat(
|
||||
$platform->getDateTimeFormatString(),
|
||||
$value,
|
||||
Types::DATETIME_MUTABLE,
|
||||
$platform->getDateTimeFormatString()
|
||||
self::getUtc()
|
||||
);
|
||||
|
||||
if ($converted !== false) {
|
||||
return $converted;
|
||||
}
|
||||
}
|
||||
|
||||
return $converted;
|
||||
throw ConversionException::conversionFailedFormat(
|
||||
$value,
|
||||
Types::DATETIME_MUTABLE,
|
||||
$platform->getDateTimeFormatString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ class Timesheet implements EntityWithMetaFields, ExportableItem, ModifiedAt
|
||||
#[Assert\NotNull]
|
||||
private ?string $category = self::WORK;
|
||||
#[ORM\Column(name: 'modified_at', type: 'datetime_immutable', nullable: true)]
|
||||
private \DateTimeImmutable $modifiedAt; // @phpstan-ignore-line - create migration and update all null values and then make it not null
|
||||
private \DateTimeImmutable $modifiedAt;
|
||||
/**
|
||||
* Tags
|
||||
*
|
||||
|
||||
@@ -16,15 +16,11 @@ interface MetaDisplayEventInterface
|
||||
{
|
||||
/**
|
||||
* If you want to filter where your meta-field will be displayed, use the query settings.
|
||||
*
|
||||
* @return BaseQuery
|
||||
*/
|
||||
public function getQuery(): BaseQuery;
|
||||
|
||||
/**
|
||||
* If you want to filter where your meta-field will be displayed, check the current location.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLocation(): string;
|
||||
|
||||
@@ -35,9 +31,6 @@ interface MetaDisplayEventInterface
|
||||
|
||||
/**
|
||||
* Adds a field that should be displayed.
|
||||
*
|
||||
* @param MetaTableTypeInterface $meta
|
||||
* @return void
|
||||
*/
|
||||
public function addField(MetaTableTypeInterface $meta) /* : void */;
|
||||
public function addField(MetaTableTypeInterface $meta): void;
|
||||
}
|
||||
|
||||
41
src/EventSubscriber/LogoutSubscriber.php
Normal file
41
src/EventSubscriber/LogoutSubscriber.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\EventSubscriber;
|
||||
|
||||
use App\Security\SessionHandler;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\Security\Http\Event\LogoutEvent;
|
||||
|
||||
final class LogoutSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
public function __construct(
|
||||
private readonly SessionHandler $sessionHandler,
|
||||
private readonly LoggerInterface $logger
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents(): array
|
||||
{
|
||||
return [
|
||||
LogoutEvent::class => 'onLogout',
|
||||
];
|
||||
}
|
||||
|
||||
public function onLogout(LogoutEvent $event): void
|
||||
{
|
||||
try {
|
||||
$this->sessionHandler->garbageCollection();
|
||||
} catch (\Exception $exception) {
|
||||
$this->logger->error('Failed removing expired session: ' . $exception->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
32
src/Export/Spreadsheet/CellFormatter/StringFormatter.php
Normal file
32
src/Export/Spreadsheet/CellFormatter/StringFormatter.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Export\Spreadsheet\CellFormatter;
|
||||
|
||||
use App\Utils\StringHelper;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\CellAddress;
|
||||
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;
|
||||
|
||||
final class StringFormatter implements CellFormatterInterface
|
||||
{
|
||||
public function setFormattedValue(Worksheet $sheet, int $column, int $row, $value): void
|
||||
{
|
||||
if (null === $value) {
|
||||
$sheet->setCellValue(CellAddress::fromColumnAndRow($column, $row), '');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!\is_string($value)) {
|
||||
throw new \InvalidArgumentException('Unsupported value given, only string is supported');
|
||||
}
|
||||
|
||||
$sheet->setCellValue(CellAddress::fromColumnAndRow($column, $row), StringHelper::sanitizeDDE($value));
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ use App\Export\Spreadsheet\CellFormatter\CellFormatterInterface;
|
||||
use App\Export\Spreadsheet\CellFormatter\DateFormatter;
|
||||
use App\Export\Spreadsheet\CellFormatter\DateTimeFormatter;
|
||||
use App\Export\Spreadsheet\CellFormatter\DurationFormatter;
|
||||
use App\Export\Spreadsheet\CellFormatter\StringFormatter;
|
||||
use App\Export\Spreadsheet\CellFormatter\TimeFormatter;
|
||||
use PhpOffice\PhpSpreadsheet\Cell\CellAddress;
|
||||
use PhpOffice\PhpSpreadsheet\Spreadsheet;
|
||||
@@ -30,7 +31,7 @@ class SpreadsheetExporter
|
||||
*/
|
||||
private array $formatter = [];
|
||||
|
||||
public function __construct(private TranslatorInterface $translator)
|
||||
public function __construct(private readonly TranslatorInterface $translator)
|
||||
{
|
||||
$this->registerCellFormatter('datetime', new DateTimeFormatter());
|
||||
$this->registerCellFormatter('date', new DateFormatter());
|
||||
@@ -38,6 +39,7 @@ class SpreadsheetExporter
|
||||
$this->registerCellFormatter('duration', new DurationFormatter());
|
||||
$this->registerCellFormatter('boolean', new BooleanFormatter());
|
||||
$this->registerCellFormatter('array', new ArrayFormatter());
|
||||
$this->registerCellFormatter('string', new StringFormatter());
|
||||
}
|
||||
|
||||
public function registerCellFormatter(string $type, CellFormatterInterface $formatter): void
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user