2 namespace Drush\Drupal\Commands\core;
4 use Consolidation\AnnotatedCommand\CommandData;
5 use Consolidation\AnnotatedCommand\CommandError;
6 use Consolidation\OutputFormatters\Options\FormatterOptions;
7 use Consolidation\OutputFormatters\StructuredData\RowsOfFields;
8 use Drupal\user\Entity\User;
9 use Drush\Commands\DrushCommands;
11 use Drush\Utils\StringUtils;
13 class UserCommands extends DrushCommands
17 * Print information about the specified user(s).
19 * @command user:information
21 * @param string $names A comma delimited list of user names.
22 * @option $uid A comma delimited list of user ids to lookup (an alternative to names).
23 * @option $mail A comma delimited list of emails to lookup (an alternative to names).
24 * @aliases uinf,user-information
25 * @usage drush user:information someguy,somegal
26 * Display information about the someguy and somegal user accounts.
27 * @usage drush user:information --mail=someguy@somegal.com
28 * Display information for a given email account.
29 * @usage drush user:information --uid=5
30 * Display information for a given user id.
37 * signature: Signature
38 * signature_format: Signature format
39 * user_created: User created
41 * user_access: User last access
43 * user_login: User last login
45 * user_status: User status
48 * picture: User picture
49 * init: Initial user mail
51 * group_audience: Group Audience
52 * langcode: Language code
54 * @table-style default
55 * @default-fields uid,name,mail,roles,user_status
57 * @return \Consolidation\OutputFormatters\StructuredData\RowsOfFields
59 public function information($names = '', $options = ['format' => 'table', 'uid' => self::REQ, 'mail' => self::REQ])
62 if ($mails = StringUtils::csvToArray($options['mail'])) {
63 foreach ($mails as $mail) {
64 if ($account = user_load_by_mail($mail)) {
65 $accounts[$account->id()] = $account;
69 if ($uids = StringUtils::csvToArray($options['uid'])) {
70 if ($loaded = User::loadMultiple($uids)) {
74 if ($names = StringUtils::csvToArray($names)) {
75 foreach ($names as $name) {
76 if ($account = user_load_by_name($name)) {
77 $accounts[$account->id()] = $account;
81 if (empty($accounts)) {
82 throw new \Exception(dt('Unable to find a matching user'));
85 foreach ($accounts as $id => $account) {
86 $outputs[$id] = $this->infoArray($account);
89 $result = new RowsOfFields($outputs);
90 $result->addRendererFunction([$this, 'renderRolesCell']);
94 public function renderRolesCell($key, $cellData, FormatterOptions $options)
96 if (is_array($cellData)) {
97 return implode("\n", $cellData);
103 * Block the specified user(s).
105 * @command user:block
107 * @param string $names A comma delimited list of user names.
108 * @aliases ublk,user-block
109 * @usage drush user:block user3
110 * Block the users whose name is user3
112 public function block($names)
114 if ($names = StringUtils::csvToArray($names)) {
115 foreach ($names as $name) {
116 if ($account = user_load_by_name($name)) {
119 $this->logger->success(dt('Blocked user(s): !user', ['!user' => $name]));
121 $this->logger->warning(dt('Unable to load user: !user', ['!user' => $name]));
128 * UnBlock the specified user(s).
130 * @command user:unblock
132 * @param string $names A comma delimited list of user names.
133 * @aliases uublk,user-unblock
134 * @usage drush user:unblock user3
135 * Unblock the users with name user3
137 public function unblock($names)
139 if ($names = StringUtils::csvToArray($names)) {
140 foreach ($names as $name) {
141 if ($account = user_load_by_name($name)) {
142 $account->activate();
144 $this->logger->success(dt('Unblocked user(s): !user', ['!user' => $name]));
146 $this->logger->warning(dt('Unable to load user: !user', ['!user' => $name]));
153 * Add a role to the specified user accounts.
155 * @command user:role:add
157 * @validate-entity-load user_role role
158 * @param string $role The name of the role to add.
159 * @param string $names A comma delimited list of user names.
160 * @aliases urol,user-add-role
161 * @usage drush user:add-role "power user" user3
162 * Add the "power user" role to user3
164 public function addRole($role, $names)
166 if ($names = StringUtils::csvToArray($names)) {
167 foreach ($names as $name) {
168 if ($account = user_load_by_name($name)) {
169 $account->addRole($role);
171 $this->logger->success(dt('Added !role role to !user', [
176 $this->logger->warning(dt('Unable to load user: !user', ['!user' => $name]));
183 * Remove a role from the specified user accounts.
185 * @command user:role:remove
187 * @validate-entity-load user_role role
188 * @param string $role The name of the role to add
189 * @param string $names A comma delimited list of user names.
190 * @aliases urrol,user-remove-role
191 * @usage drush user:remove-role "power user" user3
192 * Remove the "power user" role from user3
194 public function removeRole($role, $names)
196 if ($names = StringUtils::csvToArray($names)) {
197 foreach ($names as $name) {
198 if ($account = user_load_by_name($name)) {
199 $account->removeRole($role);
201 $this->logger->success(dt('Removed !role role from !user', [
206 $this->logger->warning(dt('Unable to load user: !user', ['!user' => $name]));
213 * Create a user account.
215 * @command user:create
217 * @param string $name The name of the account to add
218 * @option password The password for the new account
219 * @option mail The email address for the new account
220 * @aliases ucrt,user-create
221 * @usage drush user:create newuser --mail="person@example.com" --password="letmein"
222 * Create a new user account with the name newuser, the email address person@example.com, and the password letmein
224 public function create($name, $options = ['password' => self::REQ, 'mail' => self::REQ])
228 'pass' => $options['password'],
229 'mail' => $options['mail'],
233 if (!Drush::simulate()) {
234 if ($account = User::create($new_user)) {
236 drush_backend_set_result($this->infoArray($account));
237 $this->logger()->success(dt('Created a new user with uid !uid', ['!uid' => $account->id()]));
239 return new CommandError("Could not create a new user account with the name " . $name . ".");
245 * Assure that provided username is available.
247 * @hook validate user-create
249 public function createValidate(CommandData $commandData)
251 if ($mail = $commandData->input()->getOption('mail')) {
252 if (user_load_by_mail($mail)) {
253 throw new \Exception(dt('There is already a user account with the email !mail', ['!mail' => $mail]));
256 $name = $commandData->input()->getArgument('name');
257 if (user_load_by_name($name)) {
258 throw new \Exception((dt('There is already a user account with the name !name', ['!name' => $name])));
263 * Cancel user account(s) with the specified name(s).
265 * @command user:cancel
267 * @param string $names A comma delimited list of user names.
268 * @option delete-content Delete all content created by the user
269 * @aliases ucan,user-cancel
270 * @usage drush user:cancel username
271 * Cancel the user account with the name username and anonymize all content created by that user.
272 * @usage drush user:cancel --delete-content username
273 * Cancel the user account with the name username and delete all content created by that user.
275 public function cancel($names, $options = ['delete-content' => false])
277 if ($names = StringUtils::csvToArray($names)) {
278 foreach ($names as $name) {
279 if ($account = user_load_by_name($name)) {
280 if ($options['delete-content']) {
281 $this->logger()->warning(dt('All content created by !name will be deleted.', ['!name' => $account->getUsername()]));
283 if ($this->io()->confirm('Cancel user account?: ')) {
284 $method = $options['delete-content'] ? 'user_cancel_delete' : 'user_cancel_block';
285 user_cancel([], $account->id(), $method);
286 drush_backend_batch_process();
287 // Drupal logs a message for us.
290 $this->logger()->warning(dt('Unable to load user: !user', ['!user' => $name]));
297 * Set the password for the user account with the specified name.
299 * @command user:password
301 * @param string $name The name of the account to modify.
302 * @param string $password The new password for the account.
303 * @aliases upwd,user-password
304 * @usage drush user:password someuser "correct horse battery staple"
305 * Set the password for the username someuser. @see xkcd.com/936
307 public function password($name, $password)
309 if ($account = user_load_by_name($name)) {
310 if (!Drush::simulate()) {
311 $account->setpassword($password);
313 $this->logger()->success(dt('Changed password for !name.', ['!name' => $name]));
316 throw new \Exception(dt('Unable to load user: !user', ['!user' => $name]));
321 * A flatter and simpler array presentation of a Drupal $user object.
323 * @param $account A user account
326 public function infoArray($account)
329 'uid' => $account->id(),
330 'name' => $account->getUsername(),
331 'pass' => $account->getPassword(),
332 'mail' => $account->getEmail(),
333 'user_created' => $account->getCreatedTime(),
334 'created' => format_date($account->getCreatedTime()),
335 'user_access' => $account->getLastAccessedTime(),
336 'access' => format_date($account->getLastAccessedTime()),
337 'user_login' => $account->getLastLoginTime(),
338 'login' => format_date($account->getLastLoginTime()),
339 'user_status' => $account->get('status')->value,
340 'status' => $account->isActive() ? 'active' : 'blocked',
341 'timezone' => $account->getTimeZone(),
342 'roles' => $account->getRoles(),
343 'langcode' => $account->getPreferredLangcode(),
344 'uuid' => $account->uuid->value,