I think it would make much sense to add some generic-entity based Views handlers to the entity API, such as
1) a row style for entity_view(), also see #1064518: Support entity-based Views handlers
2) field handlers for outputting entity properties according to hook_entity_property_info()

For that the handlers need a way to determine the entity_type / entity to use though.

Comments

fago’s picture

drunken monkey’s picture

Would be a great addition, subscribing.
Code from the linked Search API issue and from efq_views could be a base for 1).
Maybe a style plugin (instead of a row style) would be better, though, because it would require only a single call to entity_view().

fago’s picture

Yep, also 2) is something that efq_views has already done I think + search api does on its own too.

fago’s picture

>For that the handlers need a way to determine the entity_type / entity to use though.

So what about adding an optional 'entity type' key to views base tables, such that modules may specify the relation there? So we could read it from there + just pass pass the entity id as field value. For cross-entity use cases we'd could support reading it from $this->alias['entity type'] if the base table hasn't specified the type.

fago’s picture

Status: Active » Needs review
StatusFileSize
new5.51 KB

ok, here is a try of a generic entity-view row-style. It works for all base tables which specify the 'entity type', whereas backends like efq_views / search_api would have to specify 'skip entity load' => TRUE too to skip a second entity load (which would be cached but anyway).

thoughts?

drunken monkey’s picture

Looks great! And, after shortly testing it, I can say that it also works great.
I wanted to do the same once, store additional information in the base table definition, but didn't come up with a way to do it. Good to see it does work, if you know how.
OK, if you are already committing this soon, I can probably just abandon my own solution (#1064518: Support entity-based Views handlers) and wait for yours. Since there isn't even a dependency (I only have to change one internal array key and add two yet meaningless keys to views data definitions), I can even support this before you commit it. ;)

One thing, though: What about calling entity_views() on all entities at once, like you mentioned in the Search API issue? Not practicable? Or not possible, due to inconsistent returned render arrays?

And you're right, of course, 2) is also already implemented at least in the Search API.

fago’s picture

Status: Needs review » Needs work

>...I can even support this before you commit it. ;)
Awesome!

>One thing, though: What about calling entity_views() on all entities at once, like you mentioned in the Search API issue? Not practicable? Or not possible, due to inconsistent returned render arrays?

Ops, forgot about that. We should do it that way.

+  public function pre_render($results) {
+    $this->entities = array();
+    foreach ($results as $result) {
+      if (is_object($result)) {
+        $this->entities[entity_id($this->entity_type, $result)] = $result;
+      }
+      elseif (is_array($result) && isset($result['entity'])) {
+        $id = is_object($result['entity']) ? entity_id($this->entity_type, $result['entity']) : $result['entity'];
+        $this->entities[$id] = $result['entity'];
+      }
+    }
+    if (!$this->skip_load) {
+      $this->entities = entity_load($this->entity_type, array_keys($this->entities));
+    }
+  }

While this "guessing" works probably for most cases, it's a bit weird and not extensible. Maybe we should off-load that to the query class instead?

drunken monkey’s picture

While this "guessing" works probably for most cases, it's a bit weird and not extensible. Maybe we should off-load that to the query class instead?

I think, most query classes will be able to take this into account and use one of the available methods (of course they should be documented). What we could additionally do here is to provide an optional way to circumvent this behaviour, e.g. with:

public function pre_render($results) {
  if (method_exists($this->view->query, 'getResultEntities')) {
    $this->entities = $this->view->query->getResultEntities($results);
    return; // Or: if (is_array($this->entities)) return;
  }
  // Rest as above
}
fago’s picture

re-rolled #5 with -p0 for drush make

fago’s picture

StatusFileSize
new5.16 KB

re-rolled #5 with -p0 for drush make

Shadlington’s picture

Subscribing

bojanz’s picture

Don't have time to look into this right now (still no internet in Paris apartment), but I'm pleased to announce that #975400: Refactor field render() functions to accept $value, allowing reuse has landed :)

EDIT:
Tested the patch with efq_views, works nicely.
However, that file needs to go into plugins/ not into handlers/.
Also, not sure why you're using non standard class naming, since views is still using the underscore way of naming classes (views_plugin_row), following that pattern might be a good idea.

