CommentFileSizeAuthor
#81 2068329-convert_user_sql_queries_to_the_entity_query_api-81.patch15.63 KBplach
#73 2068329-convert_user_sql_queries_to_the_entity_query_api-73.patch15.6 KBplach
#62 2068329-convert_user_sql_queries_to_the_entity_query_api-62.patch18.45 KBLinL
#61 2068329-convert_user_sql_queries_to_the_entity_query_api-61.patch18.49 KBLinL
#58 interdiff-between-patches.txt6.88 KBpenyaskito
#58 2068329-convert_user_sql_queries_to_the_entity_query_api-58.patch18.49 KBpenyaskito
#56 2068329-convert_user_sql_queries_to_the_entity_query_api-55.patch18.53 KBherom
#48 2068329-convert_user_sql_queries_to_the_entity_query_api-48.patch21.24 KBpeximo
#46 interdiff.txt2.91 KBmarcingy
#46 2068329-convert_user_sql_queries_to_the_entity_query_api-46.patch21.22 KBmarcingy
#44 2068329-convert_user_sql_queries_to_the_entity_query_api-44.patch20.94 KBmarcingy
#36 2068329-convert_user_sql_queries_to_the_entity_query_api-36.patch20.66 KBpeximo
#36 intediff.txt520 bytespeximo
#35 2068329-convert_user_sql_queries_to_the_entity_query_api-35.patch20.65 KBpeximo
#35 interdiff.txt595 bytespeximo
#34 2068329-convert_user_sql_queries_to_the_entity_query_api-34.patch20.7 KBpeximo
#34 interdiff.txt653 bytespeximo
#32 2068329-convert_user_sql_queries_to_the_entity_query_api-32.patch20.44 KBpeximo
#30 2068329-convert_user_sql_queries_to_the_entity_query_api-30.patch21.76 KBpeximo
#30 interdiff.txt841 bytespeximo
#28 2068329-convert_user_sql_queries_to_the_entity_query_api-28.patch21.76 KBpeximo
#28 interdiff.txt9.75 KBpeximo
#25 2068329-convert_user_sql_queries_to_the_entity_query_api-25.patch21.22 KBpeximo
#25 interdiff.txt9.81 KBpeximo
#23 interdiff.txt1.29 KBpeximo
#23 2068329-convert_user_sql_queries_to_the_entity_query_api-23.patch14.97 KBpeximo
#22 2068329-convert_user_sql_queries_to_the_entity_query_api-22.patch13.68 KBDésiré
#15 interdiff.txt621 bytesDésiré
#15 2068329-convert_user_sql_queries_to_the_entity_query_api-15.patch13.16 KBDésiré
#11 interdiff.txt3.75 KBchx
#11 2068329_11.patch13.24 KBchx
#6 drupal8.user-module.2068329-6.patch10.55 KBpeximo
#4 drupal8.user-module.2068329-4.patch8.73 KBpeximo
#2 drupal8.user-module.2068329-2.patch8.74 KBpeximo
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

plach’s picture

peximo’s picture

Assigned: Unassigned » peximo
Status: Active » Needs review
FileSize
8.74 KB

Hi,
this is my initial work.

Status: Needs review » Needs work

The last submitted patch, drupal8.user-module.2068329-2.patch, failed testing.

peximo’s picture

Status: Needs work » Needs review
FileSize
8.73 KB

Rerolled

