1

EDIT: I need to alter the settings of an entity reference field for administrators only. I need to change from the settings in the first image, to the settings in the second image.

Current Settings Desired Settings

The reasoning is that normally when creating content, I want users to select from the options available in the view. The options in the view are the "Bands" (a content type) that each individual user has created. However, if an admin needs to moderate the content, they are not allowed to save it after editing because the content of the field is not an option available to the admin (i.e. the band entered by the original user, and currently saved to the entity reference field, is not a band created by the admin and is therefore not an option in the admin's array). On save by an admin, it fails to save and throws an error of "The referenced entity (node: XXX) is invalid", staying on the edit page.

I tried changing $form_state through hook_form_alter, but apparently $form_state settings aren't saved on submission. So, I tried adding the alters to a validation function, which also didn't work for me. Then, I found the settings within $context of hook_field_widget_properties_alter, but it seems that $context can only be referenced and not altered. I also came across this post, which seems to state that there isn't really a hook for altering field settings.

Unfortunately, I have realized that I really need this feature in order to moderate my site. As always, any help is incredibly appreciated, as this issue seems to be beyond my abilities.

Here's some screenshots as requested by Minty:

Casual user's options, populated by the view, include only their own bands enter image description here

What I want in the admin's options, which should be all the bands authored by all users. (note that it currently shows all bands, because I figured out how to do contextual filter in the view based on the current user, not because I was able to alter the field settings as asked by the issue): enter image description here

Without the above fix, only the admin's bands appear in the list when editing a node. Therefore, as stated in the issue, it throws an error that the previously saved band is not a valid option for the field, and the node cannot be saved.

  • entity ref module uses entity api and that is not the same as Form API. Also, you only want to moderate the content, right? Then just create a new view, filter by last edited. Add fields like author, title etc. And then restrict that view by user-role and show it somewhere in the admin page. Thats it. – Minty Aug 4 '12 at 18:58
  • Yes, I want to moderate the content, in the form of being able to edit a text field if it contains inappropriate content of some sort. The problem is still the way that the field settings are set up. I am not able to save existing nodes containing this field, because the item present in the saved node is not available to the admin, because it is not included in the view for the admin user. Creating a new view does not solve my problem, because I still am unable to tell the Entity Reference field to select a new view based on the admin role. – Mrweiner Aug 4 '12 at 19:32
  • Can you provide some screenshots? I am unable to figure out what the problem is. – Minty Aug 4 '12 at 19:37
  • Added to bottom of issue. – Mrweiner Aug 4 '12 at 20:49
  • May be you should post your answer, so if other people have problems then they can refer to your answer. – Minty Aug 7 '12 at 0:41
3
+100

With respect to your original post, I ran into this exact issue here in drupalsixlandia and resolved it with a dull ax inside of views. By exact meaning I wanted to have a select list of bands created by a user presented to them when they wanted to add an album, but when an admin went in to add/edit things, s/he should see all of the bands on the system.

So, I created a view and used this view to populate the band Node Reference field in the album type in CCK.

I called it my_band and it filters on published bands and returns the Node Title of the band as the field. It has one argument, or in D7 a contextual filter, User Uid and in action to take if argument not present I provide a default argument via PHP code:

global $user;

if (in_array('super user', array_values($user->roles))) {
  return -1;
} else {
  return $user->uid;
}

Then in the Validation of that argument, I again use PHP:

if ($argument == -1) {
  return FALSE;
} else {
  return TRUE;
}

with display all values if validation fails.

So, now what happens (here at least) is if a casual user wants to create an album, s/he is presented with a list of only the bands s/he has created. But, if any user with the super user role wants to create or edit an album, the validation is forced to fail, and the argument is ignored and all bands in the system are returned.

Perhaps with some D7ing of the code above this might work for you.

  • Okay, so it turns out that this is now working for me 50%. It is populating the field fine for casual users. However, for admins, the field has no options. This seems to mean that the statement is evaluating correctly, but instead of removing the filter, it is removing the options. Any ideas? – Mrweiner Aug 4 '12 at 18:21
  • In the above comment, I failed to realize that I hadn't added an action if the statement didn't validate. However, I have now added Specify Validation Criteria -> Validator: Basic Validation -> Action to take if filter does not validate: Display all values for the specified field. Still though, the admin field options are empty. – Mrweiner Aug 4 '12 at 18:39
  • 1
    in D7, I think you do ` if (in_array('administrator', $user->roles))` instead of array_values..., so make sure that's setup correctly – Jimajamma Aug 4 '12 at 19:00
  • That is indeed what you do. I (forgot to mention) that I had changed that portion of the code. I have also placed dpm($argument) within the if statement to check if it is evaluating correctly, which it seems to be, so I don't think that that is the problem. I guess that would mean it has to be the if ($argument == -1) {, right? If that's the problem, and you're not sure of another way to represent this, I might have to do some digging. – Mrweiner Aug 4 '12 at 19:13
  • Ah, the issue was that I didn't realize there was a "PHP code" option for validation, and I had the validation portion of the code within the "Provide default argument" area. This is working perfectly. Thanks so much! I've been banging my head against the wall for a week. – Mrweiner Aug 4 '12 at 19:18
0

The $form_state variable will be processed when the form is validated, when the user-submitted values are inserted into the array. So any changes you add when the form is first being built won't be reflected once it's been validated/submitted.

The most common method I've seen to manipulate the $form_state is in a custom validation function, it might be worth giving that a try:

function entityreference_widget_form_alter(&$form, &$form_state, $form_id) {
  if($form_id ==  'review_node_form') {
    $form['#validate'][] = 'entityreference_widget_form_validate';
  }
}

function entityreference_widget_form_validate($form, &$form_state) {
  $form_state['field']['field_review_band']['und']['field']['settings']['handler'] = 'base';
  // etc...
}
  • I hadn't realized that $form_state was called on submission. Is there a way that I can alter field settings in $form so that they are altered before the form is built? Like I responded to Max, I don't see anything referencing settings within $form. – Mrweiner Jul 26 '12 at 15:27
  • I'm not familiar with the way entity reference processes it's widget I'm afraid; chances are those settings are part of a field so could be added by the module at any point in the process. You might have better luck using hook_field_widget_alter() – Clive Jul 26 '12 at 15:36
0

From what I can tell, the problem seems to be that you're filtering the view for bands authored by the current user. Then, when the admin tries to submit an edit form with a band that s/he is not the author of, the form gives an error.

If this is accurate, maybe the best solution is not to manipulate this in the form but in the view. You could change the view logic to show a band if the current user is the author OR if the user is an admin. I'm pretty certain you can achieve this with the Views Or module. Your two criteria (author, admin) would need to both be checkable with a filter or both with an argument (you can't do 'argument OR filter'), but I think this is the case. I would then disable ('#disabled' => TRUE) the form element using a form_alter when an admin is viewing it, so that they can't set it to any band.

