I am having difficulty getting around some perms issue, or finding the right incantation to do so...

I have a content type called Application. It gets some fields filled via my custom module, upon submission. I use the hook_node_insert to do this, as Rules module needs to come along next and use those fields. So within my module I can retrieve and set fields using field_get_value, and then field_attach_update. And that works happily SO LONG AS I AM ADMIN. As soon as a regularly authenticated user tries the process, the final field_attach_update('node', $node) fails, probably because the process is running as a user that doesn't have access to writing the Application (it should be read-only for them!).

So how do I overcome this? Can I temporarily elevate the user doing the PHP work? Or is there another function set I should be using? (I tried with entity_metadata_wrapper, but couldn't get the right incantations to load the fields from my nodes!)

Accepted answer

And just to add - I've never used field_attach_update(), ever... and I've been tinkering with entities for a long time. field_attach_update() is one of those functions that are usually called internally by others, so it's better to make use of the higher level node_save() once you have updated the node object.

Most helpful answers

I just wanted to add one more comment to this thread. I believe the reason why field_attach_update() did not work for you is because you need to flush the individual entity from the entity cache. The docs for the function state that "When calling this function outside an entity save operation be sure to clear caches for the entity: entity_get_controller($entity_type)->resetCache(array($entity_id))".

It seems like it was not related to permissions, but rather to cache. 

I believe that, if you don't enable the VBO submodule actions_permissions, you don't need to set that permission up - but I may be misremembering.

Comments

I would manually set the values of the fields, either directly (as in $node->field_test['und'][0]['value'] = 'xyz';), or user entity metadata wrappers to avoid dealing with the field array.

If you post here the code snippet where you tried the wrappers, I can help. I use them extensively. 

Don't forget to save the node. 

So, in other words, I'd avoid field_attach_update, since that seems to take into account writing permissions. Setting the values manually and saving should work, as node_save() doesn't check permissions.

BTW, I discovered a potential bug with hook_entity_insert(), which I don't know if it exists in hook_node_insert(). The is_new flag is not cleared before the invocation of the insert hook. This creates problems when saving the entity again, as Backdrop thinks it's still new. So, you have to manually unset the is_new flag from the entity before saving within the hook. Again, not sure if this is a problem with nodes.

 

And just to add - I've never used field_attach_update(), ever... and I've been tinkering with entities for a long time. field_attach_update() is one of those functions that are usually called internally by others, so it's better to make use of the higher level node_save() once you have updated the node object.

Thanks mate. Will try node_save again; I had stopped with that due to the Rules engagement...

my code, covered in debugs:

if($node->type==='application'){

//dd($form_state,'App_form_state'); // use dd to dump to tmp of webserver the debug file which is too big for the browser to render

//dd($form,'App_form');

if($node->field_opening){

$node->original = isset($node->original) ? $node->original : NULL;

dsm($node);

// $opening=$node->field_opening['und'][0]['target_id']; // the id of the opening node

$opening = field_get_value($node,'field_opening','target_id');

watchdog("VHB_node_insert","VHB module: Opening=".$opening);

$open_node=node_load($opening);

// $open_node=entity_metadata_wrapper('node',$opening);

dsm($open_node);

//$raw_collection = $open_node->field_collection->value();

// Wrap it with Entity API

//$collection = entity_metadata_wrapper('field_collection_item', $raw_collection);

dsm(field_get_value($open_node,'field_contact_email','value'));

//set defaults

$email='email@example.com';

$fname='To Whom It May';

$lname='Concern';

//load opening settings if valid

$opence=field_get_value($open_node,'field_contact_email','value');

if(!empty($opence)){ $email = $opence;}

$openfn=field_get_value($open_node,'field_first_name','value');

if(!empty($openfn)){ $fname = $openfn;}

$openln=field_get_value($open_node,'field_last_name','value');

if(!empty($openln)){ $lname = $openln;}


watchdog("VHB_node_insert","VHB module: Email=".$email." fname=".$fname." lname=".$lname);

$node->field_contact_mail['und'][0]['email']=$email;

$node->field_contact_fname['und'][0]['value']=$fname;

$node->field_contact_lname['und'][0]['value']=$lname;

watchdog("VHB_node_insert","VHB module: Email=".$node->field_contact_mail['und'][0]['email']." fname=".$node->field_contact_fname['und'][0]['value']." lname=".$node->field_contact_lname['und'][0]['value']);

//node_save($node);

field_attach_update('node', $node);

//entity_get_controller('node')->resetCache(array($node));

watchdog("VHB_node_insert","VHB module: Node saved=".$node->title);

}

}

 

I've looked at the code you pasted, and also tested it, and it works fine. The use of field_attach_update seems to be working great.

The part I don't understand is when you say that authenticated users don't have save privileges for the node type "application" - how does that node get saved then, to trigger the insert hook? 

They have write/save ability for most of the node creation process, but not all of it, because some of the Application fields are confidential, but need to be filled by code on the way past, and this is where it was failing;

  • the only-just-authenticated users, with role of Authenticated, were the active user within the session, and so without the ability/perms to CRUD those confidential fields, the fields would remain empty.
  • the Admin / Manager / Staff level roles have the CRUD perms, so it's not a problem for them.
  • field_attach_update works only for the roles that have CRUD perms. node_save, as you said, ignores the CRUD perms and does the job regardless. Which is good to know; they both have their place in the toolbox.

So yes, it is rocking along with node_save.

Cheers!

 

I have successfully updated the node with node_save, and found that Rules wouldn't send the email still, until perms set like this:

Thanks very much!

I believe that, if you don't enable the VBO submodule actions_permissions, you don't need to set that permission up - but I may be misremembering.

I just wanted to add one more comment to this thread. I believe the reason why field_attach_update() did not work for you is because you need to flush the individual entity from the entity cache. The docs for the function state that "When calling this function outside an entity save operation be sure to clear caches for the entity: entity_get_controller($entity_type)->resetCache(array($entity_id))".

It seems like it was not related to permissions, but rather to cache.