Preparing a patch that adds handlers and some other nice things, stay tuned.

remidewitte’s picture

subscribe

fago’s picture

>However, that file needs to go into plugins/ not into handlers/.
Indeed.

>Also, not sure why you're using non standard class naming, since views is still using the underscore way of naming classes (views_plugin_row), following that pattern might be a good idea.

I just took that over from the search api. While I think this needs to be fixed in views, we should probably follow its pattern for the integration code.

bojanz, would do you think about the idea proposed in #8? Maybe, we could improve Views itself to follow the same pattern for retrieving entities?

bojanz’s picture

> I just took that over from the search api. While I think this needs to be fixed in views, we should probably follow its pattern for the integration code.
Agreed. When Views fixes it, the pattern can change everywhere.

> bojanz, would do you think about the idea proposed in #8? Maybe, we could improve Views itself to follow the same pattern for retrieving entities?
Interesting idea, definitely something to think about.
I'm developing a commerce contrib module today and eating my dogfood (Entity API + my patches for Views integration and smarter UI generation), so once I see how it all works in practice (today), I'll update the issue with the code and results..

Shadlington’s picture

Did you get anywhere with this bojanz?

I applied the patch in #10 and whilst it made 'Entity View' available as an option, selecting it and clicking apply doesn't actually change the value. Its stuck on Fields.

Possibly a casualty of the new Views UI?

drunken monkey’s picture

After thinking about it a bit more, it wouldn't harm to use something like ":entity" instead of "entity" as the key in $values. There isn't really any downside, and even if it's rather unlikely that a table has a column "entity", it could mess things up a bit if it does happen.

bojanz’s picture

Sorry, completely forgot about it (last week was though). I'll post my progress today.

reptilex’s picture

Would this allow to include a profile2 field into a node view?

I really would need that. It seems to me that it is just one step up from including a user field, isn't it?

bojanz’s picture

StatusFileSize
new25.37 KB

I'm very tired so I'm gonna leave further explanations for tomorrow.
This applies both to current Entity code, and the current Entity code with the first patch of this issue applied.

I added support for displaying properties (which do not map to sql columns). Each property handler is the same, modeled after views_handler_field_field.
I also added support for overriding generated Views data, by providing data in the property info (so you can substitute your own handler, or make it not have a filter/field/argument/sort handler at all).
EDIT: I see that I added the docs to the entity info by mistake. That can be changed in a later reroll.

cnsmiles’s picture

Status: Needs work » Needs review

I created a view type of profile and did not see any of my profile fields values under filter which happen to be term referenced. All I see is reference to tid and delta. I also tested this with the user view type. I can pull them as fields but not under filter. I'm doing a profile2 based view. I know this works under the content views. Will what you providing address this?

bojanz’s picture

No, what you're describing is totally unrelated to this issue and patch.

joachim’s picture

@bojanz: would adding fieldAPI fields to views for entities then be a follow-up issue to this one?

bojanz’s picture

There's nothing stoping you from adding fields to your custom entity, it should work out of the box.
If it doesn't, then yeah, it will be a followup here somewhere :)

joachim’s picture

> it should work out of the box.

Nope, it doesn't -- fields added to Profile2 entities don't show as fields to be added in a view :/

bojanz’s picture

