When you add the condition 'user has role(s)' you get the following error.

Fatal error: Call to a member function id() on string in ...\rules\src\Plugin\Condition\UserHasRole.php on line 55

This problem (and others like it) will be solved in the generic solution on #2800749: Support upcasting entity IDs to full entity contexts. There is patch there, so if you have this problem please test the patch there.

Leaving this issue open so that it can be found easily by a default search.

Comments

simonmc created an issue. See original summary.

rjjakes’s picture

StatusFileSize
new3.33 KB

I'm getting the same issue with Drupal throwing:

Warning: preg_match_all() expects parameter 2 to be string, array given in Drupal\typed_data\PlaceholderResolver->scan() (line 186 of modules/typed_data/src/PlaceholderResolver.php).

It looks like the code was expecting UserHasRole()->doEvaluate()->$roles to be an array of role id's where it's actually an array of role system names.

Additionally, the preg_match_all() error was occurring because the string was being passed through to the token processor as an array.
This also happens for the "Node is of type" condition.

A similar issue was documented here: https://www.drupal.org/node/2824348 and I tracked it down to: Drupal\rules\Plugin\RulesDataProcessor\TokenProcessor()->process().
I updated that function to handle array inputs as well as string inputs.

The attach patch fixes the above so the 'User has roles(s)' and 'Node is of type' condition now works correctly with no errors.

rjjakes’s picture

Status: Active » Needs review
Anonymous’s picture

This patch works for me with Node is of type. I didn't test it with User has roles. Thx for your work on this. Now rules is the first time usable for me.

jbabiak’s picture

Status: Needs review » Reviewed & tested by the community

Tested with 'User has roles' and this fixed the error I was getting. Thanks!

fago’s picture

We should not change the argument from the entity to a dumb string, that will make the condition worse in the end. What we need to fix is entity-id handling, this is todo: see #2800749: Support upcasting entity IDs to full entity contexts.

I'm not sure about the related problem with the token processor. Can you give an example on how you used that? We should extend the test coverage with a usage like that (given it's valid) and fix the bug then.

fago’s picture

Status: Reviewed & tested by the community » Postponed (maintainer needs more info)
ckaotik’s picture

Status: Postponed (maintainer needs more info) » Needs work

@fago I've got some details that hopefully help. I've created a minimal sample rule that fires when updating a node and checks if the current user is adminstrator. At least, that's what it should do if not for this bug ;)

langcode: en
status: true
dependencies: {  }
id: node_edit_admin
label: 'Node edit user is admin'
events:
  -
    event_name: 'rules_entity_update:node'
description: ''
tags:
  - ''
config_version: '3'
expression:
  id: rules_rule
  uuid: a84a665d-f307-484e-8cba-f0b15538ee12
  conditions:
    id: rules_and
    uuid: 3067b30f-4b49-4bbe-adba-0f1651434523
    conditions:
      -
        id: rules_condition
        uuid: d9bf847b-6e9c-45ef-8014-fa1736566dfc
        context_values:
          roles:
            - administrator
          operation: AND
        context_mapping:
          user: '@user.current_user_context:current_user'
        context_processors:
          roles:
            rules_tokens: {  }
          operation:
            rules_tokens: {  }
        provides_mapping: {  }
        condition_id: rules_user_has_role
        negate: false
  actions:
    id: rules_action_set
    uuid: 1bc98e46-ee7f-4ced-84ac-0bc4e7c433ab
    actions: {  }

As you said, the user roles are never upcast to proper entities. Thus, we only ever have the string and never the entity itself.
rules_tokens is always added as the context_processor, no matter what type the actual context is.

Warning: preg_match_all() expects parameter 2 to be string, array given in Drupal\typed_data\PlaceholderResolver->scan() (line 186 of modules/contrib/typed_data/src/PlaceholderResolver.php).

Drupal\typed_data\PlaceholderResolver->scan(Array) (Line: 63)
Drupal\rules\Plugin\RulesDataProcessor\TokenProcessor->process(Array, Object) (Line: 294)
Drupal\rules\Plugin\RulesExpression\RulesCondition->processData(Object, Object) (Line: 85)

When then using the above patch as a workaround, there's a preg_match error described above. Seems rules_tokens doesn't properly handle contexts marked as multiple (i.e. the "roles" context in this case). It generally doesn't make that much sense on non-string contexts, I think.

saranya ashokkumar’s picture

StatusFileSize
new1.32 KB

Hi,

I have created a patch which will work if the roles is direct input. I couldn't give role in data selector so, I just implemented only for direct input.

jhedstrom’s picture

This patch no longer works for some reason on 8.4.x, as the $value that is coming through is now the role name, rather than the ID.

jhedstrom’s picture

The patch in #2816157-05: Simplify UserHasRole::doEvaluate() does work with 8.4.x, since it attempts to load the role by the label.

rjjakes’s picture

Thanks @jhedstrom - I've kicked off a new test. Let's see what happens.

jonathan1055’s picture

Hi,
The 15th Aug test failure for patch #2 above, https://www.drupal.org/pift-ci-job/740113 is not related to this issue. I have reported it on #2903101: AutocompleteTest fails at D8.4 due to changed "publishing" text, OK at D8.3, made a patch and a github pull request. So far, I am the only one following that issue - it needs more activity and interest, as it is preventing any other patches from passing.
Jonathan

gsquirrel’s picture

Tried both patches but neither helped in my case, may have the selector wrong but have tried every combination. I am trying to test the node author rather than current user and that might be why I cannot get the right context. Is it supposed to be checking against the uid or what?

node.uid.entity
node.uid
node.uid.entity.roles

also tried the current node context:
@node.node_route_context:node
@node.node_route_context:node.uid

etc.

even tried direct input with twig tokens like this (as it worked for another condition to get node author email)
{{ node.uid.entity }}

Does anyone know what it should be?

jonathan1055’s picture

I have started work on #2800749: Support upcasting entity IDs to full entity contexts which should solve this issue in a generic way. There is a patch which you can test, and it should fix Fatal error: Call to a member function id() on string in ... \src\Plugin\Condition\UserHasRole.php in the way that Fago wants.

Jonathan

jmuzz’s picture

I have tested jonathan1055's patch 2800749-8.upcast.patch which installed cleanly for me but did not fix the "Call to a member function etc" error in UserHasRole. For now I am using rules-user_has_role-2824360-9-8x3x.patch .

jonathan1055’s picture

Status: Needs work » Active

#2800749-36: Support upcasting entity IDs to full entity contexts had a generic patch for this problem. Please test it.

This issue will be resolved with that soluiton, so switching it to 'active' as there is no patch here that needs work. Not closing as duplicate yet, so that the issue is more easily findable and still appears in dashboards and open issue lists.

jonathan1055’s picture

Title: Fatal error when add condition 'user has role(s)' » Error "Call to a member function id() on string" for condition 'user has role(s)'
Issue summary: View changes
Related issues: +#2725525: Fatal error: Call to a member function id() on a non-object in UserRoleAdd.php on line 49, +#2816157: Simplify UserHasRole::doEvaluate()

Adding more info to the title, to allow it to be found more easily via searching the issue queue.

jonathan1055’s picture

Status: Active » Fixed

The solution in #2800749: Support upcasting entity IDs to full entity contexts has been committed.

Marking this as 'Fixed' even though there was not actual commit here, so that this issue remains viewable in the drupal dashboard for two weeks. Just to give people the chance to see that the commit has been done.

Status: Fixed » Closed (fixed)

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