Problem/Motivation

User::addRole() does not return a value, meaning the function be changed.

Steps to reproduce

Execute the following code, where $id is an existing user ID, and $role_id is the machine name of an existing role.

\Drupal::entityTypeManager()->getStorage('user')
  ->load($id)
  ->addRole($role_id)
  ->save();

An error is thrown that save() is called on NULL.

Proposed resolution

User::addRole() should return $this.

Remaining tasks

Write tests.

User interface changes

None.

API changes

None needed - this is for forward compatibility.

Data model changes

None.

Release notes snippet

Methods User::addRole() and User::removeRole() previously did not return a value, and therefore could not be chained. Now both return $self and can be used in chained calls.

Previous:

$user->removeRole('editor');
$user->addRole('contributor');
$user->save();

New:

$user
  ->removeRole('editor')
  ->addRole('contributor')
  ->save();
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Jaypan created an issue. See original summary.

Jaypan’s picture

cilefen’s picture

Version: 10.0.x-dev » 10.1.x-dev
andypost’s picture

patch was broken because using "web" prefix

Here's a test fix for new expectation

Jaypan’s picture

andypost’s picture

You're missed to add a test from my patch

The last submitted patch, 4: 3324729-4.patch, failed testing. View results

Jaypan’s picture

andypost’s picture

Status: Needs review » Needs work
+++ b/web/core/modules/user/src/UserInterface.php
--- a/web/core/modules/user/tests/src/Kernel/UserEntityTest.php
+++ b/web/core/modules/user/tests/src/Kernel/UserEntityTest.php

your patch against "web" again( not applicable to core

Jaypan’s picture

andypost’s picture

Status: Needs work » Reviewed & tested by the community

It may need change record

Jaypan’s picture

Issue summary: View changes
longwave’s picture

Status: Reviewed & tested by the community » Needs review

Can we make removeRole() chainable in the same way?

Jaypan’s picture

I'm sure someone could.

longwave’s picture

Title: User::addRole() should be chainable » User::addRole() and ::removeRole() should be chainable
Status: Needs review » Needs work
Issue tags: +Needs change record

I think it would be a good idea to change both at the same time, given that addRole and removeRole complement each other. I found this issue because I tried to chain $user->removeRole('foo')->save() today and it didn't work.

We should also write a short change record to inform developers of this API addition.

Jaypan’s picture

I'm going to exit stage left due to bikeshedding, I've already added the existing patch to my current application. Hopefully someone else will come pick this up.

Chandreshgiri Gauswami’s picture

Assigned: Unassigned » Chandreshgiri Gauswami

I will work on it.

Chandreshgiri Gauswami’s picture

Providing extended patch with interdiff file.

Chandreshgiri Gauswami’s picture

Status: Needs work » Needs review
andypost’s picture

Release notes snippet needs tuning

andypost’s picture

Issue summary: View changes
Status: Needs review » Reviewed & tested by the community
Issue tags: -Needs change record

Added CR https://www.drupal.org/node/3326231 and fixed release snippet

quietone’s picture

Status: Reviewed & tested by the community » Needs work

Just a wee thing

+++ b/core/modules/user/src/UserInterface.php
@@ -66,6 +66,9 @@ public function hasRole($rid);
+   *   The called user entity.

@@ -74,6 +77,9 @@ public function addRole($rid);
+   *   The called user entity.

Pretty sure these can be removed. See #3129184: Remove description from @return $this.

elber’s picture

Assigned: Unassigned » elber
elber’s picture

Assigned: elber » Unassigned
Status: Needs work » Needs review
FileSize
3.88 KB
1.57 KB
andypost’s picture

Status: Needs review » Needs work

Scope creep drupal.org/core/scope

+++ b/core/modules/user/src/UserInterface.php
@@ -106,7 +109,6 @@ public function getPassword();
-   *   The called user entity.

@@ -117,7 +119,6 @@ public function setPassword($password);
-   *   The called user entity.

@@ -136,7 +137,6 @@ public function getCreatedTime();
-   *   The called user entity.

@@ -155,7 +155,6 @@ public function getLastLoginTime();
-   *   The called user entity.

@@ -179,7 +178,6 @@ public function isBlocked();
-   *   The called user entity.

@@ -187,7 +185,6 @@ public function activate();
-   *   The called user entity.

this changes are unrelated, please remove it

andypost’s picture

@quietone Thank you! good old issue) Re #22 Checked core with git grep -A2 -F ' @return $this' and the most of places has no value, so it needs to fix coding standard before related issue as we just missing sniffer

andypost’s picture

Status: Needs work » Needs review
FileSize
1.54 KB
2.55 KB
longwave’s picture

Status: Needs review » Reviewed & tested by the community

Thanks, this looks good to me.

As a followup we could start using this across core, e.g. standard.install:

  // Assign user 1 the "administrator" role.
  /** @var \Drupal\user\Entity\User $user */
  $user = User::load(1);
  $user->addRole('administrator');
  $user->save();

  • xjm committed 9bd48412 on 10.1.x
    Issue #3324729 by Jaypan, andypost, Chandreshgiri Gauswami, elber,...
xjm’s picture

Status: Reviewed & tested by the community » Fixed
Issue tags: +Needs followup
+++ b/core/modules/user/src/UserInterface.php
@@ -69,6 +69,8 @@ public function hasRole($rid);
+   *
+   * @return $this

@@ -77,6 +79,8 @@ public function addRole($rid);
+   * @return $this

There is a slight disruption in adding the documentation to the interface, because it means child implementations that return nothing no longer implement the interface as documented and might fail coding standards checks. There's also hypothetically the possibility of disruption if a child implementation is already returning something other than $this (like a boolean flag, or whatever). Both those things are fine as disruptions in a minor release with a CR. I don't think it's disruptive enough that we need to add it to the release notes.

Tagging "Needs followup" for the issue to implement this where feasible.

Thanks for the test coverage and for keeping the out-of-scope changes out of scope. Committed to 10.1.x and published the CR.

quietone’s picture

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.