Problem/Motivation

My use case for this is a SAML authentication module (https://www.drupal.org/project/samlauth). Since authmap was removed, I need another way to store a mapping between local and remote users. The users_data table is a good place for that. However, when the external authentication service redirects back to the Drupal site, there's no way to find a uid in the users_data table given the unique ID that the authentication service hands us. The same is true for OAuth and likely everything else.

Proposed resolution

Add the ability to find uid in users_data with $module, $key, or $value to user.data service.

Remaining tasks

Change UserData::get into a wrapper of this and move it into a UserDataBase class so other classes implementing UserDataInterface doesn't need to bother with the weird return data structure of UserData::get. This can be a novice followup.

User interface changes

None.

API changes

New method on UserData to get an object that implements UserDataQueryInterface

Data model changes

None.

Comments

cweagans’s picture

Issue summary: View changes
cweagans’s picture

Status: Active » Needs review
StatusFileSize
new2.59 KB

Something like this maybe?

Status: Needs review » Needs work

The last submitted patch, 2: 2507117_02.patch, failed testing.

Status: Needs work » Needs review

cweagans queued 2: 2507117_02.patch for re-testing.

Status: Needs review » Needs work

The last submitted patch, 2: 2507117_02.patch, failed testing.

Status: Needs work » Needs review

cweagans queued 2: 2507117_02.patch for re-testing.

cweagans’s picture

Issue summary: View changes
berdir’s picture

The value might be unique for your module, but there's nothing in the API/storage that guarantees that is for all values, so that special case for returning a single uid doesn't really make sense in the generic implementation?

cweagans’s picture

Status: Needs review » Needs work

Ah, oops. I thought for a given $module, $uid, and $name, there could only be one $value, but I see now that assumption is false.

a_khalipau’s picture

Status: Needs work » Needs review
StatusFileSize
new2.62 KB
new744 bytes

Re-rolled patch. Please, review.

a_khalipau’s picture

StatusFileSize
new2.64 KB

Corrected comments to correspond that the get() method will return.

chx’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

Poor get method already does N different things, are we sure we want to pile on more?

Tests.

The new doxygen is 86 long, needs to be broken into two lines.

cweagans’s picture

Version: 8.0.x-dev » 8.1.x-dev

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

VinayLondhe’s picture

StatusFileSize
new2.71 KB

Reroll for 8.2.x

chx’s picture

Issue summary: View changes
Status: Needs work » Needs review
Issue tags: -Needs tests
StatusFileSize
new7.52 KB

This patch is a completely ground up attempt -- not only I am not using the previous patches but I have rewritten UserData::get from the ground up, it's 5 lines of code shorter but at the same it is much more powerful -- allows for $value as this issue asks and also happens to cover every possible combination. I really like how the getDataProvider turned out, it reads like terse documentation (of course the interface doxygen has more):

      [$contents, $uid, $name, NULL, $value],
      [$contents, $uid, NULL, $value, [$name]],
      [$contents, NULL, $name, $value, [$uid]],
      [$contents, $uid, NULL, NULL, [$name => $value]],
      [$contents, NULL, $name, NULL, [$uid => $value]],
      [$contents, NULL, NULL, $value, [$uid => $name]],
      [$contents, NULL, NULL, NULL, [$uid => [$name => $value]]],

In answering my own problems with unit tests like this: it is a meaningful test, proven by a) I found a number of bugs with it b) you can change the implementation easily (but not the query) without the test breaking. There is, of course, more that could be done (multiple rows) but this seems to be enough -- for me.

chx’s picture

StatusFileSize
new7.46 KB
new654 bytes

A little simplification in the setup.

chx’s picture

StatusFileSize
new9.34 KB

Testing non-scalar values. Of course there were bugs handling them. This begins to give at least a taste of just how massive testing this class ought to be.

benjy’s picture

Status: Needs review » Reviewed & tested by the community

This function is pretty overloaded, It would be good to add follow-up issues that added new methods for each possible return value, and then keep get() for BC.