Definitely a bug I'll be looking into then.
(Edit: I'm using the Entity API views integration with my patch, and it shows fields attached to my custom entity. Can you try if it works for you with my patch?)

Shadlington’s picture

Uhhhhh... The fields attached to my profile2 entities are showing in views.
No patch involved. Just the latest versions of entity, views and profile2.

Shadlington’s picture

Hmmmm. Actually, this is a bit odd.
If I add an existing field to a profile type, it shows up in views under the 'Fields' filter.
If I add a new field to a profile type, it shows up in views under the 'Profile' filter.

I can't imagine this is intentional. Anyway, that is probably a bug in Profile2 rather than Entity API.

bojanz’s picture

I think that's normal, Views uses an appropriate group name (entity type) if the field is only attached to one. If it's attached to several, it falls back to "Fields".

Shadlington’s picture

Oh, I see. Well, it works is the main thing.

EDIT: The patch in #20 doesn't apply cleanly (against either beta8 or the latest dev)

patching file entity.api.php
patching file entity.info
Hunk #1 FAILED at 2.
1 out of 1 hunk FAILED -- saving rejects to file entity.info.rej
patching file entity.module
patching file views/entity.views.inc
Hunk #2 succeeded at 52 (offset -26 lines).
Hunk #3 FAILED at 96.
Hunk #4 succeeded at 139 (offset -26 lines).
1 out of 4 hunks FAILED -- saving rejects to file views/entity.views.inc.rej
patching file views/handlers/entity_handler_field_property_boolean.inc
patching file views/handlers/entity_handler_field_property_date.inc
patching file views/handlers/entity_handler_field_property_numeric.inc
patching file views/handlers/entity_handler_field_property_string.inc
patching file views/handlers/entity_handler_field_property_uri.inc

bojanz’s picture

StatusFileSize
new26 KB

Try the git checkout.
The info file has additional info in downloaded releases, which is why the patch doesn't apply there.
Rerolled for the entity.views.inc part, but I am not sure I solved the conflicts correctly, I'm a bit sick at the moment. So read it with caution ;)

Shadlington’s picture

Got the git checkout and applied that patch:

patching file entity.api.php
patching file entity.info
Hunk #1 FAILED at 2.
1 out of 1 hunk FAILED -- saving rejects to file entity.info.rej
patching file entity.module
patching file views/entity.views.inc
Hunk #2 succeeded at 52 (offset -26 lines).
Hunk #3 succeeded at 69 with fuzz 2 (offset -27 lines).
Hunk #4 succeeded at 122 (offset -27 lines).
patching file views/handlers/entity_handler_field_property_boolean.inc
patching file views/handlers/entity_handler_field_property_date.inc
patching file views/handlers/entity_handler_field_property_numeric.inc
patching file views/handlers/entity_handler_field_property_string.inc
patching file views/handlers/entity_handler_field_property_uri.inc

Sorry, doesn't seem to have worked :(

It looks like the patch is expecting a line like this: 'files[] = views/plugins/entity.row_view.inc' to already be in my .info, but it isn't.
Anyway I'll sort out the .info manually.
Will report on findings shortly.

Hope you feel better soon :)

Shadlington’s picture

What exactly should I do to test this?

I'm not clear what has changed from a user's point of view.

bojanz’s picture

This is a "frameworkish" patch, so what it needs is a developer's not a user's point of view.

Shadlington’s picture

Oopf. Sorry. I thought I saw a UI change after I applied one of the patches earlier in the issue.
I'll be quiet now :)

drunken monkey’s picture

The Search API already supports part one of this feature (the row display plugin). So that can already be tested.

Shadlington’s picture

Ah, well in that case it didn't appear to work. Unless I need to be applying the patch I applied previously (#10) as well. When I applied that I did seem to get a new row display plugin called 'Entity View' but it wasn't working (see my post #16).

drunken monkey’s picture

Yes, sorry, phrased that ambiguously. The patch in #10 is what I meant with "part one".
And as for it not working: fago is on vacation until April 26, so don't expect any fixes until then. Except Bojan (or I, or someone else) would fill in.

daften’s picture

subscribe

Shadlington’s picture

Ah. I just had another try and I got it to work.
I didn't realise that this patch was in two parts.

#10 followed by #31 (with the .info bit applied manually - still having problems with that) allows me to select 'Entity View' as a row style.
And a very brief initial test shows it works!

EDIT: After much further testing I haven't come across a single problem. I love it :D

amitaibu’s picture

I've started moving OG's views integration to use entity metadata. Subscribe for now.

joachim’s picture

Has patch been committed yet? I just cloned the latest EntityAPI and I get relationships both ways and fields on profiles.

Only missing piece for Profile2, I think, is #1114454: Views integration: create an entity-entity relationship that limits by entity type if applicable.

amitaibu’s picture

> I just cloned the latest EntityAPI and I get relationships both ways and fields on profiles.

If profile2 doesn't declare hook_views_data() entity is doing it for you.

bojanz’s picture

Entity has Views integration even without this patch(es).
My patch provides property handlers (used in efq_views, search api and other places) and support for displayng properties that don't map to schema fields (database columns).
It also provides a way to override the handler from hook_property_info() (so you can specify "my_handler_field_numeric" instead of the default one, for example).

The other patch provides a style plugin that uses entity_view (similar to the node row plugin for nodes)

404’s picture

subscribe

fangel’s picture

After applying these patches I have a problem exporting views (both using features and views directly). The error I get is
Fatal error: Call to a member function get_option() on a non-object in ../sites/NN/modules/views/plugins/views_plugin_style.inc on line 35

(I only use the entity row-style, so I'm assuming it's related to that)

drunken monkey’s picture

I get this error, too, but I'm not sure it's related to this patch. Both before and after reverting the patch, I get this for some views when editing argument handler options. Just checked, and yes, for those views I also get a fatal error when exporting.
It seems, that views_plugin_style::init(&$view, &$display, $options = NULL) will sometimes be called with the second and third parameter both NULL, which causes the error.
Did you use an argument handler in the view in question? Can you please check whether reverting the patch and/or removing the argument handler (if applicable) resolves this?
If it really is a Views bug and we both get it, we should probably create an issue in the Views queue.

fangel’s picture

I am indeed using a argument (search_api_index_fulltext_search). I will check with and without the patch and the argument tomorrow when I get back to work, and report my findings.

fangel’s picture

Okay then. The results are in :)

  With patch applied Without patch
