Release 2.37 (#5546)

This commit is contained in:
Kevin Papst
2025-07-04 16:43:38 +02:00
committed by GitHub
parent 06b3060fe1
commit dfec807166
52 changed files with 602 additions and 352 deletions

View File

@@ -20,19 +20,16 @@ use Symfony\Component\Console\Style\SymfonyStyle;
abstract class AbstractRoleCommand extends Command
{
public function __construct(private UserService $userService)
public function __construct(private readonly UserService $userService)
{
parent::__construct();
}
protected function configure(): void
{
$this
->setDefinition([
new InputArgument('username', InputArgument::REQUIRED, 'The username'),
new InputArgument('role', InputArgument::OPTIONAL, 'The role'),
new InputOption('super', null, InputOption::VALUE_NONE, 'Instead specifying role, use this to quickly add the super administrator role'),
]);
$this->addArgument('username', InputArgument::REQUIRED, 'The username');
$this->addArgument('role', InputArgument::OPTIONAL, 'The role');
$this->addOption('super', null, InputOption::VALUE_NONE, 'Instead specifying role, use this to quickly add the super administrator role');
}
protected function execute(InputInterface $input, OutputInterface $output): int

View File

@@ -26,7 +26,7 @@ abstract class AbstractUserCommand extends Command
$passwordQuestion = new Question('Please enter the password: ');
$passwordQuestion->setHidden(true);
$passwordQuestion->setHiddenFallback(false);
$passwordQuestion->setHiddenFallback(true);
$passwordQuestion->setValidator(function (?string $value) {
$password = trim($value);
if (empty($password)) {

View File

@@ -17,7 +17,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'kimai:user:activate')]
#[AsCommand(name: 'kimai:user:activate', description: 'Activate a user')]
final class ActivateUserCommand extends Command
{
public function __construct(private UserService $userService)
@@ -28,10 +28,7 @@ final class ActivateUserCommand extends Command
protected function configure(): void
{
$this
->setDescription('Activate a user')
->setDefinition([
new InputArgument('username', InputArgument::REQUIRED, 'The username'),
])
->addArgument('username', InputArgument::REQUIRED, 'The username')
->setHelp(
<<<'EOT'
The <info>kimai:user:activate</info> command activates a user (so they will be able to log in):

View File

@@ -18,7 +18,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'kimai:user:password')]
#[AsCommand(name: 'kimai:user:password', description: 'Change the password of a user')]
final class ChangePasswordCommand extends AbstractUserCommand
{
public function __construct(private UserService $userService)
@@ -29,11 +29,8 @@ final class ChangePasswordCommand extends AbstractUserCommand
protected function configure(): void
{
$this
->setDescription('Change the password of a user.')
->setDefinition([
new InputArgument('username', InputArgument::REQUIRED, 'The username'),
new InputArgument('password', InputArgument::OPTIONAL, 'The password'),
])
->addArgument('username', InputArgument::REQUIRED, 'The username')
->addArgument('password', InputArgument::OPTIONAL, 'The password')
->setHelp(
<<<'EOT'
The <info>kimai:user:password</info> command changes the password of a user:

View File

@@ -20,7 +20,7 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'kimai:user:create')]
#[AsCommand(name: 'kimai:user:create', description: 'Create a new user')]
final class CreateUserCommand extends AbstractUserCommand
{
public function __construct(private UserService $userService)
@@ -33,7 +33,6 @@ final class CreateUserCommand extends AbstractUserCommand
$roles = implode(',', [User::DEFAULT_ROLE, User::ROLE_ADMIN]);
$this
->setDescription('Create a new user')
->setHelp('This command allows you to create a new user.')
->addArgument('username', InputArgument::REQUIRED, 'A name for the new user (must be unique)')
->addArgument('email', InputArgument::REQUIRED, 'Email address of the new user (must be unique)')

View File

@@ -17,7 +17,7 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'kimai:user:deactivate')]
#[AsCommand(name: 'kimai:user:deactivate', description: 'Deactivate a user')]
final class DeactivateUserCommand extends Command
{
public function __construct(private UserService $userService)
@@ -28,10 +28,7 @@ final class DeactivateUserCommand extends Command
protected function configure(): void
{
$this
->setDescription('Deactivate a user')
->setDefinition([
new InputArgument('username', InputArgument::REQUIRED, 'The username'),
])
->addArgument('username', InputArgument::REQUIRED, 'The username')
->setHelp(
<<<'EOT'
The <info>kimai:user:deactivate</info> command deactivates a user (will not be able to log in)

View File

@@ -14,7 +14,7 @@ use App\User\UserService;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'kimai:user:demote')]
#[AsCommand(name: 'kimai:user:demote', description: 'Demote a user by removing a role')]
final class DemoteUserCommand extends AbstractRoleCommand
{
protected function configure(): void
@@ -22,7 +22,6 @@ final class DemoteUserCommand extends AbstractRoleCommand
parent::configure();
$this
->setDescription('Demote a user by removing a role')
->setHelp(
<<<'EOT'
The <info>kimai:user:demote</info> command demotes a user by removing a role

View File

@@ -31,7 +31,7 @@ use Symfony\Component\Mailer\MailerInterface;
use Symfony\Contracts\Translation\LocaleAwareInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
#[AsCommand(name: 'kimai:export:create')]
#[AsCommand(name: 'kimai:export:create', description: 'Create exports')]
final class ExportCreateCommand extends Command
{
public function __construct(
@@ -49,7 +49,6 @@ final class ExportCreateCommand extends Command
protected function configure(): void
{
$this
->setDescription('Create exports')
->setHelp('Create exports by several different filters and sent them via email.')
->addOption('username', null, InputOption::VALUE_REQUIRED, 'The user to be used for generating the export (e.g. used for permissions and decimal setting)')
->addOption('start', null, InputOption::VALUE_OPTIONAL, 'Start date (format: 2020-01-01, default: start of the month)', null)

View File

@@ -34,7 +34,7 @@ use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;
#[AsCommand(name: 'kimai:invoice:create')]
#[AsCommand(name: 'kimai:invoice:create', description: 'Create invoices')]
final class InvoiceCreateCommand extends Command
{
private ?string $previewDirectory = null;
@@ -54,7 +54,6 @@ final class InvoiceCreateCommand extends Command
protected function configure(): void
{
$this
->setDescription('Create invoices')
->setHelp('This command allows to create invoices by several different filters.')
->addOption('user', null, InputOption::VALUE_REQUIRED, 'The user to be used for generating the invoices')
->addOption('start', null, InputOption::VALUE_OPTIONAL, 'Start date (format: 2020-01-01, default: start of the month)', null)

View File

@@ -16,7 +16,6 @@ use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Mime\Email;
@@ -31,7 +30,6 @@ final class MailTestCommand extends Command
protected function configure(): void
{
$this->addArgument('to', InputArgument::REQUIRED, 'The email address to send the email to');
$this->addOption('from', null, InputOption::VALUE_OPTIONAL, 'Deprecated: uses the MAILER_FROM env variable.');
}
protected function execute(InputInterface $input, OutputInterface $output): int
@@ -41,10 +39,6 @@ final class MailTestCommand extends Command
throw new \InvalidArgumentException('Need a non-empty "to" address');
}
if ($input->getOption('from') !== null) {
throw new \InvalidArgumentException('The "from" option is deprecated and will be ignored');
}
$message = new Email();
$message->to($to);
$message->subject('Test email - ' . Constants::SOFTWARE);

View File

@@ -14,7 +14,7 @@ use App\User\UserService;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'kimai:user:promote')]
#[AsCommand(name: 'kimai:user:promote', description: 'Promotes a user by adding a role')]
final class PromoteUserCommand extends AbstractRoleCommand
{
protected function configure(): void
@@ -22,7 +22,6 @@ final class PromoteUserCommand extends AbstractRoleCommand
parent::configure();
$this
->setDescription('Promotes a user by adding a role')
->setHelp(
<<<'EOT'
The <info>kimai:user:promote</info> command promotes a user by adding a role

View File

@@ -19,19 +19,14 @@ use Symfony\Component\Console\Style\SymfonyStyle;
/**
* @codeCoverageIgnore
*/
#[AsCommand(name: 'kimai:timesheet:stop-all')]
#[AsCommand(name: 'kimai:timesheet:stop-all', description: 'Stop all running timesheets immediately')]
final class TimesheetStopAllCommand extends Command
{
public function __construct(private TimesheetService $timesheetService)
public function __construct(private readonly TimesheetService $timesheetService)
{
parent::__construct();
}
protected function configure(): void
{
$this->setDescription('Stop all running timesheets immediately');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$amount = $this->timesheetService->stopAll();

View File

@@ -25,7 +25,7 @@ use Symfony\Component\HttpClient\HttpClient;
*
* @codeCoverageIgnore
*/
#[AsCommand(name: 'kimai:translations')]
#[AsCommand(name: 'kimai:translations', description: 'Automated translation adjustments')]
final class TranslationCommand extends Command
{
public function __construct(
@@ -40,7 +40,6 @@ final class TranslationCommand extends Command
protected function configure(): void
{
$this
->setDescription('Translation adjustments')
->addOption('resname', null, InputOption::VALUE_NONE, 'Fix the resname vs. id attribute')
->addOption('duplicates', null, InputOption::VALUE_NONE, 'Find duplicate translation keys')
->addOption('delete-resname', null, InputOption::VALUE_REQUIRED, 'Deletes the translation by resname')

View File

@@ -17,17 +17,14 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(name: 'kimai:version')]
#[AsCommand(name: 'kimai:version', description: 'Show version information')]
final class VersionCommand extends Command
{
protected function configure(): void
{
$this
->setDescription('Receive version information')
->setHelp('This command allows you to fetch various version information about Kimai.')
->addOption('short', null, InputOption::VALUE_NONE, 'Display the version only')
->addOption('number', null, InputOption::VALUE_NONE, 'Display the version identifier only only')
;
$this->setHelp('This command allows you to fetch various version information about Kimai.');
$this->addOption('short', null, InputOption::VALUE_NONE, 'Display the version only');
$this->addOption('number', null, InputOption::VALUE_NONE, 'Display the version identifier only only');
}
protected function execute(InputInterface $input, OutputInterface $output): int