Comments

xen’s picture

Status: Needs review » Needs work

virtual_field_handler_field_virtual_field.inc seems to be missing from the patch?

Views support would be so nice.

batje’s picture

Here is another version, including all data, and including searchAPI supprt (so virtual fields also can be rendered on views based on SearchAPI)

xen’s picture

I get broken handler when trying to use this field?

Not too fond of the fact that it seems to be loading each entity individually instead of using entity_load with an array of ids. It's a bit of a performance killer. There also seems do be a lot of magic around Search API. Why is that? I thought the idea behind using search API views was to hide the fact that it was a search. If they're really that different, having separate handlers for entity views and search API views might be a better solution.

What's going on here?:
+ // Only pass a single item to the formatter_view hook. Feel free to build a foreach here, we had issues
+ // with the key that was returned. The documentation says it should be 0, 1, 2 etc but we had to put in
+ // a certain string.

Also, it seems to be one views field where one can select a virtual field to render. Like date modules odd handling of fields. I'd rather have a handler that provides multiple views fields, like the field module.

batje’s picture

In general, we went step by step getting the thing to do what we need, based on the virtual_field, this code and a custom virtual_field with a formatter we wrote. It's all pretty new to use, fields + ctools + views 3.0 + searchAPI, so this is how far we got. And yes, it doesnt win a beauty contest.

- Not sure why you get a broken handler, what does your syslog or apachelog say?

- SearchAPI's basetable & related things are very different from the standard node one. As we need to manually load the entity (all at the same time, or one by one) we need to get the information from somewhere else, depending on the type of query the view is based on. Not sure if we would need a 'Virtual SearchAPI' Field and a 'Virtual standard' field. Rather have ugly code than the user realizing what is going on.

- Not sure where a field-handler would load all entities into a views result.

- What was going on was that the documentation for formatter_view says the return value should be a keyed array with numeric keys. Whenever we did that, we had issues. Our virtualfield returns an array with key 'links'. That worked. This is a (improvable) comment about that. And surely someone smarter than use will be able to solve.

- Am not sure how the multi-field views thing would work.

Basically, this, for now, is the best we could do. Its not much, but it can work. We used it to make the contextual menus and the tabs (edit, devel etc) of a node show up in a ctools dropdown button, and to show a progressbar of our editing process as well.

We'll surely add improvements when we find issues in our configuration, but would be glad if others can help improving this patch.

batje’s picture

indeed, the changes to the info file were not included in the patch.

xen’s picture

The latest patch is empty?

And yes, it doesnt win a beauty contest.

Hey, it's a start. You should see some of my first drafts...

- Am not sure how the multi-field views thing would work.

Well, the field handler does it, so it should be possible... But it does require figuring out what's going on here: http://drupalcode.org/project/views.git/blob/423bc82111925528f00838bd200...

- SearchAPI's basetable & related things are very different from the standard node one. As we need to manually load the entity (all at the same time, or one by one) we need to get the information from somewhere else, depending on the type of query the view is based on. Not sure if we would need a 'Virtual SearchAPI' Field and a 'Virtual standard' field. Rather have ugly code than the user realizing what is going on.