If not, another option is to use a Views hook to remove the author filter if the current user is an admin. This would achieve the same effect described above.

One thing to consider: which widget are you using for the band select? If it's anything other than autocomplete, this method may not be advisable because it would mean loading all the bands on the page as <select> options or whatever. If this a very large number of bands, it could seriously slow down your page.

  • Yes, the situation is correct. If I were to take one of these options, I'd have to go with the views hook option, because really what I need to do is remove the author argument if the user is admin. However, when trying to implement the hook, I'm getting the error of Fatal error: Cannot use object of type view as array in ... in any conditional statement involving $view. So I can't even tell it to apply the hook only if($view['name'] == 'users_bands', because the error is thrown. Any ideas? As for widget type, that's a non-issue. I already have it altered to autocomplete for admins. :) – Mrweiner Jul 29 '12 at 6:05
  • The error means that you're trying to reference a view property as if it's an array, like $view['something'], but the view is an object so it should be $view->something. Note that both approaches achieve the same thing. You can take a Views Or approach and achieve the same thing without any custom code (but with an extra module, of course), pending the limitations listed above. – goron Jul 29 '12 at 7:59
  • Again, I would recommend, for both approaches, to disable the field as explained above. – goron Jul 29 '12 at 8:02
  • Unfortunately, on D7 so no Views OR. However, I did indeed finally get the views alter to work after adding the view as a default view. I also got '#disabled' => TRUE to work, but want to set it only if the UID for the author of the content does not match the current (admin) UID. This is because, the users with admin accounts also create content, so they must be able to alter that field in their own content. I'm using $user->uid != $form['uid']['#value'], and it is working fine, but is also showing the error Notice: Undefined index: uid, referring to the $form portion. Any idea why? – Mrweiner Jul 29 '12 at 23:00
  • Ah, apparently the OR functionality is included in Views 7.x-3.x. I didn't know. See drupal.org/node/791216. About the error, it must mean that there is no uid index in the $form. Have you inspected the form using devel module? (i.e. dpm($form); in your alter) – goron Jul 29 '12 at 23:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.