With SearchAPI fulltext argument Error Error
Without SearchAPI fulltext argument OK OK

So it's clear that the bug isn't in these set of patches, as they do not affect the bug. However, the SearchAPI fulltext argument is to blame.
@drunkenmonkey, do you want to take it from here or should I start a separate issue on the SearchAPI tracker?

-Morten

drunken monkey’s picture

Please start a new issue in the Search API queue.
I am, however, not sure whether the fault here lies with the Search API or with Views, or in between. Please mention in the Search API issue also whether you have the same problem with all arguments or just with the one. (The three different cases are normal fields, fulltext fields and "Search: Fulltext search".)

amitaibu’s picture

@bojanz,
I couldn't apply patch with "git apply", it needs a re-roll?

bojanz’s picture

Tried "patch -p1" ?
I'll take a look tomorrow and reroll if needed.

amitaibu’s picture

> Tried "patch -p1" ?

Yes, didn't work for me

Shadlington’s picture

If I wanted to add in some custom code to selectively pick a view mode for each row based on specific criteria (for example, whether a 'featured' check box was ticked or not for a given node) then where would the best place to do this be?

I can quickly achieve this by sticking some code into EntityViewsRowView's render function but I'd rather do this in a less hackish way.
Any advice would be much appreciated.

drunken monkey’s picture

You should then probably subclass the EntityViewsRowView class and add code (and maybe even an options form) for this.
The row style could then be added in hook_views_plugins() with the same code that this module uses.

girishmuraly’s picture

StatusFileSize
new25.95 KB

@bojanz @Shadlington based on #40, I am able to get entity based build modes (I am using this with search_api). So I have attempted to combine patches #10 and #31 (since #31 had problems applying). Hope this works.

bojanz’s picture

StatusFileSize
new5.04 KB

Here's a rerolled entity row patch. Should be ready for commit.

becw’s picture

StatusFileSize
new5.29 KB

A couple comments:

  1. The Views plugin should have 'plugin' in the name; it's a "row plugin", not a "row view".
  2. In the plugin's pre_render() method, this checks whether view results are arrays or objects. Views core assumes that results are objects, so I think this code should work from that assumption as well. This looks like it is written to accommodate Search API Views' query plugin behavior--it returns Views results as arrays--which is being addressed in #1089758: Make use of new flexibility for Views field handlers.
  3. The plugin's options form is empty when there are zero or one view modes available. It should show that the default view mode is is being used.
  4. The view mode should default to 'default' if no view modes are available. The 'full' view mode is a convention, but is not guaranteed to be present; 'default' provided internally, and is always available.

Attached is a version of this patch with these changes.

fago’s picture

Finally, I've created #1172970: provide a unified way to retrieve result entities. Please add your comments there.

@patch:

In the plugin's pre_render() method, this checks whether view results are arrays or objects. Views core assumes that results are objects, so I think this code should work from that assumption as well. This looks like it is written to accommodate Search API Views' query plugin behavior--it returns Views results as arrays--which is being addressed in #1089758: Make use of new flexibility for Views field handlers.

