I am using a reverse relationship between entities which is defined by Entity API's Views controller.

One of my fields is using a handler which subclasses views_handler_field_entity, because it needs to work with full entities, and views_handler_field_entity::pre_render() loads them. This field is on the relationship.

This would work fine except for views_handler_field_entity::query() is breaking the base table, which then prevents the entities from being loaded in get_result_entities().

Here's the code in the views_handler_field_entity handler:

  function query() {
    $this->table_alias = $base_table = $this->view->base_table;
    $this->base_field = $this->view->base_field;

    if (!empty($this->relationship)) {
      foreach ($this->view->relationship as $relationship) {
        if ($relationship->alias == $this->relationship) {
          $base_table = $relationship->definition['base'];
          $this->table_alias = $relationship->alias;

          $table_data = views_fetch_data($base_table);
          // *** everything is fine up to this point.
          $this->base_field = empty($relationship->definition['base field']) ? $table_data['table']['base']['field'] : $relationship->definition['base field'];
        }
      }
    }
    // Base field is now set to something incorrect!
    dsm($this->base_field);

$this->base_field is getting set to the base field for the relationship. This is not an Entity ID field, but the foreign key field:

BaseEntity.entity_id ----> JoinEntity.foreign_id

Trying to load entities with 'foreign_id' won't work at all. What is needed is JoinEntity.entity_id. This is actually already present in $table_data['table']['base']['field'] -- just the code is electing not to use that but take something wrong instead.

I would make a patch to just rip this out, but I'm not sure what that line is trying to accomplish.

Comments

joachim’s picture

> I would make a patch to just rip this out, but I'm not sure what that line is trying to accomplish.

On further reflection, I suspect that line is trying to cater for forward relationships, eg:

- Base entity table has a foreign_id
- Join entity table has an entity_id

and the relationship is thus:

    'relationship' => array(
      'base' => 'join',
      'base field' => 'entity_id',
      'relationship field' => 'foreign_id',
      'handler' => 'views_handler_relationship',
    ),

Here, the base field is the entity ID of the table we're joining to.

But flip this over to being a reverse relationship, where we go from a table with an entity ID and use that to join to a table that points to us with a foreign key, and it doesn't work at all.

andrewbelcher’s picture

This issue actually breaks all views_handler_field_entity and extending fields, as the entities do not get correctly loaded for a relationship where the join is not on the entity id. In #2856944: 'Please select at least one item' - after upgrading to 7.x-3.4 we found people having problems with the VBO operation field on OG Membership entities, which join via the etid or gid fields, rather than the OG Membership entity ID (id). This meant that no entities were being loaded for that relationship and therefore the VBO operation field was broken.

Similar to @joachim, I'm not 100% sure what it's trying to do here, but I would have thought \views_handler_field_entity::query needs to be re-worked to ALWAYS use the entity ID field for the particular entity type, rather than trying to do anything based on base fields of either the base table or the relationship. The join field is only relevant for the join, so I think it's simply unnecessary. I've attached a patch to that end...

andrewbelcher’s picture

Status: Active » Needs review