Issue #2852067 by Sam152, seanB, amateescu, jibran, dawehner, larowlan, tstoeckler, tim.plunkett: Add support for rendering computed fields to the "field" views field handler

8.5.x
Lee Rowlands 2017-08-25 18:18:27 +10:00
parent 6496b03d54
commit 1fa12fb744
No known key found for this signature in database
GPG Key ID: 2B829A3DF9204DC4
7 changed files with 348 additions and 7 deletions

View File

@ -0,0 +1,45 @@
<?php
namespace Drupal\entity_test\Entity;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\entity_test\Plugin\Field\ComputedTestFieldItemList;
/**
* An entity used for testing computed field values.
*
* @ContentEntityType(
* id = "entity_test_computed_field",
* label = @Translation("Entity Test computed field"),
* base_table = "entity_test_computed_field",
* handlers = {
* "views_data" = "Drupal\entity_test\EntityTestViewsData"
* },
* entity_keys = {
* "id" = "id",
* "label" = "name",
* },
* admin_permission = "administer entity_test content",
* links = {
* "add-form" = "/entity_test_computed_field/add",
* },
* )
*/
class EntityTestComputedField extends EntityTest {
/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);
$fields['computed_string_field'] = BaseFieldDefinition::create('string')
->setLabel('Computed Field Test')
->setComputed(TRUE)
->setClass(ComputedTestFieldItemList::class);
return $fields;
}
}

View File