I'm not sure about that, isn't it up to the query backend how the results look? Stuff that comes with views is basically meant to work for the default-backend, so it doesn't have to bother with, yes. But I don't think that means everyone has to follow that.

Else, the patch looks good to me. I guess we should go and add this now, so people can start using it + update it based on the solution of #1172970: provide a unified way to retrieve result entities?

JoeMcGuire’s picture

I was looking at this issue for an issue on the Search API Views module #1109318: Views: Add option to display image fields as image

I am thinking it would be really helpful to have another row style "Entity API Fields" which was able to extend the work Views is doing to add Field API fields extending the existing handlers so we can use their option forms and render methods. But instead get values from an existing entity object instead of the database.

bojanz’s picture

I'm in the process of moving from France to Serbia so I'm pretty useless at the moment.

But instead get values from an existing entity object instead of the database.

Views already works like that, Field API values are fetched from the entity (entity_load), not the db result set. Nothing else is needed.

drunken monkey’s picture

I'm not sure about that, isn't it up to the query backend how the results look? Stuff that comes with views is basically meant to work for the default-backend, so it doesn't have to bother with, yes. But I don't think that means everyone has to follow that.

You're probably right. It makes sense to follow Views there, but it needn't be mandatory if there's an easy way to accommodate both variants.

Else, the patch looks good to me. I guess we should go and add this now, so people can start using it + update it based on the solution of #1172970: provide a unified way to retrieve result entities?

Yes, that would probably be the best way. Can't tell how long the Views issue will take …

fago’s picture

Status: Needs review » Needs work

>I am thinking it would be really helpful to have another row style "Entity API Fields" which was able to extend the work Views is doing to add Field API fields extending the existing handlers so we can use their option forms and render methods. But instead get values from an existing entity object instead of the database.

I think Views is already using the data from an entity-load for fields, so ideally it could be re-used for display only stuff with other back-ends too once #1172970: provide a unified way to retrieve result entities gets fixed. It uses the db for stuff like click-sorting and grouping though, so for the search-api case it would make sense to exchange that parts and to use the search-index for that if the field is in there.

>You're probably right. It makes sense to follow Views there, but it needn't be mandatory if there's an easy way to accommodate both variants.

Ok, let's do so then and support search-api arrays too. That way, our solution also works *now* with search api.

zambrey’s picture

subscribe

sonar_un’s picture

Subscribing

bojanz’s picture

Okay, I'm back.

I think we should rename the row class from EntityViewsPluginRow to entity_views_plugin_row (or better yet, entity_plugin_row).
That follows the views naming convention as well as the names of the handlers in the #31 patch.

Regarding the #31 patch, any comments on that?
It aimed to do three things:
1) Provide a way to override a handler through entity metadata. Looking back at it, it can be removed. Anyone can use hook_views_data_alter(), no point in doing this.
2) Provide generic entity handlers.
3) Use them for displaying fields that don't map to db columns.

fago’s picture

Title: add entity-based Views handlers » add an entity-view row plugin

>I think we should rename the row class from EntityViewsPluginRow to entity_views_plugin_row (or better yet, entity_plugin_row). That follows the views naming convention as well as the names of the handlers in the #31 patch.

Yes, let's follow views here - it's views integration.

@patch in #31:
That sounds great, but let's care about that in a follow up and finish the view plugin row first, as this is mostly ready. Then I think we should move on with #1172970: provide a unified way to retrieve result entities, as this would help us greatly with #31 too.

bojanz’s picture

Status: Needs work » Needs review
StatusFileSize
new5.35 KB

This one follows the views naming (views_row_plugin_node_view => entity_row_plugin_entity_view).

drunken monkey’s picture

Status: Needs review » Needs work

Yes, let's follow views here - it's views integration.

It's also Drupal, so why not follow the Drupal coding standards? I still don't understand why Views insists on having a whole other set of coding standards, in places even diametrical to Drupal's.

But that's just my usual ranting, sorry. If you think it makes sense this way, let's do so.

However, the patch doesn't take into account fago's comment from #63:

>You're probably right. It makes sense to follow Views there, but it needn't be mandatory if there's an easy way to accommodate both variants.
Ok, let's do so then and support search-api arrays too. That way, our solution also works *now* with search api.