Sniffing about SearchAPI code (http://drupalcode.org/project/search_api.git/blob/bfc5f152b1956008940664...) it does seem to add the entity type to the information passed to views, as does Views (http://drupalcode.org/project/views.git/blob/423bc82111925528f00838bd200... for instance), so it would be a much safer bet to get that information from views (how, I don't know off-hand), than relying on parsing the base table (which might not map up to a entity type). That might actually eliminate the need for special SearchAPI handling.

- What was going on was that the documentation for formatter_view says the return value should be a keyed array with numeric keys. Whenever we did that, we had issues. Our virtualfield returns an array with key 'links'. That worked. This is a (improvable) comment about that. And surely someone smarter than use will be able to solve.

Sounds odd. And just looking at the code, there seems to be something wrong, but I don't know what. But you shouldn't be calling the formatter hooks directly, but use field_view_value() which should do most of the heavy lifting for you.

- Am not sure how the multi-field views thing would work.

A pre_render method, I guess. Apparently it gets the full resultset prior to rendering: http://drupalcode.org/project/views.git/blob/423bc82111925528f00838bd200... , it should then load all the entities and cache them in the object for the render method to pick out.

Jan van Diepen’s picture

Issue summary: View changes
StatusFileSize
new6.83 KB

Redid the intended patch with the changes to the .info file included.
Also fixed a php warning:

Deprecated function: Call-time pass-by-reference has been deprecated in _registry_check_code()

Jan van Diepen’s picture

Status: Needs work » Needs review

Changed status from needs work to needs review.

Jan van Diepen’s picture

Created a new patch with the following notices fixed.

Notice: Undefined index: search_api_item_id in virtual_field_handler_field_virtual_field->render() (line 55 of /var/www/dtip3/profiles/devtrac/modules/contrib/virtual_field/includes/views/handlers/virtual_field_handler_field_virtual_field.inc).
Notice: Undefined variable: entities in virtual_field_handler_field_virtual_field->render() (line 87 of /var/www/dtip3/profiles/devtrac/modules/contrib/virtual_field/includes/views/handlers/virtual_field_handler_field_virtual_field.inc).

xen’s picture

  1. +++ b/includes/views/handlers/virtual_field_handler_field_virtual_field.inc
    @@ -0,0 +1,156 @@
    +      $entities = entity_load($entity_type, array($id));
    

    So it's basically fully loading the entities. I can't imagine that views does that for fields in general.

  2. +++ b/includes/views/handlers/virtual_field_handler_field_virtual_field.inc
    @@ -0,0 +1,156 @@
    +    $langcode = LANGUAGE_NONE;
    

    This code shouldn't define a language. I guess field_language() should be used.

  3. +++ b/includes/views/handlers/virtual_field_handler_field_virtual_field.inc
    @@ -0,0 +1,156 @@
    +    $formatter_prepare_view = $formatter.'_prepare_view';
    +    $formatter_view = $formatter.'_view';
    

    This is rather low level. Something like field_view_value() seems a better option.

  4. +++ b/includes/views/handlers/virtual_field_handler_field_virtual_field.inc
    @@ -0,0 +1,156 @@
    +          // check if this virtual field is our virtual field (through the formatter)
    

    Odd comment.

  5. +++ b/includes/views/handlers/virtual_field_handler_field_virtual_field.inc
    @@ -0,0 +1,156 @@
    +    $index_id = substr($this->view->base_table, 17);
    

    Is this really the only way of detecting Search API?

Jan van Diepen’s picture

Made the code a little bit more robust.

Here's a new patch.

xen’s picture

  1. +++ b/includes/views/handlers/virtual_field_handler_field_virtual_field.inc
    @@ -0,0 +1,156 @@
    +    if ($this->_is_searchapi()) {
    +      $index_id = substr($this->view->base_table, 17);
    +      $index = search_api_index_load($index_id);
    +      $entity_type = $index->item_type; // node, user etc.
    +      $id = $this->view->result[$this->view->row_index]->entity;
    +      $entity =  $values->_entity_properties['entity object'];
    +      $entities = array($id => $entity);
    +    }
    +    else {
    +      $entity_type = $this->view->base_table; //node, user etc.
    +      $base_field = $this->view->base_field;
    +      $id = $values->$base_field;
    +      $entities = entity_load($entity_type, array($id));
    +      $entity = $entities[$id];
    +    }
    

    I'm still hoping that there's a better way to find the entities than this, preferably avoiding having to have special handling for search_api. Else we need more defensive coding that checks whether we really get a proper entity type.

  2. +++ b/includes/views/handlers/virtual_field_handler_field_virtual_field.inc
    @@ -0,0 +1,156 @@
    +    /*
    +     *  Get the field instance
    +     */
    +    $instances = array();
    +    $instances[$id] = field_info_instance($entity_type, $fieldname, $entity->type);
    +    $instance = $instances[$id];
    +
    +    $field = 'dummy';
    +    $langcode = LANGUAGE_NONE;
    +    $items = array ();
    +    $displays = array();
    +
    +    // Get the default formatter for this field and bailout if thats not set.
    +    if (!($formatter = $instance['display']['default']['type'])) {
    +      return;
    +    }
    +
    +    $formatter_prepare_view = $formatter.'_prepare_view';
    +    $formatter_view = $formatter.'_view';
    +
    +    $formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, $items, $displays);
    +    // Only pass a single item to the formatter_view hook. Feel free to build a foreach here, we had issues
    +    // with the key that was returned. The documentation says it should be 0, 1, 2 etc but we had to put in
    +    // a certain string.
    +    $element = $formatter_view($entity_type, $entity, $field, $instance, $langcode, $items[$id], $displays);
    +
    +    // So here we just use any key that has been returned.
    +    $keys = array_keys($element);
    +    $key = $keys[0];
    +    return $element[$key]['#markup'];
    

    I've still not gotten a good explanation why we need all this, rather than a simple field_view_field() or field_view_value().

  3. +++ b/includes/views/virtual_field.views.inc
    @@ -0,0 +1,22 @@
    +  $data['virtual_field']['table']['join'] = array(
    +      '#global' => array(),
    +  );
    +
    

    This is still lazy. We should be able to figure out which virtual fields exists and only add existing fields to the relevant base tables. Views build-in field support does it, so should we.

Joanna_Kisaakye’s picture

I noticed that the patch from #11 was not compatible with field_collection_item entities that use the field name as the name of the bundle, therefore I updated the patch in #11 to that effect.

Status: Needs review » Needs work

The last submitted patch, 13: virtual_field_views_support_1506376_13.patch, failed testing.

Joanna_Kisaakye’s picture

I fixed the typo in my last patch

Joanna_Kisaakye’s picture

Status: Needs work » Needs review

The last submitted patch, 7: virtual_field_views_support_1506376_7.patch, failed testing.

The last submitted patch, 9: virtual_field_views_support_1506376_9.patch, failed testing.

The last submitted patch, 11: virtual_field_views_support_1506376_11.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 15: virtual_field_views_support_1506376_15.patch, failed testing.

batje’s picture

Joanna, if you review the test, you can see that the patch does not apply correctly.

Did you base the patch on the raw 7.x-1.0 dev branch or on the 7.x-1.2 stable version?

xen’s picture

I would prefer if someone would address my reservations above rather than rerolling.

Joanna_Kisaakye’s picture

Batje, I based my patch on the current 7.x-1.x branch