diff --git a/core/modules/views/src/Plugin/views/field/Field.php b/core/modules/views/src/Plugin/views/field/Field.php index 5eaff3857c1..386456cff31 100644 --- a/core/modules/views/src/Plugin/views/field/Field.php +++ b/core/modules/views/src/Plugin/views/field/Field.php @@ -9,7 +9,6 @@ namespace Drupal\views\Plugin\views\field; use Drupal\Component\Utility\SafeMarkup; use Drupal\Component\Utility\Xss as CoreXss; -use Drupal\Core\Cache\CacheableMetadata; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Field\FieldStorageDefinitionInterface; @@ -18,6 +17,7 @@ use Drupal\Core\Field\FormatterPluginManager; use Drupal\Core\Form\FormHelper; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Language\LanguageManagerInterface; +use Drupal\Core\Render\BubbleableMetadata; use Drupal\Core\Render\Element; use Drupal\Core\Render\RendererInterface; use Drupal\Core\Session\AccountInterface; @@ -832,17 +832,19 @@ class Field extends FieldPluginBase implements CacheablePluginInterface, MultiIt // Render using the formatted data itself. $items = []; + // Each item is extracted and rendered separately, the top-level formatter + // render array itself is never rendered, so we extract its bubbleable + // metadata and add it to each child individually. + $bubbleable = BubbleableMetadata::createFromRenderArray($build_list); foreach (Element::children($build_list) as $delta) { - $items[$delta]['rendered'] = $build_list[$delta]; - // Merge the cacheability metadata of the top-level render array into - // each child because they will most likely be rendered individually. - if (isset($build_list['#cache'])) { - CacheableMetadata::createFromRenderArray($build_list) - ->merge(CacheableMetadata::createFromRenderArray($items[$delta]['rendered'])) - ->applyTo($items[$delta]['rendered']); - } - // Add the raw field items (for use in tokens). - $items[$delta]['raw'] = $build_list['#items'][$delta]; + BubbleableMetadata::createFromRenderArray($build_list[$delta]) + ->merge($bubbleable) + ->applyTo($build_list[$delta]); + $items[$delta] = [ + 'rendered' => $build_list[$delta], + // Add the raw field items (for use in tokens). + 'raw' => $build_list['#items'][$delta], + ]; } return $items; } diff --git a/core/modules/views/src/Tests/Handler/FieldFieldTest.php b/core/modules/views/src/Tests/Handler/FieldFieldTest.php index d01e34efa29..fd0da5211d6 100644 --- a/core/modules/views/src/Tests/Handler/FieldFieldTest.php +++ b/core/modules/views/src/Tests/Handler/FieldFieldTest.php @@ -28,12 +28,12 @@ class FieldFieldTest extends ViewUnitTestBase { /** * {@inheritdoc} */ - public static $modules = ['field', 'entity_test', 'user']; + public static $modules = ['field', 'entity_test', 'user', 'views_test_formatter']; /** * {@inheritdoc} */ - public static $testViews = ['test_field_field_test', 'test_field_alias_test', 'test_field_field_complex_test', 'test_field_field_revision_test', 'test_field_field_revision_complex_test']; + public static $testViews = ['test_field_field_test', 'test_field_alias_test', 'test_field_field_complex_test', 'test_field_field_attachment_test', 'test_field_field_revision_test', 'test_field_field_revision_complex_test']; /** * The stored test entities. @@ -265,6 +265,30 @@ class FieldFieldTest extends ViewUnitTestBase { $this->assertEqual(6, $executable->getStyle()->getField(4, 'field_test')); } + /** + * Tests that formatter's #attached assets are correctly preserved. + * + * @see \Drupal\views_test_formatter\Plugin\Field\FieldFormatter\AttachmentTestFormatter::viewElements() + */ + public function testAttachedRender() { + $executable = Views::getView('test_field_field_attachment_test'); + $executable->execute(); + + // Check that the attachments added by AttachmentTestFormatter have been + // preserved in the render array. + $render = $executable->display_handler->render(); + $expected_attachments = [ + 'library' => [ + 'views/views.module' + ] + ]; + foreach ($this->entities as $entity) { + $expected_attachments['library'][] = 'foo/fake_library'; + $expected_attachments['drupalSettings']['AttachmentIntegerFormatter'][$entity->id()] = $entity->id(); + } + $this->assertEqual($expected_attachments, $render['#attached']); + } + /** * Tests the result of a view with complex field configuration. * diff --git a/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_attachment_test.yml b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_attachment_test.yml new file mode 100644 index 00000000000..eae936f7f59 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_config/test_views/views.view.test_field_field_attachment_test.yml @@ -0,0 +1,140 @@ +langcode: en +status: true +dependencies: + config: + - field.storage.entity_test.field_test + module: + - entity_test +id: test_field_field_attachment_test +label: test_field_field_attachment_test +module: views +description: '' +tag: '' +base_table: entity_test +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: none + 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: none + options: + offset: 0 + 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: + field_test: + id: field_test + table: entity_test__field_test + field: field_test + 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: number_unformatted_with_attachment + settings: { } + 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 + plugin_id: field + filters: { } + sorts: { } + header: { } + footer: { } + empty: { } + relationships: { } + arguments: { } + display_extenders: { } + cache_metadata: + contexts: + - 'languages:language_content' + - 'languages:language_interface' + cacheable: false diff --git a/core/modules/views/tests/modules/views_test_formatter/src/Plugin/Field/FieldFormatter/AttachmentTestFormatter.php b/core/modules/views/tests/modules/views_test_formatter/src/Plugin/Field/FieldFormatter/AttachmentTestFormatter.php new file mode 100644 index 00000000000..a5fb7e37fad --- /dev/null +++ b/core/modules/views/tests/modules/views_test_formatter/src/Plugin/Field/FieldFormatter/AttachmentTestFormatter.php @@ -0,0 +1,42 @@ +getEntity()->id(); + $elements['#attached']['library'][] = 'foo/fake_library'; + $elements['#attached']['drupalSettings']['AttachmentIntegerFormatter'][$entity_id] = $entity_id; + + return $elements; + } + +} diff --git a/core/modules/views/tests/modules/views_test_formatter/views_test_formatter.info.yml b/core/modules/views/tests/modules/views_test_formatter/views_test_formatter.info.yml new file mode 100644 index 00000000000..91658d87e21 --- /dev/null +++ b/core/modules/views/tests/modules/views_test_formatter/views_test_formatter.info.yml @@ -0,0 +1,8 @@ +name: 'Views Test Formatter' +type: module +description: 'Provides test field formatters.' +package: Testing +version: VERSION +core: 8.x +dependencies: + - views