Issue #2852067 by Sam152, seanB, amateescu, jibran, dawehner, larowlan, tstoeckler, tim.plunkett: Add support for rendering computed fields to the "field" views field handler
parent
6496b03d54
commit
1fa12fb744
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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: { }
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue