[3.0] Update Symfony to 7.4 and dependencies, removed deprecated code, removed API password (#5622)

* deactivate deprecated auto-mapping
* use native month-picker with fallback on old browser
* bump dependencies to new major versions
* replace deprecated ARRAY column type with JSON
* named arguments
* nullable arguments
* native lazy ghosts
* update routes to use php config
* disable PHP < 8.4
* use static RTL configuration
* new qr code package
* clear out env file
* recipe updates
* fix deprecations
* preset new env variable if not existing
* bump maria db version examples
* remove deprecated api-token support
* fix validator deprecations
* remove timesheet category column
* fix broken validator autoconfiguration
* stabilize tests
* fix migration syntax compatibility
* fix doctrine deprecation
* fix datetime format
* remove constructor dependency
* only include visible preferences in invoice templates
* fix test container dependency
* removed ProjectConstraint multi-constraint logic
* allow to disable plugins in certain environments
* refactor TimesheetConstraint to non-service
* activate new interface methods
* prevent update issues with .env
* improved customer fixture
* removed $user->isExportDecimal()
This commit is contained in:
Kevin Papst
2026-01-04 15:04:25 +01:00
committed by GitHub
parent 9e87fc131b
commit 677f8d776c
467 changed files with 3929 additions and 6567 deletions

View File

@@ -51,20 +51,20 @@ use Symfony\Component\Validator\Constraints as Assert;
#[Constraints\User(groups: ['UserCreate', 'Registration', 'Default', 'Profile'])]
class User implements UserInterface, EquatableInterface, ThemeUserInterface, PasswordAuthenticatedUserInterface, TwoFactorInterface
{
public const ROLE_USER = 'ROLE_USER';
public const ROLE_TEAMLEAD = 'ROLE_TEAMLEAD';
public const ROLE_ADMIN = 'ROLE_ADMIN';
public const ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
public const string ROLE_USER = 'ROLE_USER';
public const string ROLE_TEAMLEAD = 'ROLE_TEAMLEAD';
public const string ROLE_ADMIN = 'ROLE_ADMIN';
public const string ROLE_SUPER_ADMIN = 'ROLE_SUPER_ADMIN';
public const DEFAULT_ROLE = self::ROLE_USER;
public const DEFAULT_LANGUAGE = 'en';
public const DEFAULT_FIRST_WEEKDAY = 'monday';
public const string DEFAULT_ROLE = self::ROLE_USER;
public const string DEFAULT_LANGUAGE = 'en';
public const string DEFAULT_FIRST_WEEKDAY = 'monday';
public const AUTH_INTERNAL = 'kimai';
public const AUTH_LDAP = 'ldap';
public const AUTH_SAML = 'saml';
public const string AUTH_INTERNAL = 'kimai';
public const string AUTH_LDAP = 'ldap';
public const string AUTH_SAML = 'saml';
public const WIZARDS = ['intro', 'profile'];
public const array WIZARDS = ['intro', 'profile'];
/**
* Unique User ID
@@ -108,17 +108,6 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
#[Serializer\Expose]
#[Serializer\Groups(['Default'])]
private ?string $avatar = null;
/**
* API token (password) for this user
*/
#[ORM\Column(name: 'api_token', type: Types::STRING, length: 255, nullable: true)]
private ?string $apiToken = null;
/**
* @internal to be set via form, must not be persisted
*/
#[Assert\NotBlank(groups: ['ApiTokenUpdate'])]
#[Assert\Length(min: 8, max: 60, groups: ['ApiTokenUpdate'])]
private ?string $plainApiToken = null;
/**
* User preferences
*
@@ -206,7 +195,7 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
/**
* List of all role names
*/
#[ORM\Column(name: 'roles', type: Types::ARRAY, nullable: false)] // @phpstan-ignore classConstant.deprecated
#[ORM\Column(name: 'roles', type: Types::JSON, nullable: false)]
#[Serializer\Expose]
#[Serializer\Groups(['User_Entity'])]
#[Serializer\Type('array<string>')]
@@ -293,41 +282,6 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
return $this;
}
public function getApiToken(): ?string
{
return $this->apiToken;
}
public function setApiToken(?string $apiToken): User
{
$this->apiToken = $apiToken;
return $this;
}
/**
* @deprecated since 2.15
*/
#[Serializer\VirtualProperty]
#[Serializer\SerializedName('apiToken')]
#[Serializer\Groups(['Default'])]
public function hasApiToken(): bool
{
return $this->apiToken !== null;
}
public function getPlainApiToken(): ?string
{
return $this->plainApiToken;
}
public function setPlainApiToken(?string $plainApiToken): User
{
$this->plainApiToken = $plainApiToken;
return $this;
}
/**
* Read-only list of all visible user preferences.
*
@@ -351,7 +305,6 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
'login_initial_view',
'update_browser_title',
'daily_stats',
'export_decimal',
];
$all = [];
@@ -473,14 +426,6 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
return $this->getPreferenceValue(UserPreference::FIRST_WEEKDAY, User::DEFAULT_FIRST_WEEKDAY, false);
}
/**
* @ deprecated since 2.40 - will be removed with 3.0
*/
public function isExportDecimal(): bool
{
return (bool) $this->getPreferenceValue('export_decimal', false, false);
}
public function getSkin(): string
{
return (string) $this->getPreferenceValue(UserPreference::SKIN, 'default', false);
@@ -819,10 +764,9 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
}
}
#[\Deprecated]
public function eraseCredentials(): void
{
$this->plainPassword = null;
$this->plainApiToken = null;
}
public function hasUsername(): bool
@@ -845,7 +789,7 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
public function getUserIdentifier(): string
{
return $this->getUsername();
return $this->getUsername(); // @phpstan-ignore return.type
}
public function getEmail(): ?string
@@ -924,8 +868,9 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
/**
* Alias for setUserIdentifier()
*
* The visible username is setAlias())
*
* Cannot be deleted, referenced in SAML configurations and API.
*/
public function setUsername(string $username): void
{
@@ -934,7 +879,7 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
public function setUserIdentifier(string $identifier): void
{
$this->setUsername($identifier);
$this->username = $identifier;
}
public function setEmail(?string $email): User
@@ -956,14 +901,14 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
return $this;
}
public function setPassword($password): User
public function setPassword(?string $password): User
{
$this->password = $password;
return $this;
}
public function setPlainPassword($password): User
public function setPlainPassword(?string $password): User
{
$this->plainPassword = $password;
@@ -977,7 +922,7 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
return $this;
}
public function setConfirmationToken($confirmationToken): void
public function setConfirmationToken(?string $confirmationToken): void
{
$this->confirmationToken = $confirmationToken;
}
@@ -1036,6 +981,8 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
public function __serialize(): array
{
$this->plainPassword = null;
return [
'id' => $this->id,
'username' => $this->username,
@@ -1216,62 +1163,6 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
return new TotpConfiguration($this->totpSecret, TotpConfiguration::ALGORITHM_SHA1, 30, 6);
}
/**
* @deprecated since 2.22.0
*/
public function getWorkHoursMonday(): int
{
return (int) $this->getPreferenceValue(UserPreference::WORK_HOURS_MONDAY, 0);
}
/**
* @deprecated since 2.22.0
*/
public function getWorkHoursTuesday(): int
{
return (int) $this->getPreferenceValue(UserPreference::WORK_HOURS_TUESDAY, 0);
}
/**
* @deprecated since 2.22.0
*/
public function getWorkHoursWednesday(): int
{
return (int) $this->getPreferenceValue(UserPreference::WORK_HOURS_WEDNESDAY, 0);
}
/**
* @deprecated since 2.22.0
*/
public function getWorkHoursThursday(): int
{
return (int) $this->getPreferenceValue(UserPreference::WORK_HOURS_THURSDAY, 0);
}
/**
* @deprecated since 2.22.0
*/
public function getWorkHoursFriday(): int
{
return (int) $this->getPreferenceValue(UserPreference::WORK_HOURS_FRIDAY, 0);
}
/**
* @deprecated since 2.22.0
*/
public function getWorkHoursSaturday(): int
{
return (int) $this->getPreferenceValue(UserPreference::WORK_HOURS_SATURDAY, 0);
}
/**
* @deprecated since 2.22.0
*/
public function getWorkHoursSunday(): int
{
return (int) $this->getPreferenceValue(UserPreference::WORK_HOURS_SUNDAY, 0);
}
public function getWorkStartingDay(): ?\DateTimeInterface
{
return $this->getPreferenceDate('work_start_day');
@@ -1322,62 +1213,6 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
return $this->getFormattedHoliday(is_numeric($holidays) ? $holidays : 0.0);
}
/**
* @deprecated since 2.22.0
*/
public function setWorkHoursMonday(?int $seconds): void
{
$this->setPreferenceValue(UserPreference::WORK_HOURS_MONDAY, $seconds ?? 0);
}
/**
* @deprecated since 2.22.0
*/
public function setWorkHoursTuesday(?int $seconds): void
{
$this->setPreferenceValue(UserPreference::WORK_HOURS_TUESDAY, $seconds ?? 0);
}
/**
* @deprecated since 2.22.0
*/
public function setWorkHoursWednesday(?int $seconds): void
{
$this->setPreferenceValue(UserPreference::WORK_HOURS_WEDNESDAY, $seconds ?? 0);
}
/**
* @deprecated since 2.22.0
*/
public function setWorkHoursThursday(?int $seconds): void
{
$this->setPreferenceValue(UserPreference::WORK_HOURS_THURSDAY, $seconds ?? 0);
}
/**
* @deprecated since 2.22.0
*/
public function setWorkHoursFriday(?int $seconds): void
{
$this->setPreferenceValue(UserPreference::WORK_HOURS_FRIDAY, $seconds ?? 0);
}
/**
* @deprecated since 2.22.0
*/
public function setWorkHoursSaturday(?int $seconds): void
{
$this->setPreferenceValue(UserPreference::WORK_HOURS_SATURDAY, $seconds ?? 0);
}
/**
* @deprecated since 2.22.0
*/
public function setWorkHoursSunday(?int $seconds): void
{
$this->setPreferenceValue(UserPreference::WORK_HOURS_SUNDAY, $seconds ?? 0);
}
public function setPublicHolidayGroup(null|string $group = null): void
{
$this->setPreferenceValue(UserPreference::PUBLIC_HOLIDAY_GROUP, $group);
@@ -1402,44 +1237,11 @@ class User implements UserInterface, EquatableInterface, ThemeUserInterface, Pas
return (float) number_format((round($holidays * 2) / 2), 1);
}
/**
* @deprecated since 2.22.0
*/
public function hasContractSettings(): bool
{
return $this->hasWorkHourConfiguration() || $this->getHolidaysPerYear() !== 0.0;
}
public function hasWorkHourConfiguration(): bool
{
return $this->getWorkContractMode() !== WorkingTimeModeNone::ID;
}
/**
* @deprecated since 2.22.0
*/
public function getWorkHoursForDay(\DateTimeInterface $dateTime): int
{
return match ($dateTime->format('N')) {
'1' => $this->getWorkHoursMonday(),
'2' => $this->getWorkHoursTuesday(),
'3' => $this->getWorkHoursWednesday(),
'4' => $this->getWorkHoursThursday(),
'5' => $this->getWorkHoursFriday(),
'6' => $this->getWorkHoursSaturday(),
'7' => $this->getWorkHoursSunday(),
default => throw new \Exception('Unknown day: ' . $dateTime->format('Y-m-d'))
};
}
/**
* @deprecated since 2.22.0
*/
public function isWorkDay(\DateTimeInterface $dateTime): bool
{
return $this->getWorkHoursForDay($dateTime) > 0;
}
public function hasSupervisor(): bool
{
return $this->supervisor !== null;