I have a use case that I haven't seen come up much, but that which at least one other person has. I thought about proposing it first as a feature request to Entity Reference and figuring out with the community how it should work. Otherwise, I'll create a module.

Before I continue, look at this code:

function finance_payments_views_query_alter(&$view, &$query) {
  if (arg(0) == 'node' && arg(2) == 'edit') {
    $node = menu_get_object();
    if ($node->type == 'payment') {
      $its_this_group = NULL;
      $type = NULL;
      foreach ($query->where as $index => &$condition_group) {
        foreach ($condition_group['conditions'] as &$condition) {
          if ($condition['field'] == 'field_data_field_remaining.field_remaining_value') {
            // Flag this condition group as needing another condition
            // Use $query since that survives the foreach()
            $its_this_group = &$query->where[$index];
          }
          // Figure out the type from the filter setup
          if ($condition['field'] == 'node.type') {
            // Just the first one is fine
            $type = $condition['value'][0];
          }
        }
      }
      if ($its_this_group && $type) {
        $its_this_group['type'] = 'OR';
        $node_field_name = $type == 'income' ? 'field_line_item' : 'field_target_line_item';
        $query_field_name = 'node.nid';
        $its_this_group['conditions'][] = array(
          'field' => $query_field_name,
          'value' => $node->{$node_field_name}[$node->language][0]['target_id'],
          'operator' => '=',
        );
      }
    }
  }
}

What it does

This code uses hook_views_query_alter() to change a particular condition group (the one that causes the existing entity field values to be excluded sometimes) into an OR group and to add a condition to it so that the currently-selected income or expense (field_line_item and field_target_line_item are the Entity Reference fields). This ensures that they are available in the list of valid entities that can be referenced (for which the module checks).

Why?

In my case, Payment nodes can potentially reference any income or expense item in the system, but with hundreds of each now in there, page load time gets too high. Originally (and again now), I had a filter saying that if the income was used up or the expense was all paid, it need not appear when creating a payment. Unfortunately, this meant I couldn't edit payments where both of the entities met those filter conditions - they wouldn't be available in the list. The above code solves that. It's not that elegant, though, and, as it stands, it would require the user telling us a few things for it to work, like into which condition group we should inject our query-altering, for example.

I think this could be easier, but I'm not sure how it should work. An idea I had just now was simply to add an option or widget that, if selected, shows a checkbox on the node edit form that says, "Force value to be:" and then if checked shows an autocomplete box into which the user can search for the value to use. The "force" box could either use a different view or just go by content type. It'd basically be like having two reference fields in one place, but only one value is actually stored, and the forced value takes precedence.

Hmm...yeah, that might actually be the way to do it, but, before I try to standardize things, what do you guys think?

Comments

DamienMcKenna’s picture

Modifying entity reference values (and other references) is a complicated thing - an object's attributes can change so they no longer match the original settings, be it a node being unpublished, a permission changing, or just a field or something else changing so it no longer matches the assigned view. When editing a object when the referenced objects no longer match, should it be forced that the objects may no longer be referenced? Should there be a permission that allows these objects still be referenced? Should it be a per-field option?

Or are we instead saying that this use case is not supported?

wizonesolutions’s picture

Ah - a permission could be a logical approach. I suppose the "forced" value is perhaps too overarching. +1