However the current tests are passing and the new tests are welcome to such complicated code

Just one nitpick.

+++ b/core/modules/user/src/UserDataInterface.php
@@ -16,18 +16,26 @@
+   * @see \Drupal\Tests\user\Unit\UserDataTest::getDataProvider() ¶

Trailing whitespace.

chx’s picture

StatusFileSize
new9.34 KB

Fixed the whitespace.

larowlan’s picture

+++ b/core/modules/user/src/UserData.php
@@ -29,49 +29,46 @@ public function __construct(Connection $connection) {
+  public function get($module, $uid = NULL, $name = NULL, $value = NULL) {
+    $args = ['uid' => $uid, 'name' => $name, 'value' => $value];
+    if (!$args_not_set = array_filter($args, 'is_null')) {
+      throw new \InvalidArgumentException('All four arguments can not be set at the same time.');
+    }

I disagree, I think this adds way too much complexity and isn't the intention of the existing method.

The original method is for getting a value with a known module and possibly uid.

Now we're doing the reverse.

I think we need to take a step back and think about how we'd design this in a greenfield scenario.

We'd add a getUidGivenValue method.

But we can't do that here because BC.

So I propose we add a new service that extends the existing one - eg. user_data.reverse and mark the existing one deprecated to be removed in 9.0

then we don't overload the existing method with complexity

chx’s picture

Title: Add a method to find uid in users_data with $module, $key, and $value » Add a service to find uid in users_data with $module, $key, and $value
Issue summary: View changes
StatusFileSize
new7.27 KB

Sure. Here's a simple query service.

chx’s picture

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

StatusFileSize
new7.08 KB

Pointless doxygen fixes.

chx’s picture

StatusFileSize
new6.86 KB

A little bit of test simplification. Trying to keep the size down.

chx’s picture

Issue summary: View changes
fabianx’s picture

Status: Needs review » Reviewed & tested by the community
Issue tags: +Needs framework manager review

I like the service a lot. I do think it is a great addition, my review is only nit picks and one strategic decision (shared: FALSE).

Setting to RTBC to get D8 core committer feedback.

----

  1. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,56 @@
    +   * ¶
    ...
    +   * ¶
    ...
    +   * ¶
    ...
    +   * ¶
    

    nit - whitespace

  2. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,56 @@
    +   *   A list of result objects. Each object contains has module, uid, name
    +   *   and value properties.
    

    nit - remove contains

  3. +++ b/core/modules/user/user.services.yml
    @@ -25,6 +25,12 @@ services:
    +    shared: FALSE
    

    This would be the first core service to use shared: FALSE (and should be lowercase FALSE). (The other ones are from zen feed reader)

    I do think we use factories for that in core so far. I don't think we should deviate from that pattern as it is more explicit.

    However I can see the argument that the factory would in essence do nothing and be just 'dead code'.

    However as it is a kinda new paradigm for core at this stage, this definitely needs a framework manager review.

    I am not opposed to it, just think that factories are clearer, but shared: FALSE is there for a reason, too.

chx’s picture

StatusFileSize
new1.73 KB
new6.84 KB

Nits fixed. All I can say about shared: false is that I was glad when I found it. Yes, it's a new pattern but Drupal 8 definitely could use less boilerplate.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 28: 2507117_28.patch, failed testing.

chx’s picture

Status: Needs work » Reviewed & tested by the community

Unrelated fail, retested OK so going back to green.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 28: 2507117_28.patch, failed testing.

dawehner’s picture

Status: Needs work » Reviewed & tested by the community

This was a random test failure.

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 28: 2507117_28.patch, failed testing.

chx’s picture

Status: Needs work » Reviewed & tested by the community

More of the same.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: -Needs framework manager review +Needs tests
  1. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,125 @@
    +      if (!is_scalar($this->value)) {
    +        $this->value = serialize($this->value);
    +        $query->condition('serialized', 1);
    +      }
    ...
    +      if ($row->serialized) {
    +        $row->value = unserialize($row->value);
    +      }
    

    Not tested logic.

  2. +++ b/core/modules/user/user.services.yml
    @@ -25,6 +25,12 @@ services:
    +    shared: false
    

    I'm fine with this. It's a feature of our service container - seems fine to use it. We have specific code for it in \Drupal\Component\DependencyInjection\Container.

chx’s picture

Status: Needs work » Needs review
StatusFileSize
new7.47 KB
new2.27 KB
chx’s picture

Issue tags: -Needs tests
chx’s picture

StatusFileSize
new7.04 KB

I rewrote the whole class. I liked this one so much better: the class only talks to the select object not the entire connection. The select object carries the state, not the query class. It's extremely small this way. At this point interdiff is pointless.

jibran’s picture

Status: Needs review » Reviewed & tested by the community

Well #36 looks really good but #37 is more inline with query service concept so RTBC for #37.

xjm’s picture

Issue tags: +beta deadline

Tagging for visibility.

fabianx’s picture

+++ b/core/modules/user/src/UserDataQuery.php
@@ -0,0 +1,89 @@
+  /**
+   * Constructs a new user data service.
+   *
...
+  public function __construct(SelectInterface $select) {
...
+  /**
+   * Factory method for the class.
+   *
...
+  public static function create(Connection $connection) {

Question: What do we gain when using a separate factory method here?

It seems the 'ud' is hard-coded in both, so I imagine any special custom code would need to override both as well.

Storing the select instead of the connection looks good to me, but I don't see the need for the factory ...

Can someone explain, please?

catch’s picture

Status: Reviewed & tested by the community » Needs review

I don't see any mention of https://www.drupal.org/project/externalauth in this issue.

Also I think I've seen a core issue to bring some of that into core, but wasn't able to find it again.

We were trying to remove users_data in Drupal 8, but didn't manage to do it, not sure about making it easier to use - could equally go for trying to deprecate it.

chx’s picture

Re #41 if you override the constructor you can use this class for anything that support the simplest form of condition method and execute. Nothing presumes a SQL database select really. That was my evil plan with this. We could equally pass in a connection to the constructor and retrieve the select there but running logic in the constructor felt wrong. All in all, the class cares about a select so let's pass it a select. You can't do that from the services.yml alone so we needed something to go for it.

Re externelauth we kill Authmap from that project, yes, I am aware and glad we do. We could try to deprecate user data sure but ... it's here for now and Authmap hardwires SQL while userdata being in core and backend overrideable and all that, doesn't really. Just my two cents. I'd say keep it but change UserData::get into a wrapper for the new query class because it's reasonably horrible spaghetti and then the maintenance cost is very low for keeping it.

fabianx’s picture

Status: Needs review » Reviewed & tested by the community

Back to RTBC, I agree that keeping users_data is a good idea.

The advantage to K/V is that it can have conditions, which is sometimes needed for user specific data.

And just using fields was sometimes a little brittle for users, when what you need is not needed on every entity load of the user.

So I think its a pretty good compromise.

chx’s picture

I could accept won't fixing this on the condition of having a "save this field only" mechanism. There are other use cases (denormalizing flag or comment counts) for that. Currently if this were in a field you'd lose the meaning of user->changed as the entity would change every time their oauth token expires... until that (very hard) issue this simple one needs to suffice for user.

alexpott’s picture

So whilst reviewing this again I decided to look at \Drupal\user\UserData and I read the ::get() method. That method is not a limited version of this service therefore it's confusing to know which one you want. So one option would be to deprecate it in favour of this new service. But the other thing that strikes me is that if you are going to override user.data or user.data.query using the backend_overridable tag then you've have to do both - which seems OTT. Shouldn't the user.data service provide this ability and then you only got once place to override?

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new2.7 KB
new7.59 KB

Perhaps the simplest way to address #46 is just to have one service.

tim.plunkett’s picture

  1. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,89 @@
    +class UserDataQuery implements UserDataQueryInterface {
    
    +++ b/core/modules/user/tests/src/Kernel/UserDataQueryTest.php
    @@ -0,0 +1,95 @@
    + * @coversDefaultClass \Drupal\user\UserData
    

    Mismatch

  2. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,56 @@
    +namespace Drupal\user;
    +
    +interface UserDataQueryInterface {
    

    This deserves some docs.

  3. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,56 @@
    +   * Set the module value.
    ...
    +   * Set the user account ID the data is associated with.
    ...
    +   * Set the name of the data key.
    ...
    +   * Set the value stored.
    ...
    +   * Run the query.
    

    All of these should be "Sets" and then "Runs"

  4. +++ b/core/modules/user/user.services.yml
    @@ -25,6 +25,13 @@ services:
    +    class: Drupal\user\UserDataQuery
    +    shared: false
    +    tags:
    +      - { name: backend_overridable }
    +    factory: ['Drupal\user\UserDataQuery', 'create']
    +    arguments: ['@database']
    

    Super nitpicky, but could these be reordered? class, factory, arguments first, and then shared/tags.

    Also is this the first service we use the class itself for a static factory method? Interesting to me since it mirrors plugins and ContainerInjectionInterface, but slicker.

  5. +++ b/core/modules/user/user.services.yml
    @@ -25,6 +25,13 @@ services:
    +    shared: false
    

    Ooh, first time I've seen this. Seems we use it for Zend feed plugins. http://symfony.com/doc/current/service_container/shared.html says it gives us a new instance, and yeah that seems super important in this case.

    Seems like it'd be worth a kernel test that fails if that line is removed?

Also I just read #46 and now I'm equally confused.

EDIT: crossposted with #47, that works for me, and removes the need for the extra test coverage I requested.

alexpott’s picture

StatusFileSize
new2.28 KB
new7.83 KB

Addressing @tim.plunkett's review.

alexpott’s picture

chx’s picture

Thanks, that's an interesting direction but you no longer need create in this version I beleive.

chx’s picture

StatusFileSize
new7.55 KB

Note however this will break any modules implementing UserDataInterface . I guess that's better than subtly breaking for not having the service. Those modules will be rare, no doubt.

Removed create, no other changes.

chx’s picture

StatusFileSize
new7.51 KB
new704 bytes

Ops, I left in a stray use statement. Fixed. Pity __call can't satisfy an interface the whole class could be collapsed into a single method call. Interdiff to 49.

legolasbo’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/user/src/UserData.php
    @@ -77,6 +77,13 @@ public function get($module, $uid = NULL, $name = NULL) {
    +    return new UserDataQuery($this->connection->select('users_data', 'ud'));
    

    Shouldn't the UserDataQuery be a service instead of creating it here?

  2. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,78 @@
    +    $this->select->condition('module', $module);
    

    I believe this class can never return any values if multiple module conditions have been set. Therefore the method should check if a module condition has been set already and throw an exception OR it should add the condition as an OR condition.

  3. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,78 @@
    +    $this->select->condition('uid', $uid);
    

    This should also check if a condition has already been set or add it as an OR condition.

  4. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,78 @@
    +    $this->select->condition('name', $name);
    

    Same here

  5. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,78 @@
    +    if (!is_scalar($value)) {
    

    And here

  6. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,61 @@
    +  public function module($module);
    

    The name 'module' does not describe what this method does. Shouldn't this be setModuleValue or setModuleCondition?

  7. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,61 @@
    +  public function uid($uid);
    

    The name 'uid' does not describe what this method does. Shouldn't this be setUidValue or setUidCondition?

  8. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,61 @@
    +  public function name($name);
    

    The name 'name' does not describe what this method does. Shouldn't this be setDataKeyName or setDataKeyNameCondition?

  9. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,61 @@
    +  public function value($value);
    

    The name 'value' does not describe what this method does. Shouldn't this be setValue or setValueCondition?

  10. +++ b/core/modules/user/src/UserDataQueryInterface.php
    @@ -0,0 +1,61 @@
    +  public function execute();
    

    This violates the single responsibility principe. The method both executes a query and returns it's result.

    I suggest adding a getResults() method.

alexpott’s picture

Title: Add a service to find uid in users_data with $module, $key, and $value » Add the ability to find uid in users_data with $module, $key, or $value to user.data service
Issue summary: View changes
chx’s picture

Status: Needs work » Needs review

> Shouldn't the UserDataQuery be a service instead of creating it here?

You are of course aware that the exact opposite was done by a core committer in #47.

> The method both executes a query and returns it's result.

So does db_select()->execute().

As for the rest of the requests, I will not overengineer a small class like this. Simply ->module() won't be called twice or if it is, their problem. We didn't build such safety blocks into db_select() or EQ although certainly we could've.

https://medium.com/@chx/the-terrible-cycle-of-contributing-to-drupal-cor... 4. is very, very relevant.

alexpott’s picture

Re #54 well I think the points about multiple calls to ->module etc.. are valid.
I think #54.1 came from the IS which I had failed to update - my fault.
I agree with @chx about #54.10 - I think execute returning a traversable is just fine.

Patch incoming.

alexpott’s picture

StatusFileSize
new8.5 KB
new11.38 KB

Yep this behaves differently from a db query but this has a slightly different aim. It's meant to be a something that retrieves data from the user.data service based on a limited set of conditions you supply it. Seems elegant to make it work regardless of how often setFoo() is called.

chx’s picture

Unfollowed. I never unfollowed a work patch before but there's a first for everything.

alexpott’s picture

StatusFileSize
new11.29 KB
new11.94 KB

So @chx didn't like the move away from querybuilder-lite, however the points @legolasbo raises in #54 about calling the condition setting methods more than once are valid. I think the behaviour of #53 is unexpected. The patch in #58 solves this but it opens another problem how to query for NULL values. After some discussion in IRC I think the best way forward is to use an exception since setting the same condition twice is never the right thing to do with this simple query service.

legolasbo’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -10,35 +11,14 @@
    +  protected $sets;
    

    Since this is an array, why not initialize it as an empty array?

  2. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,109 @@
    +  /**
    +   * Stores which conditions have been set.
    +   *
    +   * @var array
    +   */
    +  protected $sets;
    

    Let's initialize this array

  3. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,109 @@
    +    $this->setter('module', $module);
    +    return $this;
    

    If we make setter return $this then these setters can be simplified to return $this->setter(...);

  4. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,109 @@
    +    $is_scalar_value = is_scalar($value);
    

    Nit: $isScalarValue

  5. +++ b/core/modules/user/tests/src/Kernel/UserDataQueryTest.php
    @@ -0,0 +1,179 @@
    +  /**
    +   * Data provider for testUserDataQuery.
    +   *
    +   * @return array
    +   */
    +  public function userDataQueryProvider() {
    ...
    +  /**
    +   * Data provider for testUserDataQueryMultipleMethodCalls.
    +   *
    +   * @return array
    +   */
    +  public function userDataQueryMultipleMethodCallsProvider() {
    

    Let's put these utility methods at the top of the class. Also, they should be 'private' or 'protected'

  6. Nitpick: The tests don't test if the setter methods return self.
legolasbo’s picture

Status: Needs work » Reviewed & tested by the community

The findings above are no deal breakers however. Would be nice to see them changed but RTBC anyway.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review

Re #61
1. Because that is not necessary.
2. Because that is not necessary.
3. Because reading return $this; is very simple. As a dev you don't have to think whilst return $this->setter() you have to work out what that returns.
4. Not required and not yet implemented in core.
5. There is no standard for order and nope they shouldn't be private or protected.
6. See 3

alexpott’s picture

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

StatusFileSize
new706 bytes
new11.93 KB

We can add some implicit coverage of the chaining very simply.

legolasbo’s picture

About 5. I know there is no standard for order, but grouping tests and utility methods improves readability of the code which is why is suggested it.

alexpott’s picture

@legolasbo but there is an order - the providers come immediately after the test method that they provide for. This order is almost standard in core tests.

alexpott’s picture

Status: Reviewed & tested by the community » Needs review
StatusFileSize
new2.52 KB
new12.5 KB

So the \Drupal\Tests\user\Kernel\UserDataQueryTest::testSetValue was not quite testing what I hoped for. After making it test the adding of the serialized condition properly I realised that the addition of this condition seems unnecessary. Since if you already have a serialized value why would you want to unserialize it to pass it to setValue to serialize it again.

alexpott’s picture

StatusFileSize
new6.61 KB
new12.58 KB

Better names for things.

Status: Needs review » Needs work

The last submitted patch, 69: 2507117-2-69.patch, failed testing.

legolasbo’s picture

Status: Needs work » Reviewed & tested by the community
+++ b/core/modules/user/tests/src/Kernel/UserDataQueryTest.php
@@ -0,0 +1,189 @@
+    // and re-running the query does not break is the value is not scalar.

Typo: ..if the value is not scalar.

Other than that I have nothing else to add to this patch.

fabianx’s picture

RTBC + 1, I like how the original service and the new query class are combined.

alexpott’s picture

StatusFileSize
new732 bytes
new12.58 KB

Fixing #71

alexpott’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs change record

We need a change record for this.

chx’s picture

And also this is broken because serialized condition is not set so if someone demented enough stored b:0; as a string value and then queried for FALSE then you'd get the former as well.

alexpott’s picture

@chx good point. It seems a shame to not cope with the case where you already have a serialized value. I can easy imagine that happening.

alexpott’s picture

Status: Needs work » Needs review
StatusFileSize
new2.49 KB
new13.49 KB

Fortunately we can have the best of both worlds.

chx’s picture

Seriously it's going overboard the only thing I was missing is a $this->select->condition('serialized', 1); noone will want (or should) use a setSerializedValue. If we want that method, make it protected please.

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

jibran’s picture

Status: Needs review » Needs work

I guess NW for #78.

larowlan’s picture

  1. +++ b/core/modules/user/src/UserDataInterface.php
    @@ -32,6 +32,15 @@
    +  public function getUserDataQuery();
    

    Adding a new method to an existing interface is a BC break, we need to add a new interface, and have UserData implement that too.

  2. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,120 @@
    +  protected $existingConditions;
    

    this should be initialized to an empty array

  3. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,120 @@
    +  public function setSerializedValue($value) {
    

    Is there a reason why this is public?

  4. +++ b/core/modules/user/src/UserDataQuery.php
    @@ -0,0 +1,120 @@
    +    if (isset($this->existingConditions[$name]) && $this->existingConditions[$name]) {
    

    !empty?

avpaderno’s picture

Status: Needs work » Needs review

Just nitpicking: Since $is_scalar_valueis used just once, is_scalar() can be used directly inside the if() statement.

+  public function setValue($value) {
+    $is_scalar_value = is_scalar($value);
+    if (!$is_scalar_value) {
avpaderno’s picture

Status: Needs review » Needs work

Also, it is sufficient to use !empty($this->existingConditions[$name]), instead of isset($this->existingConditions[$name]) && $this->existingConditions[$name].

+  protected function createCondition($name, $value) {
+    if (isset($this->existingConditions[$name]) && $this->existingConditions[$name]) {
+      throw new ExistingConditionException("Can not add another condition on '$name'");
+    }
avpaderno’s picture

I would instead use the following code.

  /**
   * {@inheritdoc}
   */
  public function setValue($value) {
    $serialize = !is_scalar($value);
    if (serialize) {
      $value = serialize($value);
    }
    $this->setSerializedValue($value, $serialize);
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  protected function setSerializedValue($value, $serialized = TRUE) {
    $this->createCondition('value', $value);
    $this->select->condition('serialized', (int) $serialized);
    return $this;
  }

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

xjm’s picture

Issue tags: -beta deadline

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.