twistor’s picture

  1. +++ b/core/modules/user/lib/Drupal/user/UserAutocomplete.php
    @@ -65,9 +65,15 @@ public function getMatches($string, $include_anonymous = FALSE) {
    +      $uids = \Drupal::entityQuery('user')
    +        ->condition('name', db_like($string) . '%', 'LIKE')
    +        ->range(0, 10)
    

    Should we use STARTS_WITH here?

  2. +++ b/core/modules/user/lib/Drupal/user/UserAutocomplete.php
    @@ -65,9 +65,15 @@ public function getMatches($string, $include_anonymous = FALSE) {
    +        $matches[$account->getUsername()] = check_plain($account->getUsername());
    

    Go ahead and convert this to String::checkPlain().

  3. +++ b/core/modules/user/user.module
    @@ -522,16 +521,14 @@ function user_search_access() {
    +    $group = $query->orConditionGroup()
    +      ->condition('name', '%' . db_like($keys) . '%', 'LIKE')
    +      ->condition('mail', '%' . db_like($keys) . '%', 'LIKE');
    +    $query->condition($group);
    

    Use CONTAINS?

  4. +++ b/core/modules/user/user.module
    @@ -1137,10 +1133,7 @@ function user_login_finalize(UserInterface $account) {
    -    ->execute();
    +  $controller = Drupal::entityManager()->getStorageController('user')->save($user);
    

    Why not $user->save()?

peximo’s picture

Ok, I modified as suggested by @twistor, updated some parts and continued with the work.

Désiré’s picture

Status: Needs review » Reviewed & tested by the community

I'm successfully applied, and tested this patch.
I'm also not found any coding standard problems, so I change the status to RTBC.

Berdir’s picture

+++ b/core/modules/user/user.module
@@ -1062,10 +1061,7 @@ function user_login_finalize(UserInterface $account) {
-  db_update('users')
-    ->fields(array('login' => $user->getLastLoginTime()))
-    ->condition('uid', $user->id())
-    ->execute();
+  $user->save();

I'm not sure about this change. This very explicitly did not use user save before, doing that is quite an overhead over the old code.

Désiré’s picture

The main issue is about to use Entity API everywhere instead of SQL queries #2068325: [META] Convert entity SQL queries to the Entity Query API, and this means that we should user_save to change this data.
But I'm also thinking this is an overhead, have you any idea how can we resolve this without using db_update or user_save?

Berdir’s picture

Yes, there is an alternative, that would be to add a updateTimestamp($uid) to the user storage controller. But I'm not sure if it's worth it.

chx’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
13.24 KB
3.75 KB

I think it worths it.

Status: Needs review » Needs work

The last submitted patch, 2068329_11.patch, failed testing.

Berdir’s picture

Status: Needs work » Needs review

#11: 2068329_11.patch queued for re-testing.

Status: Needs review » Needs work

The last submitted patch, 2068329_11.patch, failed testing.

Désiré’s picture

Status: Needs work » Needs review
FileSize
13.16 KB
621 bytes

In the last patch the last login time wasn't set, here is the fix.

Désiré’s picture

I'm also confused of the variable name usage in this function:

Some cases it uses $user, other cases $account, they are the same of course, but is here any reason to using one or other in a context?
I think no, so if you agree, I'll change all usage of $account to $user from the 3. line of the function.

function user_login_finalize(UserInterface $account) {
  global $user;
  $user = $account;
  watchdog('user', 'Session opened for %name.', array('%name' => $user->getUsername()));
  // Update the user table timestamp noting user has logged in.
  // This is also used to invalidate one-time login links.
  $account->setLastLoginTime(REQUEST_TIME);
  \Drupal::entityManager()
    ->getStorageController('user')
    ->updateLastLoginTimestamp($account);

  // Regenerate the session ID to prevent against session fixation attacks.
  // This is called before hook_user in case one of those functions fails
  // or incorrectly does a redirect which would leave the old session in place.
  drupal_session_regenerate();

  \Drupal::moduleHandler()->invokeAll('user_login', array($user));
}

Status: Needs review » Needs work
Désiré’s picture

Status: Needs work » Needs review
chx’s picture

> Some cases it uses $user, other cases $account, they are the same of course, but is here any reason to using one or other in a context?

I would rather change everything to account; using $user with the global $user being around is bad and dangerous practice. But if that's too much; just go with $user -- the global will be gone soon after all.

peximo’s picture

Ok I think it remains to change the anonimous and admin user creation on installation; but I do not know if at that stage it's possible to make an entity save.

@chx:

Do we also need to modify queries in the update functions and tests?

chx’s picture

> change the anonimous and admin user creation on installation; but I do not know if at that stage it's possible to make an entity save.

I doubt you can; it worths trying; but I think any non-sql database will need to alter the install tasks anyways...

Regarding renames: just rename my $account to $user let's no go off on a tangent and do massive renames.

Regarding updates: absolutely not you can't use the entity system during updates.

Désiré’s picture

I'm agree that use $account is better than the global $user, so here is the new patch, only the variable names was changed in the user_login_finalize() function, and rerolled against the new 8.x HEAD.

peximo’s picture

I believe that as expected you can not create the entity on installation. I only made ​​one final change to the api file; I think that there is nothing else to do.

Berdir’s picture

+++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
@@ -258,13 +258,12 @@ public function validate(array $form, array &$form_state) {
+        $name_taken = (bool) \Drupal::entityQuery('user')

@@ -275,13 +274,12 @@ public function validate(array $form, array &$form_state) {
+      $mail_taken = (bool) \Drupal::entityQuery('user')

+++ b/core/modules/user/lib/Drupal/user/Plugin/Block/UserNewBlock.php
@@ -65,7 +65,13 @@ public function blockSubmit($form, &$form_state) {
+    $uids = \Drupal::entityQuery('user')

+++ b/core/modules/user/lib/Drupal/user/Plugin/Block/UserOnlineBlock.php
@@ -82,7 +82,10 @@ public function build() {
-    $authenticated_count = db_query("SELECT COUNT(uid) FROM {users} WHERE access >= :timestamp", array(':timestamp' => $interval))->fetchField();
+    $authenticated_count = \Drupal::entityQuery('user')

@@ -92,7 +95,13 @@ public function build() {
+      $uids = \Drupal::entityQuery('user')

+++ b/core/modules/user/lib/Drupal/user/UserAutocomplete.php
@@ -65,9 +66,15 @@ public function getMatches($string, $include_anonymous = FALSE) {
+      $uids = \Drupal::entityQuery('user')
...
+      $controller = \Drupal::entityManager()->getStorageController('user');
+      foreach ($controller->loadMultiple($uids) as $account) {

I guess we need to inject all those entity query instances?

peximo’s picture

Ok modified as suggested, I hope the right way.

plach’s picture

Changes look good to me.

+++ b/core/modules/user/user.services.yml
@@ -20,7 +20,7 @@ services:
+    arguments: ['@database', '@config.factory', '@entity.query', '@entity.manager']

A very minor nitpick: if we happen to reroll this, can we swap the entity manager and the query factory order? The entity manager appears as more "important" to my eyes :)

Status: Needs review » Needs work
peximo’s picture

Status: Needs work » Needs review
FileSize
9.75 KB
21.76 KB

Rerolled with some adjustment.

Status: Needs review » Needs work
peximo’s picture

Status: Needs work » Needs review
FileSize
841 bytes
21.76 KB

I hope this is the last time, rerolled.

plach’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
    @@ -16,6 +18,29 @@
     abstract class AccountFormController extends EntityFormControllerNG {
    

    The patch no longer applies: EntityFormControllerNG has been renamed to ContentEntityFormController.

  2. +++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
    @@ -258,13 +283,12 @@ public function validate(array $form, array &$form_state) {
    +          ->condition('name', db_like($form_state['values']['name']), 'LIKE')
    
    @@ -275,13 +299,12 @@ public function validate(array $form, array &$form_state) {
    +        ->condition('mail', db_like($mail), 'LIKE')
    
    +++ b/core/modules/user/lib/Drupal/user/Plugin/Validation/Constraint/UserUniqueValidator.php
    @@ -22,14 +22,13 @@ public function validate($value, Constraint $constraint) {
           ->condition($field->getName(), db_like($value), 'LIKE')
    
    +++ b/core/modules/user/user.module
    @@ -460,11 +460,10 @@ function user_access($string, AccountInterface $account = NULL) {
         ->condition('name', db_like($name), 'LIKE')
    

    The operator here should just be omitted and the unescaped value should be passed, AAMOF the equality operator is already case-insensitive for regular string fields (see #2068655: Entity fields do not support case sensitive queries).

  3. +++ b/core/modules/user/user.admin.inc
    @@ -10,30 +10,19 @@
    +  $uids = Drupal::entityQuery('user')
    
    +++ b/core/modules/user/user.api.php
    @@ -118,22 +118,18 @@ function hook_user_cancel($edit, $account, $method) {
    +      $nodes = Drupal::entityQuery('node')
    ...
    +      $nodes = Drupal::entityQuery('node')
    
    +++ b/core/modules/user/user.module
    @@ -460,11 +460,10 @@ function user_access($string, AccountInterface $account = NULL) {
    +  return Drupal::entityQuery('user')
    

    Now we always use a leading backslash: \Drupal::...

peximo’s picture

Status: Needs work » Needs review
FileSize
20.44 KB

Rerolled.

plach’s picture

Status: Needs review » Needs work
Issue tags: +API change

Nice work!

+++ b/core/modules/user/user.module
@@ -460,11 +460,10 @@ function user_access($string, AccountInterface $account = NULL) {
  *   FALSE if the user is not blocked.
  */
 function user_is_blocked($name) {
-  return db_select('users')
-    ->fields('users', array('name'))
-    ->condition('name', db_like($name), 'LIKE')
+  return \Drupal::entityQuery('user')
+    ->condition('name', $name)
     ->condition('status', 0)
-    ->execute()->fetchObject();
+    ->execute();

I didn't realize we have a small API change here: the returned value is now an array of user ids. The documentation should reflect it.

Aside from this I'd say we are RTBC.

peximo’s picture

Status: Needs work » Needs review
FileSize
653 bytes
20.7 KB

Ok modified as required.

peximo’s picture

I realized that returning a boolean value is cleaner for the purpose of the function.

peximo’s picture

Sorry I forgot the cast.

plach’s picture

Thanks! RTBC if green.

plach’s picture

Status: Needs review » Reviewed & tested by the community
plach’s picture

plach’s picture

Xano’s picture

Status: Reviewed & tested by the community » Needs work
marcingy’s picture

Status: Needs work » Needs review
FileSize
20.94 KB

Just a simple re-roll

Status: Needs review » Needs work
marcingy’s picture

Status: Needs work » Needs review
FileSize
21.22 KB
2.91 KB

Should fix the issues and also kills what seems to be unused use statements

plach’s picture

Status: Needs review » Reviewed & tested by the community

Looks good, thanks.

peximo’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
21.24 KB

Rerolled.

Status: Needs review » Needs work
peximo’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work
plach’s picture

That test passes locally and is failing in other unrelated issues too.

plach’s picture

LinL’s picture

Status: Reviewed & tested by the community » Needs work
herom’s picture

Status: Needs work » Needs review
FileSize
18.53 KB

reroll

Status: Needs review » Needs work
penyaskito’s picture

Reroll. Attached diff between patches #48 and this one.

chx’s picture

Status: Needs review » Reviewed & tested by the community
plach’s picture

LinL’s picture

LinL’s picture

LinL’s picture

Status: Reviewed & tested by the community » Needs review
chx’s picture

Status: Needs review » Reviewed & tested by the community
xjm’s picture

Berdir’s picture

Note that #2164715: Remove user_node_load() will remove the user_node_load() completely which I think is preferred over this, so will need a re-roll if it gets in first and if something else conflicts first, I'd suggest to re-roll without that change.

catch’s picture

Status: Reviewed & tested by the community » Needs review
+++ b/core/modules/user/lib/Drupal/user/AccountFormController.php
@@ -301,13 +313,12 @@ public function validate(array $form, array &$form_state) {
+          ->condition('name', $form_state['values']['name'])

Doesn't this mean the query will no-longer be case insensitive?

plach’s picture

@catch:

The equality operator is case-insensitive for regular string fields (see #2068655: Entity fields do not support case sensitive queries).

catch’s picture

That patch isn't in yet though right?

plach’s picture

Yep, but no code would change here. Do you want to postpone this on that one?

catch’s picture

Hmm. Either postpone or make that one critical?

plach’s picture

Well, these conversions actually block a critical beta blocker so it's more or less the same thing, I guess. I'd vote to commit this to avoid the reroll fun :)

plach’s picture

Speaking of rerolls... This is smaller as a couple of hunks were removed.

catch’s picture

Status: Needs review » Reviewed & tested by the community

Bumped the other issue to critical, I haven't reviewed the full patch here yet so just leaving RTBC.

Status: Reviewed & tested by the community » Needs work

plach’s picture

Status: Needs work » Needs review
plach’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC

catch’s picture

Status: Reviewed & tested by the community » Needs work
plach’s picture

Status: Needs work » Needs review
FileSize
15.63 KB

Rerolled

Status: Needs review » Needs work
plach’s picture

Status: Needs work » Needs review
plach’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC

alexpott’s picture

Title: Convert user SQL queries to the Entity Query API » Change notice: Convert user SQL queries to the Entity Query API
Priority: Normal » Major
Status: Reviewed & tested by the community » Active
Issue tags: +Approved API change, +Needs change record

This looks great!

Committed 0f704ad and pushed to 8.x. Thanks!

diff --git a/core/modules/user/lib/Drupal/user/UserStorageController.php b/core/modules/user/lib/Drupal/user/UserStorageController.php
index bd86370..6093e7e 100644
--- a/core/modules/user/lib/Drupal/user/UserStorageController.php
+++ b/core/modules/user/lib/Drupal/user/UserStorageController.php
@@ -112,12 +112,12 @@ public function save(EntityInterface $entity) {
   /**
    * {@inheritdoc}
    */
-  public function saveRoles(UserInterface $user) {
+  public function saveRoles(UserInterface $account) {
     $query = $this->database->insert('users_roles')->fields(array('uid', 'rid'));
-    foreach ($user->getRoles() as $rid) {
+    foreach ($account->getRoles() as $rid) {
       if (!in_array($rid, array(DRUPAL_ANONYMOUS_RID, DRUPAL_AUTHENTICATED_RID))) {
         $query->values(array(
-          'uid' => $user->id(),
+          'uid' => $account->id(),
           'rid' => $rid,
         ));
       }
diff --git a/core/modules/user/lib/Drupal/user/UserStorageControllerInterface.php b/core/modules/user/lib/Drupal/user/UserStorageControllerInterface.php
index ec4348d..5718f93 100644
--- a/core/modules/user/lib/Drupal/user/UserStorageControllerInterface.php
+++ b/core/modules/user/lib/Drupal/user/UserStorageControllerInterface.php
@@ -27,7 +27,7 @@ public function addRoles(array $users);
    *
    * @param \Drupal\user\UserInterface $account
    */
-  public function saveRoles(UserInterface $user);
+  public function saveRoles(UserInterface $account);

   /**
    * Remove the roles of a user.

Fixed during commit - there was an inconsistency between the parameter names in the interface and the class.

xjm’s picture

Hm. Do we actually need a change record here? It looks to me like we are just injecting a couple more dependencies in some constructors, so the only BC breaks would be for someone subclassing these things or using them directly in D8. Maybe we just need to see if there are any references to these classes in existing change records, or verify that their aren't? Or did I miss something?

plach’s picture

We have a small API change in user_is_blocked() and the addition of UserStorageController::updateLastLoginTimestamp(). Not sure whether that's enough for a change notice, but I'd say it wouldn't hurt :)

xjm’s picture

Issue tags: +Missing change record

Alright, thanks @plach!

Tagging "Missing change record", as completing the change record updates here blocks a beta: #2083415: [META] Write up all outstanding change notices before release

plach’s picture

Status: Active » Needs review

Here it is:

https://drupal.org/node/2186163

I added a note about the API addition at the bottom of the CN, since it is primarily focused on the API change.

plach’s picture

Title: Change notice: Convert user SQL queries to the Entity Query API » Convert user SQL queries to the Entity Query API
Status: Needs review » Fixed
Issue tags: -Needs change record, -Missing change record

Moving the change record to the review queue.

Status: Fixed » Closed (fixed)

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