While Search API now also uses objects, it still might make sense to not make this mandatory.

fago’s picture

Status: Needs work » Needs review
StatusFileSize
new6 KB

ok, I re-rolled the patch to include support for the array variant too. Updated patch attached.

However, it didn't work with the latest search api any more. It seams like the search api says 'skip load' but then passed only an entity id? :/

becw’s picture

Search API Views' has changed slightly, per #1089758: Make use of new flexibility for Views field handlers. Search API Views' query backend now returns view results as objects instead of arrays (following the example set by the default Views query backend), and will only load the full entity if the view is requesting fields that are present on the entity but not on the Search API result. This means that for some views, an entity_load() will be run for each result, and for others it will not run entity_load() at all (this could possibly even vary per result)--it depends on the view's field configuration.

That said, I haven't reviewed this version of the patch.

drunken monkey’s picture

However, it didn't work with the latest search api any more. It seams like the search api says 'skip load' but then passed only an entity id? :/

Sorry, my understanding was that this would now only come along with a method for retreiving the results. Now, as Bec explained, the entity key on the results are a bit unpredictable.

If you want, though, I could modify the patch here so it checks for whether a result contains an entity or just an ID, and then load accordingly, if necessary. (Or anyone else could do that, it's of course a very simple change – the question is whether you want such "magic" there?)

fago’s picture

StatusFileSize
new6.15 KB

thanks, I've just added another fallback checking for ids even if skip-load is defined. Seems to work.

Updated patch attached. Another question, should we check for view access of the current user or just display it? I think views doesn't check access for node-view, but it does for fields. So I'm not sure what's the approach to follow here?

let's clean this mess up asap in #1172970: provide a unified way to retrieve result entities

fago’s picture

Status: Needs review » Fixed
StatusFileSize
new5.67 KB

ok, talked to dereine on IRC regarding the access-issue. He recommends to leave it out or at least add it as option, so I leave it out for now. And finally I understand how views deals with access checks. :)

also dereine helped to clear the array/object issue, see this commit. Thus, I re-worked the patch again to remove the array checks and committed it. That means, folks need to use the latest search-api for this to work with it.

Attached is the finally committed version.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

Anonymous’s picture

Status: Closed (fixed) » Needs work

Hi,

I have a custom entity type and setting up a View for a Search API index of that entity type. I need to style the views-view.tpl.php. When I click on the 'theme: information' I get this error:

ResponseText: Notice: Undefined index: theme in theme_functions() (line 498 of C:\Inetpub\wwwroot\123.dev\sites\all\modules\contrib\views\includes\plugins.inc). =>

It seems that the patch #74 needs one more line in entity_views_plugins() in entity.views.inc
To solve the above error, I needed to add the "theme":

(...)
          'type' => 'normal',
          'base' => $base_tables,
          'theme' => 'views_view_entity', // required new line

But this doesn't work right, I don't know how to do this right. Somehow it needs to point to a .tpl.php file for views.

Anonymous’s picture

I ended up with the following function:

function entity_views_plugins() {
  $path = drupal_get_path('module', 'entity'); // new line
  foreach (views_fetch_data() as $table => $data) {
    if (!empty($data['table']['base']['entity type'])) {
      $base_tables[] = $table;
    }
  }
  if (!empty($base_tables)) {
    return array(
      'row' => array(
        'entity' => array(
          'title' => t('Entity'),
          'help' => t('Displays a single entity in a specific view mode (e.g. teaser).'),
          'handler' => 'entity_plugin_row_entity_view',
          'uses fields' => FALSE,
          'uses options' => TRUE,
          'type' => 'normal',
          'base' => $base_tables,
          'theme' => 'entity_view_entity', // new line
          'theme file' => 'entity.views.inc', // new line
          'theme path' => "$path/views", // new line
        ),
      ),
    );
  }
}

And copied entity.tpl.php to /views/entity-view-entity.tpl.php

It escapes me what is going on here -- this needs more work.

drunken monkey’s picture

FYI: Follow-up for the field handlers (or at least related stuff): #1266036: Add generic Views entity tables with fields and relationships.

fago’s picture

Status: Needs work » Closed (fixed)

please open separate issues for any troubles with the committed plugin.