@ -16,6 +16,17 @@ class EntityTestViewsData extends EntityViewsData {
public function getViewsData() { public function getViewsData() {
$views_data = parent::getViewsData(); $views_data = parent::getViewsData();
if ($this->entityType->id() === 'entity_test_computed_field') {
$views_data['entity_test_computed_field']['computed_string_field'] = [
'title' => $this->t('Computed String Field'),
'field' => [
'id' => 'field',
'default_formatter' => 'string',
'field_name' => 'computed_string_field',
],
];
}
if ($this->entityType->id() != 'entity_test') { if ($this->entityType->id() != 'entity_test') {
return $views_data; return $views_data;
} }

View File

@ -0,0 +1,37 @@
<?php
namespace Drupal\entity_test\Plugin\Field;
use Drupal\Core\Field\FieldItemList;
/**
* A computed field item list.
*/
class ComputedTestFieldItemList extends FieldItemList {
/**
* Compute the list property from state.
*/
protected function computedListProperty() {
foreach (\Drupal::state()->get('entity_test_computed_field_item_list_value', []) as $delta => $item) {
$this->list[$delta] = $this->createItem($delta, $item);
}
}
/**
* {@inheritdoc}
*/
public function get($index) {
$this->computedListProperty();
return isset($this->list[$index]) ? $this->list[$index] : NULL;
}
/**
* {@inheritdoc}
*/
public function getIterator() {
$this->computedListProperty();
return parent::getIterator();
}
}

View File

@ -316,24 +316,33 @@ class EntityField extends FieldPluginBase implements CacheableDependencyInterfac
} }
/** /**
* Gets the field storage of the used field. * Gets the field storage definition.
* *
* @return \Drupal\Core\Field\FieldStorageDefinitionInterface * @return \Drupal\Core\Field\FieldStorageDefinitionInterface
* The field storage definition used by this handler.
*/ */
protected function getFieldStorageDefinition() { protected function getFieldStorageDefinition() {
$entity_type_id = $this->definition['entity_type']; $entity_type_id = $this->definition['entity_type'];
$field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id); $field_storage_definitions = $this->entityManager->getFieldStorageDefinitions($entity_type_id);
$field_storage = NULL;
// @todo Unify 'entity field'/'field_name' instead of converting back and // @todo Unify 'entity field'/'field_name' instead of converting back and
// forth. https://www.drupal.org/node/2410779 // forth. https://www.drupal.org/node/2410779
if (isset($this->definition['field_name'])) { if (isset($this->definition['field_name']) && isset($field_storage_definitions[$this->definition['field_name']])) {
$field_storage = $field_storage_definitions[$this->definition['field_name']]; return $field_storage_definitions[$this->definition['field_name']];
} }
elseif (isset($this->definition['entity field'])) {
$field_storage = $field_storage_definitions[$this->definition['entity field']]; if (isset($this->definition['entity field']) && isset($field_storage_definitions[$this->definition['entity field']])) {
return $field_storage_definitions[$this->definition['entity field']];
}
// The list of field storage definitions above does not include computed
// base fields, so we need to explicitly fetch a list of all base fields in
// order to support them.
// @see \Drupal\Core\Entity\EntityFieldManager::getFieldStorageDefinitions()
$base_fields = $this->entityManager->getBaseFieldDefinitions($entity_type_id);
if (isset($this->definition['field_name']) && isset($base_fields[$this->definition['field_name']])) {
return $base_fields[$this->definition['field_name']]->getFieldStorageDefinition();
} }
return $field_storage;
} }
/** /**

View File

@ -0,0 +1,171 @@
langcode: en
status: true
dependencies:
module:
- entity_test
id: computed_field_view
label: 'Computed Field View'
module: views
description: ''
tag: ''
base_table: entity_test_computed_field
base_field: id
core: 8.x
display:
default:
display_plugin: default
id: default
display_title: Master
position: 0
display_options:
access:
type: none
options: { }
cache:
type: tag
options: { }
query:
type: views_query
options:
disable_sql_rewrite: false
distinct: false
replica: false
query_comment: ''
query_tags: { }
exposed_form:
type: basic
options:
submit_button: Apply
reset_button: false
reset_button_label: Reset
exposed_sorts_label: 'Sort by'
expose_sort_order: true
sort_asc_label: Asc
sort_desc_label: Desc
pager:
type: mini
options:
items_per_page: 10
offset: 0
id: 0
total_pages: null
expose:
items_per_page: false
items_per_page_label: 'Items per page'
items_per_page_options: '5, 10, 25, 50'
items_per_page_options_all: false
items_per_page_options_all_label: '- All -'
offset: false
offset_label: Offset
tags:
previous:
next:
style:
type: default
options:
grouping: { }
row_class: ''
default_row_class: true
uses_fields: false
row:
type: fields
options:
inline: { }
separator: ''
hide_empty: false
default_field_elements: true
fields:
computed_string_field:
id: computed_string_field
table: entity_test_computed_field
field: computed_string_field
relationship: none
group_type: group
admin_label: ''
label: ''
exclude: false
alter:
alter_text: false
text: ''
make_link: false
path: ''
absolute: false
external: false
replace_spaces: false
path_case: none
trim_whitespace: false
alt: ''
rel: ''
link_class: ''
prefix: ''
suffix: ''
target: ''
nl2br: false
max_length: 0
word_boundary: true
ellipsis: true
more_link: false
more_link_text: ''
more_link_path: ''
strip_tags: false
trim: false
preserve_tags: ''
html: false
element_type: ''
element_class: ''
element_label_type: ''
element_label_class: ''
element_label_colon: false
element_wrapper_type: ''
element_wrapper_class: ''
element_default_classes: true
empty: ''
hide_empty: false
empty_zero: false
hide_alter_empty: true
click_sort_column: value
type: string
settings:
link_to_entity: false
group_column: value
group_columns: { }
group_rows: true
delta_limit: 0
delta_offset: 0
delta_reversed: false
delta_first_last: false
multi_type: separator
separator: ', '
field_api_classes: false
entity_type: entity_test_computed_field
plugin_id: field
filters: { }
sorts: { }
header: { }
footer: { }
empty: { }
relationships: { }
arguments: { }
display_extenders: { }
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url.query_args
tags: { }
page_1:
display_plugin: page
id: page_1
display_title: Page
position: 1
display_options:
display_extenders: { }
path: foo
cache_metadata:
max-age: -1
contexts:
- 'languages:language_content'
- 'languages:language_interface'
- url.query_args
tags: { }

View File

@ -0,0 +1,57 @@
<?php
namespace Drupal\Tests\views\Kernel\Handler;
use Drupal\entity_test\Entity\EntityTestComputedField;
use Drupal\Tests\views\Kernel\ViewsKernelTestBase;
use Drupal\views\Views;
/**
* Provides some integration tests for the Field handler.
*
* @see \Drupal\views\Plugin\views\field\EntityField
* @group views
*/
class ComputedFieldTest extends ViewsKernelTestBase {
/**
* Views to be enabled.
*
* @var array
*/
public static $testViews = ['computed_field_view'];
/**
* Modules to enable.
*
* @var array
*/
public static $modules = ['entity_test'];
/**
* {@inheritdoc}
*/
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
$this->installEntitySchema('entity_test_computed_field');
}
/**
* Test the computed field handler.
*/
public function testComputedFieldHandler() {
\Drupal::state()->set('entity_test_computed_field_item_list_value', ['computed string']);
$entity = EntityTestComputedField::create([]);
$entity->save();
$view = Views::getView('computed_field_view');
$rendered_view = $view->preview();
$output = $this->container->get('renderer')->renderRoot($rendered_view);
$this->assertContains('computed string', (string) $output);
}
}

View File

@ -16,6 +16,7 @@ use Drupal\Core\TypedData\DataDefinitionInterface;
use Drupal\Core\TypedData\ListInterface; use Drupal\Core\TypedData\ListInterface;
use Drupal\Core\TypedData\Type\StringInterface; use Drupal\Core\TypedData\Type\StringInterface;
use Drupal\Core\TypedData\TypedDataInterface; use Drupal\Core\TypedData\TypedDataInterface;
use Drupal\entity_test\Entity\EntityTestComputedField;
use Drupal\node\Entity\Node; use Drupal\node\Entity\Node;
use Drupal\node\Entity\NodeType; use Drupal\node\Entity\NodeType;
@ -737,6 +738,16 @@ class EntityFieldTest extends EntityKernelTestBase {
} }
} }
/**
* Test computed fields.
*/
public function testComputedFields() {
\Drupal::state()->set('entity_test_computed_field_item_list_value', ['foo computed']);
$entity = EntityTestComputedField::create([]);
$this->assertEquals($entity->computed_string_field->value, 'foo computed');
}
/** /**
* Executes the computed properties tests for the given entity type. * Executes the computed properties tests for the given entity type.
* *