Skip to content

Commit 5309cd9

Browse files
authored
Simplify user:login with less options and dependencies (#6501)
More DI
1 parent 032a019 commit 5309cd9

2 files changed

Lines changed: 37 additions & 72 deletions

File tree

src/Commands/user/UserLoginCommand.php

Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,12 @@
44

55
namespace Drush\Commands\user;
66

7-
use Consolidation\SiteAlias\SiteAliasManagerInterface;
7+
use Drupal\Component\Datetime\TimeInterface;
8+
use Drupal\Core\Language\LanguageManagerInterface;
89
use Drupal\Core\Url;
910
use Drupal\user\Entity\User;
10-
use Drush\Attributes as CLI;
11-
use Drush\Boot\BootstrapManager;
12-
use Drush\Boot\DrupalBootLevels;
1311
use Drush\Commands\AutowireTrait;
14-
use Drush\Drush;
1512
use Drush\Exec\ExecTrait;
16-
use Drush\SiteAlias\ProcessManager;
1713
use Symfony\Component\Console\Attribute\AsCommand;
1814
use Symfony\Component\Console\Command\Command;
1915
use Symfony\Component\Console\Input\InputArgument;
@@ -26,8 +22,6 @@
2622
description: 'Display a one time login link for user ID 1, or another user.',
2723
aliases: ['uli', 'user-login'],
2824
)]
29-
#[CLI\Bootstrap(DrupalBootLevels::NONE)]
30-
#[CLI\HandleRemoteCommands]
3125
final class UserLoginCommand extends Command
3226
{
3327
use AutowireTrait;
@@ -36,9 +30,8 @@ final class UserLoginCommand extends Command
3630
public const string NAME = 'user:login';
3731

3832
public function __construct(
39-
private readonly BootstrapManager $bootstrapManager,
40-
protected readonly ProcessManager $processManager,
41-
private readonly SiteAliasManagerInterface $siteAliasManager
33+
protected readonly LanguageManagerInterface $languageManager,
34+
protected readonly TimeInterface $time,
4235
) {
4336
parent::__construct();
4437
}
@@ -50,8 +43,6 @@ protected function configure(): void
5043
->addOption('name', null, InputOption::VALUE_REQUIRED, 'A user name to log in as.')
5144
->addOption('uid', null, InputOption::VALUE_REQUIRED, 'A user ID to log in as.')
5245
->addOption('mail', null, InputOption::VALUE_REQUIRED, 'A user email to log in as.')
53-
->addOption('browser', null, InputOption::VALUE_NEGATABLE, 'Open the URL in the default browser. Use --no-browser to avoid opening a browser.', true)
54-
->addOption('redirect-port', null, InputOption::VALUE_REQUIRED, 'A custom port for redirecting to (e.g., when running within a Vagrant environment)')
5546
->addUsage('user:login --name=ryan node/add/blog')
5647
->addUsage('user:login --uid=123')
5748
->addUsage('user:login --mail=foo@bar.com')
@@ -61,62 +52,43 @@ protected function configure(): void
6152
public function execute(InputInterface $input, OutputInterface $output): int
6253
{
6354
$path = $input->getArgument('path');
64-
// Redispatch if called against a remote-host so a browser is started on the *local* machine.
65-
$aliasRecord = $this->siteAliasManager->getSelf();
66-
if ($this->processManager->hasTransport($aliasRecord)) {
67-
$process = $this->processManager->drush($aliasRecord, self::NAME, [$path], Drush::redispatchOptions());
68-
$process->mustRun();
69-
$link = $process->getOutput();
70-
} else {
71-
if (!$this->bootstrapManager->doBootstrap(DrupalBootLevels::FULL)) {
72-
throw new \Exception('Unable to bootstrap Drupal.');
73-
}
74-
75-
$account = null;
76-
if ($input->getOption('name') && !$account = user_load_by_name($input->getOption('name'))) {
77-
throw new \Exception(sprintf('Unable to load user by name: %s', $input->getOption('name')));
78-
}
79-
80-
if ($input->getOption('uid') && !$account = User::load($input->getOption('uid'))) {
81-
throw new \Exception(sprintf('Unable to load user by uid: %s', $input->getOption('uid')));
82-
}
55+
$account = null;
56+
if ($input->getOption('name') && !$account = user_load_by_name($input->getOption('name'))) {
57+
throw new \Exception(sprintf('Unable to load user by name: %s', $input->getOption('name')));
58+
}
8359

84-
if ($input->getOption('mail') && !$account = user_load_by_mail($input->getOption('mail'))) {
85-
throw new \Exception(sprintf('Unable to load user by mail: %s', $input->getOption('mail')));
86-
}
60+
if ($input->getOption('uid') && !$account = User::load($input->getOption('uid'))) {
61+
throw new \Exception(sprintf('Unable to load user by uid: %s', $input->getOption('uid')));
62+
}
8763

88-
if (empty($account)) {
89-
$account = User::load(1);
90-
}
64+
if ($input->getOption('mail') && !$account = user_load_by_mail($input->getOption('mail'))) {
65+
throw new \Exception(sprintf('Unable to load user by mail: %s', $input->getOption('mail')));
66+
}
9167

92-
if ($account->isBlocked()) {
93-
throw new \InvalidArgumentException('Account %s is blocked and thus cannot login. The user:unblock command may be helpful.', $account->getAccountName());
94-
}
68+
if (empty($account)) {
69+
$account = User::load(1);
70+
}
9571

96-
// Can't inject dependency because this command instantiates without a bootstrap.
97-
$timestamp = \Drupal::time()->getRequestTime();
98-
$link = Url::fromRoute(
99-
'user.reset.login',
100-
[
101-
'uid' => $account->id(),
102-
'timestamp' => $timestamp,
103-
'hash' => user_pass_rehash($account, $timestamp),
104-
],
105-
[
106-
'absolute' => true,
107-
'query' => $path ? ['destination' => $path] : [],
108-
// Can't inject dependency because this command instantiates without a bootstrap.
109-
'language' => \Drupal::languageManager()->getLanguage($account->getPreferredLangcode()),
110-
]
111-
)->toString();
72+
if ($account->isBlocked()) {
73+
throw new \InvalidArgumentException('Account %s is blocked and thus cannot login. The user:unblock command may be helpful.', $account->getAccountName());
11274
}
113-
$port = $input->getOption('redirect-port');
114-
// $browser = $input->getOption('browser');
115-
// if (is_null($browser) && !str_contains(strval($input), '--browser')) {
116-
// // WHen user doesn't specify, we have always represented that with true.
117-
// $browser = true;
118-
// }
119-
$this->startBrowser($link, 0, $port, $input->getOption('browser'));
75+
76+
// Can't inject dependency because this command instantiates without a bootstrap.
77+
$timestamp = $this->time->getRequestTime();
78+
$link = Url::fromRoute(
79+
'user.reset.login',
80+
[
81+
'uid' => $account->id(),
82+
'timestamp' => $timestamp,
83+
'hash' => user_pass_rehash($account, $timestamp),
84+
],
85+
[
86+
'absolute' => true,
87+
'query' => $path ? ['destination' => $path] : [],
88+
// Can't inject dependency because this command instantiates without a bootstrap.
89+
'language' => $this->languageManager->getLanguage($account->getPreferredLangcode()),
90+
]
91+
)->toString();
12092
$output->writeln($link);
12193
return self::SUCCESS;
12294
}

tests/functional/UserTest.php

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44

55
namespace Unish;
66

7-
use PHPUnit\Framework\Attributes\Group;
87
use Drush\Commands\core\PhpCommands;
98
use Drush\Commands\core\RoleCommands;
109
use Drush\Commands\core\UserCommands;
1110
use Drush\Commands\pm\PmCommands;
1211
use Drush\Commands\user\UserLoginCommand;
12+
use PHPUnit\Framework\Attributes\Group;
1313
use Symfony\Component\Filesystem\Path;
1414

1515
#[Group('slow')]
@@ -124,13 +124,6 @@ public function testUserPassword(): void
124124
$this->assertStringContainsString('2', $output, 'User can login with new password.');
125125
}
126126

127-
public function testUserLoginNoBootstrappedSite(): never
128-
{
129-
$this->markTestSkipped('TODO: @none should prevent selection of site at cwd');
130-
// Check if user-login on a non-bootstrapped environment returns error.
131-
$this->drush(UserLoginCommand::NAME, [], [], '@none', null, self::EXIT_ERROR);
132-
}
133-
134127
public function testUserLogin(): void
135128
{
136129
// Check user-login

0 commit comments

Comments
 (0)