Problem/Motivation

Views integration works for config fields created in the UI, but not for base fields added to the entity types in code.

As an example, consider Date module. That diligently implements datetime_range_field_views_data() to declare its custom Views filters and arguments. But if I add a date field to my entity's base fields, the Views integration is completely missing.

Proposed resolution

Add the views handler to the field annotation as with the entity annotation. Provide the default base class for standard views data. Allow custom fields to have specific classes for views data.

Remaining tasks

Write a patch for the above proposed resolution.

User interface changes

None

API changes

API completion

Data model changes

None

Release notes snippet

TBC

CommentFileSizeAuthor
#93 drupal-Allow_FieldType_to_customize_views-2337515-93-9.2.x.patch39.68 KBgolddragon007
#88 2337515-88.drupal.Allow-FieldType-to-customize-views.patch42.81 KBjaperry
#84 2337515-84.drupal.Allow-FieldType-to-customize-views-data.patch40.22 KBgreggles
#82 2337515-82.drupal.Allow-FieldType-to-customize-views-data.patch40.14 KBjoachim
#71 2337515-71.patch39.95 KBclaudiu.cristea
#65 allow_fieldtype_to-2337515-65.patch39.83 KBborisson_
#65 interdiff.txt1.36 KBborisson_
#63 interdiff.txt1.61 KBborisson_
#63 allow_fieldtype_to-2337515-63.patch40.63 KBborisson_
#60 allow_fieldtype_to-2337515-60.patch40.34 KBborisson_
#60 interdiff.txt3.09 KBborisson_
#59 allow_fieldtype_to-2337515-59.patch38.14 KBborisson_
#59 interdiff.txt729 bytesborisson_
#55 allow_fieldtype_to-2337515-55.patch39.07 KBborisson_
#55 interdiff.txt2.95 KBborisson_
#53 allow_fieldtype_to-2337515-52.patch38.35 KBborisson_
#53 interdiff.txt2.31 KBborisson_
#50 allow_fieldtype_to-2337515-50.patch37.94 KBborisson_
#50 interdiff.txt2.68 KBborisson_
#47 allow_fieldtype_to-2337515-47.patch37.27 KBborisson_
#47 interdiff.txt2.18 KBborisson_
#46 allow_fieldtype_to-2337515-46.patch37.98 KBborisson_
#46 interdiff.txt2.2 KBborisson_
#45 allow_fieldtype_to-2337515-45.patch35.77 KBborisson_
#45 interdiff.txt5.41 KBborisson_
#40 interdiff-2337515-32-40.txt15.29 KBstborchert
#40 drupal-allow_FieldType_to_customize_views_data-2337515-40.patch34.68 KBstborchert
#39 drupal-allow_FieldType_to_customize_views_data-2337515-39.patch33.03 KBstborchert
#39 interdiff-2337515-32-39.txt15.15 KBstborchert
#32 interdiff.txt12.68 KBdawehner
#32 2337515-32.patch17.81 KBdawehner
#29 2337515-29.patch7.81 KBdawehner
#18 2337515-18.patch9.94 KBJaesin
#12 views-entity-field-data-alter-2337515-12.patch1.77 KBjhedstrom
#6 views-entity-field-data-alter-2337515-06.patch4.65 KBjhedstrom
#6 interdiff.txt4.48 KBjhedstrom
#3 2337515.patch1.97 KBdamiankloip

Issue fork drupal-2337515

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

damiankloip’s picture

Nice issue Daniel!

dawehner’s picture

@damiankloip
Yeah love it :)

damiankloip’s picture

StatusFileSize
new1.97 KB

Something like this could be useful.

dawehner’s picture

  1. +++ b/core/modules/views/src/EntityViewsData.php
    @@ -396,6 +396,16 @@ protected function mapSingleFieldViewsData($table, $field_name, $field_type, $co
    +    $this->moduleHandler->alter('views_entity_field_data', $views_field, $context);
    +    $this->moduleHandler->alter('views_entity_field_data_' . $field_type, $views_field, $context);
    

    I would have expected the more generic alter to come after the field type specific one ... any reason why you have chosen that order?

  2. +++ b/core/modules/views/views.api.php
    @@ -593,6 +593,30 @@ function hook_field_views_data_views_data_alter(array &$data, \Drupal\field\Fiel
    +function hook_views_entity_field_data_alter(&$field_data, $context) {
    ...
    +function hook_views_entity_field_data_boolean_alter(&$field_data, $context) {
    

    Should we quickly explain what is in $context ?

tim.plunkett’s picture

jhedstrom’s picture

Status: Active » Needs review
StatusFileSize
new4.48 KB
new4.65 KB

This adds tests, and takes into account the feedback from #4.

Jaesin’s picture

+++ b/core/modules/views/src/EntityViewsData.php
@@ -437,6 +437,16 @@ protected function mapSingleFieldViewsData($table, $field_name, $field_type, $co
+    $this->moduleHandler->alter('views_entity_field_data_' . $field_type, $views_field, $context);
+    $this->moduleHandler->alter('views_entity_field_data', $views_field, $context);

Why not allow fields to supply their default handlers in the field definition instead of making an assumption in the first place?

Something like:

<?php
      $defaults = $field_definitions[$field_name]->getViewsDefaults($table, $field_column_name);
      $table_data[$views_field_name] = $defaults ?: $this->mapSingleFieldViewsData($table, $field_name, $field_definition_type, $field_column_name, $field_schema['columns'][$field_column_name]['type'], $first, $field_definition);
?>

Of course you would have to add getViewsDefaults to FieldStorageDefinitionInterface and BaseFieldDefinition.

dawehner’s picture

Why not allow fields to supply their default handlers in the field definition instead of making an assumption in the first place?

Well that is a good question. Should entries in lib/Drupal/Core/Field care about views? I don't know to be honest.

Jaesin’s picture

Well that is a good question. Should entries in lib/Drupal/Core/Field care about views? I don't know to be honest.

I think so but added to FieldDefinitionInterface instead FieldStorageDefinitionInterface. Storage is only part of a field definition. Retrieval is the other part.

When I created a custom field, I looked for a viewsHandlers() callback and was surprised that I had to use HOOK_field_views_data.

tstoeckler’s picture

Well we could add a generic ViewsDataProviderInterface in Views module and then in EntityViewsData we could check if the field item class implements that. Then at least for core (#2489476: [PP-1] Base fields miss out on Views data from hook_field_views_data()) and contributed (!) modules it would be quite simple and straightforward to provide their views data and would be a completely soft dependency. For the field types provided by Drupal\Core we might not want to introduce the knowledge about Views module, so EntityViewsData would have to care for those itself, just like it does now.

Thoughts?

dawehner’s picture

I like that!

jhedstrom’s picture

Issue tags: +Needs tests
StatusFileSize
new1.77 KB

Something like this? We'll need tests.

dawehner’s picture

+++ b/core/modules/views/src/ViewsDataProviderInterface.php
@@ -0,0 +1,25 @@
+   * @param array &$views_field
+   *   The views field data.
...
+   */
+  public function alterViewsFieldData(array &$views_field);

It would be great to check whether theoretically all needs of \entity_reference_field_views_data are covered.

Jaesin’s picture

  1. +++ b/core/modules/views/src/ViewsDataProviderInterface.php
    @@ -0,0 +1,25 @@
    +  public function alterViewsFieldData(array &$views_field);
    

    We already have field_views_data_alter so I think the point is to have the field plugin be able to supply the views data directly with something like $field_definition->getItemDefinition()->viewsSchema()

  2. +++ b/core/modules/views/src/EntityViewsData.php
    @@ -430,6 +428,11 @@ protected function mapSingleFieldViewsData($table, $field_name, $field_type, $co
    +    // Let fields provide data.
    ...
    +      $field_definition->alterViewsFieldData($views_field);
    +    }
    +
    

    The $field_definition doesn't get you the field plugin. None of the fields I've seen so far override the BaseFieldDefinition It might be better to allow the item definition implement the ViewsDataProviderInterface.

      if ($field_definition->getItemDefinition() instanceof ViewsDataProviderInterface) {
        $views_field = $field_definition->getItemDefinition()->viewsSchema($field_definition, $arg1);
      } else {
        switch ($field_type) {
    ...
        }
    }
    
jibran’s picture

Added related issues and it's at least a major issue. I think we can also delete all these methods (maybe in followup)

processViewsDataForLanguage
processViewsDataForEntityReference
processViewsDataForTextLong
processViewsDataForUuid

from EntityViewsData and move them to corresponding fields. Moreover EntityViewsData::processViewsDataForEntityReference() handles only forward relationships and doesn't provide reverse relationships and we have a lot of ugly code for these in EntityViewsData sub classes like UserViewsData::getViewsData() adds

    $data['users_field_data']['uid']['relationship'] = array(
      'title' => t('Content authored'),
      'help' => t('Relate content to the user who created it. This relationship will create one record for each content item created by the user.'),
      'id' => 'standard',
      'base' => 'node_field_data',
      'base field' => 'uid',
      'field' => 'uid',
      'label' => t('nodes'),
    );

We can also handle this in follow up.

Can we handle forward and backward relationships if we implement #10? Does this work for both base fields and storage fields?

I think we can improve current approach. Just like for entity classes we add views_data class * "views_data" = "Drupal\user\UserViewsData",. We can add views_data key to FieldType plugins. Core can provide FieldViewsData and fields can subclass it just like UserViewsData does that for user. This will help also make EntityViewsData skinny. This mean move EntityViewsData::mapSingleFieldViewsData() to FieldViewsData. Thoughts?

Jaesin’s picture

@JIbran, I do like where you are going with this and as long as "views_data" isn't required for field type definitions, we might be able to get away with it. This would bring field definitions a little close to what entity definitions look like.

Jaesin’s picture

Status: Needs review » Needs work
Jaesin’s picture

StatusFileSize
new9.94 KB

This is just a start but it adds handlers to field types (which could be useful for contrib).

The concept here is you could use $field_type->getHandler('views_data')->getViewsData().

<?php
/**
 * Plugin implementation of the 'text' field type.
 *
 * @FieldType(
 *   id = "text",
 *   label = @Translation("Text (formatted)"),
 *   description = @Translation("This field stores a text with a text format."),
 *   category = @Translation("Text"),
 *   default_widget = "text_textfield",
 *   default_formatter = "text_default"
 *   handlers = {
 *     "views_data" = "\Drupal\text\Plugin\Field\FieldType\TextViewsData"
 *   },
 * )
 */
?>
dawehner’s picture

IMHO its a mess that entity handlers aren't plugins, you know why, because now with field handlers we deal with the same plugins, should there be handlers,
or should be simply introduce another plugin thingy like we have for formatters and widgets ... No idea at all to be honest.

Jaesin’s picture

Like @dawehner was saying another approach would be to add a `@FieldHandler` or a `@Handler` plugin type. So you might have something like \Drupal\text\Plugin\Field\Handler\TextViewsFieldHandler That has the all of the callbacks and specifies which fields it applies to.

What do others think about this approach?

If handlers are generic, they will have to have a handler_type and/or context definition (which could dictate which interface they use). I think we have to have a default ViewsFieldHandler which brings up the issue, if handlers are generic how do they deal with defaults if a handler is not created for a field type. Maybe the handler consumer (views in this case) deals with this.

Also, this approach seems like would have a bit more overhead as it has to have another plugin manager for handlers.

The up side to this approach is that could be very useful in contrib to have a generic handler which you can specify context for in the handler definition.

@jibran @jhedstrom @damiankloip What do you guys think?

jibran’s picture

Title: EntityViewsData: "// @todo Allow field types to customize this." » Allow @FieldType to customize views data
Issue tags: +Entity Field API, +Field API

I understand @dawehner's concern but let's not reinvent the wheel here. This is a major bug and we can't create new plugin system and get away with that at this point in time in release window. I suggested the handler apporoch because we already have that in core.

bojanz’s picture

I agree with jibran. We're staring RC in the face.

dawehner’s picture

This is a major bug and we can't create new plugin system and get away with that at this point in time in release window.

I think this general statement is wrong, IMHO.

@damiankloip, @plach, @dawehner talked about this particular issue. Given that both entity selection thingies are plugins, but also as you see in the annotation above formatters, and widgets are plugins, so introducing handlers as an additional concept is more confusing and disruptive as adding a plugin type. Let's discuss more, but yeah we don't see an advantage of using the handlers approach to be honest, but for sure let's keep talking about it.

Jaesin’s picture

It's debatable which would be more work because we don't need to create a plugin "system", per say. Creating a new plugin manager is relatively easy.

In core, the only concept of handlers that is similar/relevant are entity handlers (Dare: grep core for "handler"). Since the code for entity handlers isn't reusable, there is isn't much to leverage.

dawehner’s picture

Exactly, entity handlers are a non long term solution IMHO, so let's do it right when we do it right.

christianadamski’s picture

Any progress here? We do use custom entities, we have complex fields attached to them, and any magic those fields provide to Views is lost.

Is there any workaround besides copying each fields type hook_fields_views_data() content into the entities getViewsData() ?

jibran’s picture

Version: 8.0.x-dev » 8.1.x-dev

Whatever we'll do here it will not be added to 8.0.x.

Version: 8.1.x-dev » 8.2.x-dev

Drupal 8.1.0-beta1 was released on March 2, 2016, which means new developments and disruptive changes should now be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

dawehner’s picture

StatusFileSize
new7.81 KB

@alexpott and myself discussed a bit and we kinda think a plugin/field type handler would totally makes sense.
This would then result into something like this.

jibran’s picture

plugin/field type handler would totally makes sense.

Can you please elaborate on this? I know patch is just WIP perhaps update the issue summary with agreed apporoch.

dawehner’s picture

Can you please elaborate on this

Well, its a 1to1 relationship between field type and views data. A hook for example is a relationship betweent he provider of a field type and the module of it. A hook also is some kind of event we are firing, this here is a clear functionality for itself.

dawehner’s picture

StatusFileSize
new17.81 KB
new12.68 KB

This implements it for booleans and entity_references. I fear we need much more parameters though.

dawehner’s picture

[13:36:11] but yeah my idea was to slightly convert examples over examples to figure out the right signature/abstraction
[13:36:25] and then post a patch without the conversions + a follow up to provide the actual conversions

berdir’s picture

Should the arguments/process be similar to the existing hook_field_views_data() pseudo hook/callback?

I suppose we could check if there is a hook, then call that and if not, use the new plugin (which has views_field_default_views_data() as the default implementation if nothing is specified exactly).

I don't think that supporting both is needed, so we'd deprecate the old hook in favor of this system?

dawehner’s picture

I don't think that supporting both is needed, so we'd deprecate the old hook in favor of this system?

Oh yeah the new system should be the prefered one.

I suppose we could check if there is a hook, then call that and if not, use the new plugin (which has views_field_default_views_data() as the default implementation if nothing is specified exactly).

Ah good idea. For now its kinda the other way round, as the default implementation is still the old way.

dawehner’s picture

In case someone is interested in that ask during the devdays I'm happy to help out to get people started.

stborchert’s picture

Assigned: Unassigned » stborchert

If there are no objections or nobody else is working on this, I'll take a look ...

dawehner’s picture

Nice! Please ping me when you need help / want to discuss something!

stborchert’s picture

Status: Needs work » Needs review
StatusFileSize
new15.15 KB
new33.03 KB

Here is a (very incomplete and partially working) draft of what I think could be a way to do this.
I guess there are some thing that could be done much easier and in a more elegant way.

stborchert’s picture

StatusFileSize
new34.68 KB
new15.29 KB

Next try solving some issues.
Obviously the field definition (i.e. for body fields) are wrong so this does not work yet.

Status: Needs review » Needs work
stborchert’s picture

Assigned: stborchert » Unassigned

I'm off for two weeks, so setting to unassigned ...

dawehner’s picture

Thanks a lot @stBorchert Enjoy your holidays!

Version: 8.2.x-dev » 8.3.x-dev

Drupal 8.2.0-beta1 was released on August 3, 2016, which means new developments and disruptive changes should now be targeted against the 8.3.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

borisson_’s picture

Status: Needs work » Needs review
StatusFileSize
new5.41 KB
new35.77 KB

I started looking at this and while reading the patch I figured I'd fix docs issues as I went trough it. I'll try fixing the failures now.

borisson_’s picture

StatusFileSize
new2.2 KB
new37.98 KB

As discussed with @dawehner, I added string / integer fields.

borisson_’s picture

StatusFileSize
new2.18 KB
new37.27 KB

Class / file name for string didn't match, so fixed that. Also fixed at least one testfailure, the bulkform test. Hopefully this also fixes more / other things.

The last submitted patch, 46: allow_fieldtype_to-2337515-46.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 47: allow_fieldtype_to-2337515-47.patch, failed testing.

borisson_’s picture

Status: Needs work » Needs review
StatusFileSize
new2.68 KB
new37.94 KB

@bojanz told the formats were not correct for integer / string, so I removed those.

I also changed one test so it doesn't fatal but fails as expected.

jibran’s picture

Status: Needs review » Needs work

Nice progress.

  1. +++ b/core/modules/views/src/EntityViewsData.php
    @@ -517,115 +516,6 @@ protected function mapSingleFieldViewsData($table, $field_name, $field_type, $co
    -      else {
    -        $views_field['field']['id'] = 'field';
    -        $views_field['argument']['id'] = 'string';
    -        $views_field['filter']['id'] = 'string';
    -        $views_field['sort']['id'] = 'standard';
    -      }
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/EntityReference.php
    @@ -0,0 +1,98 @@
    +      if ($entity_type instanceof ContentEntityType) {
    

    So we removed the else part nicely done. We should add some docs in the if part.

  2. +++ b/core/modules/views/src/Plugin/FieldTypeViewsDataPluginManager.php
    @@ -0,0 +1,48 @@
    +    $this->alterInfo('views_field_type_views_data');
    

    This is not documented anywhere.

  3. +++ b/core/modules/views/src/Plugin/FieldTypeViewsDataPluginManager.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Boolean.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Boolean.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/EntityReference.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/EntityReference.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Integer.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Integer.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Language.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Language.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/StringField.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/StringField.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Text.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Text.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/TextLong.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/TextLong.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/TextWithSummary.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/TextWithSummary.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Uri.php
    
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Uri.php
    --- /dev/null
    +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Uuid.php
    

    Field specific handler should be moved to respective fields and base field handler should be moved to Core fields plugin folders.

  4. +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/EntityReference.php
    @@ -0,0 +1,98 @@
    +    $views_data = $this->entityTypeManager->getHandler($field_storage->getTargetEntityTypeId(), 'views_data');
    

    We need a hasHandler check before getHandler.

  5. +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/EntityReference.php
    @@ -0,0 +1,98 @@
    +        $views_field['argument']['id'] = 'numeric';
    +        $views_field['filter']['id'] = 'numeric';
    

    We have string id fields as well in core so we need a check here like _comment_entity_uses_integer_id().

  6. +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/EntityReference.php
    @@ -0,0 +1,98 @@
    +    if ($field_storage->getName() == $this->entityTypeManager->getDefinition($field_storage->getTargetEntityTypeId())->getKey('bundle')) {
    

    Instead of calling gerTargetEntityTypeId again and again let's use a variable here.

  7. +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/Uuid.php
    @@ -0,0 +1,25 @@
    + *     "click sortable" = FALSE,
    

    Do we really need this?

The last submitted patch, 50: allow_fieldtype_to-2337515-50.patch, failed testing.

borisson_’s picture

Status: Needs work » Needs review
Issue tags: +Drupalaton
StatusFileSize
new2.31 KB
new38.35 KB

#51:
.1 fixed.
.2 I'd like to do that when we figure out all the failures.
.3 same here, let's get the patch green before doing that.
.4 Makes sense, done.
.5 Yup, done.
.6 done.
.7 I have no idea really, I left it as-is now and I'll try to steal some @dawehner's time here at drupalaton.

Status: Needs review » Needs work

The last submitted patch, 53: allow_fieldtype_to-2337515-52.patch, failed testing.

borisson_’s picture

Status: Needs work » Needs review
StatusFileSize
new2.95 KB
new39.07 KB

Fixes #51.5, that was actually not fixed in #53.

jibran’s picture

Thanks for fixing the feedback.

+++ b/core/modules/views/src/Plugin/views/FieldTypeViewsData/EntityReference.php
@@ -0,0 +1,128 @@
+        else {
+          $views_field['argument']['id'] = 'string';
+          $views_field['filter']['id'] = 'string';
+        }

These are the default values no need to set these again.

Status: Needs review » Needs work

The last submitted patch, 55: allow_fieldtype_to-2337515-55.patch, failed testing.

The last submitted patch, 45: allow_fieldtype_to-2337515-45.patch, failed testing.

borisson_’s picture

Status: Needs work » Needs review
StatusFileSize
new729 bytes
new38.14 KB

Fixes #56. I'll try to do more work on this during my flight from here back to Belgium but I can't promise that I'll figure out all the remaining fails and honestly I don't see too much time I can spend on this during the weeks after this.

borisson_’s picture

StatusFileSize
new3.09 KB
new40.34 KB

Reduces unit test fails for EntityViewsDataTest

The last submitted patch, 59: allow_fieldtype_to-2337515-59.patch, failed testing.

Status: Needs review » Needs work

The last submitted patch, 60: allow_fieldtype_to-2337515-60.patch, failed testing.

borisson_’s picture

Status: Needs work » Needs review
StatusFileSize
new40.63 KB
new1.61 KB

As promised, I did some work in the airport / on the plane, I have to say that I didn't really get any further, not even after trying to follow @dawehner's sugggestions. I did make a small change to improve readability and changed some documentation.

Leaving that here.

Status: Needs review » Needs work

The last submitted patch, 63: allow_fieldtype_to-2337515-63.patch, failed testing.

borisson_’s picture

Status: Needs work » Needs review
StatusFileSize
new1.36 KB
new39.83 KB

I'm not supposed to be working on drupal core issues now, but I was just explaining to someone why assigning something in an if-statement is a bad idea and I remembered that this patch also does that. So I cleaned that up.

Still the same amount of failures and still no concrete idea how to resolve them.

Status: Needs review » Needs work

The last submitted patch, 65: allow_fieldtype_to-2337515-65.patch, failed testing.

Version: 8.3.x-dev » 8.4.x-dev

Drupal 8.3.0-alpha1 will be released the week of January 30, 2017, which means new developments and disruptive changes should now be targeted against the 8.4.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Version: 8.4.x-dev » 8.5.x-dev

Drupal 8.4.0-alpha1 will be released the week of July 31, 2017, which means new developments and disruptive changes should now be targeted against the 8.5.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

joachim’s picture

This really should be a bug, as it's a big problem for a contrib module that provides a custom field type: Views integration works great for config fields created in the UI, but not for base fields added to the entity types in code.

As an example, consider State Machine module. That diligently implements hook_field_views_data() to declare is custom Views filter plugins. But if I add a state field to my entity's base fields, the Views integration is completely missing.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

claudiu.cristea’s picture

Assigned: Unassigned » claudiu.cristea
Status: Needs work » Needs review
Issue tags: +DCTransylvania2018, +DCTransylvania
StatusFileSize
new39.95 KB

Straight reroll of #65. Assigning.

Status: Needs review » Needs work

The last submitted patch, 71: 2337515-71.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

amateescu’s picture

Issue tags: -DCTransylvania2018

Cleaning up tags.

Version: 8.6.x-dev » 8.7.x-dev

Drupal 8.6.0-alpha1 will be released the week of July 16, 2018, which means new developments and disruptive changes should now be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

kim.pepper’s picture

Issue tags: +DrupalSouth 2018
jibran’s picture

Assigned: claudiu.cristea » Unassigned

Going to have a look at DrupalSouth 2018.

pameeela’s picture

Issue summary: View changes
jibran’s picture

Thanks, Pam, for creating the issue summary.

@Sam152, and I discussed this issue at DrupalSouth. We come up the views handler approach for FieldTypes same as Entities.

The idea is to deprecate the hook_views_field_data and provide modules the complete felxible API to provide views data for both base and configureable fields.

g089h515r806’s picture

I suggest make it configurable in baseFieldDefinitions() of entity class.

 $fields['mybasefield'] = BaseFieldDefinition::create('list_string')
      ->setLabel(t('my base field'))
      ->setDescription(t(''))
      ->setRequired(FALSE)
      ->setDefaultValue('')
      ->setSetting('allowed_values', [
        'option1' => 'option1',
        'option2' => 'option2',
      ])
      ->setViewsOptions('filter ', [
        'id' => 'list_field',
      ])	  
      ->setDisplayOptions('view', [
        'label' => 'above',
        'type' => 'list_default',
        'weight' => 22,
      ])
      ->setDisplayOptions('form', [
        'type' => 'options_select',
        'weight' => 22,
      ])
      ->setDisplayConfigurable('form', TRUE)
      ->setDisplayConfigurable('view', TRUE);  

allow config views settings using method:

      ->setViewsOptions('filter ', [
        'id' => 'list_field',
      ])

It will be easy for developer to use this feature. Then I could add this feature to content entity builder module to make it configurable for base field by UI.

joachim’s picture

  1. +++ b/core/modules/views/src/FieldTypeViewsData.php
    @@ -0,0 +1,73 @@
    + * Field views data.
    

    Needs to be a sentence.

  2. +++ b/core/modules/views/src/FieldTypeViewsData.php
    @@ -0,0 +1,73 @@
    +abstract class FieldTypeViewsData implements FieldTypeViewsDataInterface, ContainerFactoryPluginInterface {
    

    Most plugin base classes in core have a 'Base' suffix. They also usually go in the plugin folder, alongside the actual plugins.

  3. +++ b/core/modules/views/src/FieldTypeViewsData.php
    @@ -0,0 +1,73 @@
    +  /**
    +   * Views data plugin definition.
    +   *
    +   * @var array
    +   */
    +  protected $plugin_definition;
    +
    +  /**
    +   * Creates a new instance of the data type.
    +   *
    +   * @param array $configuration
    +   *   The configuration for this specific instance.
    +   * @param string $plugin_id
    +   *   The id of the plugin to create.
    +   * @param array $plugin_definition
    +   *   The definition of the plugin's available options.
    +   */
    +  public function __construct(array $configuration, $plugin_id, $plugin_definition) {
    +    foreach (['argument', 'field', 'filter', 'sort'] as $key) {
    +      if (isset($plugin_definition[$key])) {
    +        $this->plugin_definition[$key] = $plugin_definition[$key];
    +      }
    +    }
    +  }
    

    Doesn't the PluginBase class do all this for us?

  4. +++ b/core/modules/views/src/Plugin/views/FieldTypeViewsDataInterface.php
    @@ -0,0 +1,17 @@
    +  /**
    +   * Returns the data that views uses to display the field.
    +   *
    +   * @return array
    +   *   The data views uses to display the field.
    +   */
    +  public function getViewsData(FieldStorageDefinitionInterface $field_storage, $column_name);
    

    Missing @params.

  5. +++ b/core/modules/views/views.views.inc
    @@ -176,13 +177,21 @@ function views_views_data() {
    +        if ($field_type_views_data->hasDefinition($field_storage->getType()) && ($field_type_views_data_plugin = $field_type_views_data->createInstance($field_storage->getType()))) {
    
    @@ -749,6 +758,55 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora
    +  // If the field type is not available, ignore it.
    +  if (!\Drupal::service('plugin.manager.field.field_type')->hasDefinition($field_storage->getType())) {
    +    return $data;
    +  }
    

    This is being checked twice.

  6. +++ b/core/modules/views/views.views.inc
    @@ -749,6 +758,55 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora
    +  // Fields with custom storage will need to write their own handlers, so ignore
    +  // them.
    +  if ($field_storage->hasCustomStorage()) {
    

    What does this mean? How would they write their own handlers, and how would those be used? What type of handlers does this mean anyway?

  7. +++ b/core/modules/views/views.views.inc
    @@ -749,6 +758,55 @@ function views_field_default_views_data(FieldStorageConfigInterface $field_stora
    +  // Check whether the entity type storage is supported.
    +  $storage = _views_field_get_entity_type_storage($field_storage);
    +  if (!$storage) {
    +    return $data;
    +  }
    +
    +  $table_mapping = $storage->getTableMapping();
    +  $table = $storage->getBaseTable();
    +  $field_name = $field_storage->getName();
    +  $field_column_mapping = $table_mapping->getColumnNames($field_name);
    +  $multiple = (count($field_column_mapping) > 1);
    +
    +  foreach ($field_column_mapping as $field_column_name => $schema_field_name) {
    +    $views_field_name = ($multiple) ? $field_name . '__' . $field_column_name : $field_name;
    +
    +    $data[$table][$views_field_name] = $field_type_views_data_plugin->getViewsData($field_storage, $field_column_name);
    +  }
    

    Why not fold all this logic into the plugin?

Version: 8.7.x-dev » 8.8.x-dev

Drupal 8.7.0-alpha1 will be released the week of March 11, 2019, which means new developments and disruptive changes should now be targeted against the 8.8.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

joachim’s picture

Here's a straight reroll of #71 for 8.8.x.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

greggles’s picture

Here's a reroll of #82 for 8.8.x since that failed to apply.

dunebl’s picture

D 8.8.2
Unfortunately #84 is the origin of a new bug:
When I applied the patch, I got a "broken/missing handler" for a simple Filter criteria on an Entity Reference field (Taxonomy).
Here is how my broken filter is defined: my_taxo_field is one of a_value
=>Same problem if I recreate this filter from scratch

If I unpatch #84, my filter is working again

geek-merlin’s picture

@DuneBL: I guess this can only help if you add a backtrace.

Version: 8.9.x-dev » 9.1.x-dev

Drupal 8.9.0-beta1 was released on March 20, 2020. 8.9.x is the final, long-term support (LTS) minor release of Drupal 8, which means new developments and disruptive changes should now be targeted against the 9.1.x-dev branch. For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

japerry’s picture

Status: Needs work » Needs review
StatusFileSize
new42.81 KB

The langauge plugin contained a reference to entity.manager. Lets see if removing that gets tests to pass.

Status: Needs review » Needs work

The last submitted patch, 88: 2337515-88.drupal.Allow-FieldType-to-customize-views.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

Version: 9.1.x-dev » 9.2.x-dev

Drupal 9.1.0-alpha1 will be released the week of October 19, 2020, which means new developments and disruptive changes should now be targeted for the 9.2.x-dev branch. For more information see the Drupal 9 minor version schedule and the Allowed changes during the Drupal 9 release cycle.

Version: 9.2.x-dev » 9.3.x-dev

Drupal 9.2.0-alpha1 will be released the week of May 3, 2021, which means new developments and disruptive changes should now be targeted for the 9.3.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.3.x-dev » 9.4.x-dev

Drupal 9.3.0-rc1 was released on November 26, 2021, which means new developments and disruptive changes should now be targeted for the 9.4.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

golddragon007’s picture

I've created this patch to apply to 9.2.x drupal, which I used as base the #88 patch, but it does not seem to solve my original problem.
Also, I've dropped the /core/modules/views/tests/src/Unit/EntityViewsDataTest.php file, as it does not exist in this drupal version.

joachim’s picture

Between #19 and #35 there was discussion and agreement on changing the approach. But the issue summary now needs updating.

joachim’s picture

> Also, I've dropped the /core/modules/views/tests/src/Unit/EntityViewsDataTest.php file, as it does not exist in this drupal version.

The unit test class EntityViewsDataTest.php was converted to a Kernel test, so #93 has lost work that needs to be added to the kernel test.

Nope, the changes to that file were just a monstrous amount of mocking, which only goes to show that converting that unit test was the right thing to do :)

joachim’s picture

Moving this to MRs, as it'll be easier to rebase in future.

joachim’s picture

I'm having a more in-depth look at the current line of work, at a deeper level than my eyeball review in #80, and I'm not sure about this approach.

      $field_type_definition_exists = $this->fieldTypeViewsData->hasDefinition($field_definition_type);
      if ($field_type_definition_exists) {
        /** @var \Drupal\views\Plugin\views\FieldTypeViewsDataInterface $field_type_views_data_plugin */
        $field_type_views_data_plugin = $this->fieldTypeViewsData->createInstance($field_definition_type);

This is creating a 1-1 relationship between the field type ID and the field data ID.

I'm not sure this is very efficient. What if multiple field types have the same requirements?

It also means we have several plugins in the MR which are just empty classses, e.g.

class Integer extends FieldTypeViewsData {

}

Additionally, the plugin type's class names and namespaces aren't following the pattern for the rest of the Views plugins:

- FieldTypeViewsData for the plugin namespace -- other views plugins namespaces are in snake case
- FieldTypeViewsData for the base class -- plugin base classes are typically located in the plugin folder and called FooPluginBase
-

joachim’s picture

I've made a lot of the changes I wanted to make.

Still to do:

- I'm confused why these plugins don't define a 'field' section for Views data, just 'argument' and 'filter'. How is that getting defined?
- I want to consolidate the plugins some more

Also, two tests are failing with this and I have NO IDEA:

1) Drupal\Tests\views\Kernel\Entity\EntityViewsDataTest::testDataTableFields
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'Translation language'
+'Original language'

/Users/joachim/Sites/drupal-core-composer/vendor/phpunit/phpunit/src/Framework/Constraint/Equality/IsEqual.php:96
/Users/joachim/Sites/drupal-core-composer/repos/drupal/core/modules/views/tests/src/Kernel/Entity/EntityViewsDataTest.php:487
/Users/joachim/Sites/drupal-core-composer/vendor/phpunit/phpunit/src/Framework/TestResult.php:726

I can't find ANYWHERE in core where the string 'Translation language' is coming from!

berdir’s picture

> - I'm confused why these plugins don't define a 'field' section for Views data, just 'argument' and 'filter'. How is that getting defined?

Because field rendering uses formatters just like view displays, so there is no views specific integration needed.

This is creating a 1-1 relationship between the field type ID and the field data ID.

I'm not sure this is very efficient. What if multiple field types have the same requirements?

It also means we have several plugins in the MR which are just empty classses, e.g.

I haven't thought it through and I haven't look at the MR, but one option could be to use the same mechanism as field widgets and formatters, which have an annotation property that defines with which field types they are compatible with. That can also be altered through a plugin definition alter hook to add your own field type to an existing plugin. Although that also opens the door for multiple plugins per field type and I'm not sure we really want to go there. Similar to entity types <=> entity classes, we could explicitly check for multiple matches and throw an exception then

joachim’s picture

> I haven't thought it through and I haven't look at the MR, but one option could be to use the same mechanism as field widgets and formatters, which have an annotation property that defines with which field types they are compatible with

Already done that in the MR :)

> we could explicitly check for multiple matches and throw an exception then

And that :)

berdir’s picture

Posted a bunch of comments on the MR, I recommend reading through all of them before replying, sometimes I saw stuff further down that affected a previous comment.

joachim’s picture

For anyone wanting to apply this as a patch to a 9.3 codebase, I've pushed a branch 2337515-93x-views-data-from-fieldtype which is at time of writing up to date with the work on the main development branch, 2337515-views-data-from-fieldtype.

Version: 9.4.x-dev » 9.5.x-dev

Drupal 9.4.0-alpha1 was released on May 6, 2022, which means new developments and disruptive changes should now be targeted for the 9.5.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

Version: 9.5.x-dev » 10.1.x-dev

Drupal 9.5.0-beta2 and Drupal 10.0.0-beta2 were released on September 29, 2022, which means new developments and disruptive changes should now be targeted for the 10.1.x-dev branch. For more information see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

joachim’s picture

Rebased branches, and made a new MR for 9.5.x.

Not had time to consider the architectural questions raised by Berdir :(

I wonder if plugin decoration would be a way to do this: #2958184: Allow decoration of plugins.

Or we just specify a handler class name?

_pratik_ made their first commit to this issue’s fork.

geek-merlin’s picture

Version: 10.1.x-dev » 11.x-dev

Drupal core is moving towards using a “main” branch. As an interim step, a new 11.x branch has been opened, as Drupal.org infrastructure cannot currently fully support a branch named main. New developments and disruptive changes should now be targeted for the 11.x branch, which currently accepts only minor-version allowed changes. For more information, see the Drupal core minor version schedule and the Allowed changes during the Drupal core release cycle.

joachim’s picture

I've just realised this is closely linked to hook_field_views_data_views_data_alter()

The docs for that say:

> The Views module's implementation of hook_views_data_alter() invokes this for each field storage, in the module that defines the field type. It is not invoked in other modules.

So it's basically: the module defining the field type gets to say something about Views data. That hook is still needed, because it allows field type providers to do things like reverse entity references.

But as a follow-up we could move that hook to the new handler classes that this issue will introduce.

joachim’s picture

I'm removing commit e7790601 because it's making lots of unrelated changes, which is making the branch harder to rebase.

joachim’s picture

Rebased to 11.x and made a new branch.

nicxvan’s picture

Can we clean up the unused MRs?
Also does this have to be annotations still?

godotislate’s picture

If the approach with a new plugin type is used, then this definitely needs an attribute, and probably should replace the annotation, since there's no need for the annotation BC layer for a new plugin type.

Though I think @berdir suggested in #102/MR review that tagged services might be a better way to go than plugins?

berdir’s picture

This is going to be a pretty painful rebase now that views.views.inc is gone, but yes, since it is now in a service, I think it would make a lot of sense to make that essentially a tagged service and then we can just inject the handlers into that. I have this open and plan to see if I can make that work.

joachim’s picture

How would a tagged service work?

> Which is where things start to get interesting. This currently only has access to its own definition. but that callback is called on the whole definition and is capable of implementing back-references (see file_field_views_data_views_data_alter() for example and core_field_views_data() for term entity reference fields.

This precise point has come up at #2706431: provide Views reverse relationships automatically for entity base fields -- handler classes for field type views data need to have one method for the field table, and another, optional one, to allow adding to the whole of the Views data.

Version: 11.x-dev » main

Drupal core is now using the main branch as the primary development branch. New developments and disruptive changes should now be targeted to the main branch.

Read more in the announcement.