diff -u b/core/lib/Drupal/Core/Field/FieldItemBase.php b/core/lib/Drupal/Core/Field/FieldItemBase.php --- b/core/lib/Drupal/Core/Field/FieldItemBase.php +++ b/core/lib/Drupal/Core/Field/FieldItemBase.php @@ -212,11 +212,9 @@ public function deleteRevision() { } /** - * - * TODO : Transfer to EntityViewBuilder.php * {@inheritdoc} */ - public function view($display_options) { + public function view($display_options = array()) { // Push the item as the single value for the field, and defer to // FieldItemList::view() to build the render array for the whole list. $clone_items = clone $this->getParent(); diff -u b/core/lib/Drupal/Core/Field/FieldItemInterface.php b/core/lib/Drupal/Core/Field/FieldItemInterface.php --- b/core/lib/Drupal/Core/Field/FieldItemInterface.php +++ b/core/lib/Drupal/Core/Field/FieldItemInterface.php @@ -138,7 +138,16 @@ /** - * TODO : PhpDoc. + * Returns a renderable array for a single field item. + * + * @param array $display_options + * Can be either the name of a view mode, or an array of display settings. + * See FieldItemListInterface::view() for more information. + * + * @return array + * A renderable array for the field item. + * + * @see \Drupal\Core\Field\FieldItemListInterface::view() */ - public function view($display_options); + public function view($display_options = array()); } diff -u b/core/lib/Drupal/Core/Field/FieldItemList.php b/core/lib/Drupal/Core/Field/FieldItemList.php --- b/core/lib/Drupal/Core/Field/FieldItemList.php +++ b/core/lib/Drupal/Core/Field/FieldItemList.php @@ -286,9 +286,9 @@ } /** - * TODO : PhpDoc & Transfer to EntityViewBuilder.php + * {@inheritdoc} */ - public function view($display_options) { + public function view($display_options = array()) { $output = array(); $entity = $this->getEntity(); diff -u b/core/lib/Drupal/Core/Field/FieldItemListInterface.php b/core/lib/Drupal/Core/Field/FieldItemListInterface.php --- b/core/lib/Drupal/Core/Field/FieldItemListInterface.php +++ b/core/lib/Drupal/Core/Field/FieldItemListInterface.php @@ -168,7 +168,46 @@ /** - * TODO:PhpDoc + * Returns a renderable array for the field items. + * + * The resulting output is a fully themed field with label and multiple + * values. + * + * This function can be used by third-party modules that need to output an + * isolated field. + * - Do not use inside node (or any other entity) templates; use + * render($content[FIELD_NAME]) instead. + * - Do not use to display all fields in an entity; use + * field_attach_prepare_view() and field_attach_view() instead. + * - The FieldItemInterface::view() method can be used to output a single + * formatted field value, without label or wrapping field markup. + * + * The function takes care of invoking the prepare_view steps. It also + * respects field access permissions. + * + * @param array $display_options + * Can be either: + * - The name of a view mode. The field will be displayed according to the + * display settings specified for this view mode in the $instance + * definition for the field in the entity's bundle. If no display settings + * are found for the view mode, the settings for the 'default' view mode + * will be used. + * - An array of display options. The following key/value pairs are allowed: + * - label: (string) Position of the label. The default 'field' theme + * implementation supports the values 'inline', 'above' and 'hidden'. + * Defaults to 'above'. + * - type: (string) The formatter to use. Defaults to the + * 'default_formatter' for the field type. The default formatter will + * also be used if the requested formatter is not available. + * - settings: (array) Settings specific to the formatter. Defaults to the + * formatter's default settings. + * - weight: (float) The weight to assign to the renderable element. + * Defaults to 0. + * + * @return array + * A renderable array for the field values. + * + * @see \Drupal\Core\Field\FieldItemInterface::view() */ - public function view($display_options); + public function view($display_options = array()); } only in patch2: unchanged: --- a/core/modules/edit/edit.api.php +++ b/core/modules/edit/edit.api.php @@ -32,9 +32,9 @@ function hook_edit_editor_alter(&$editors) { * Returns a renderable array for the value of a single field in an entity. * * To integrate with in-place field editing when a non-standard render pipeline - * is used (field_view_field() is not sufficient to render back the field - * following in-place editing in the exact way it was displayed originally), - * implement this hook. + * is used (FieldItemListInterface::view() is not sufficient to render back the + * field following in-place editing in the exact way it was displayed + * originally), implement this hook. * * Edit module integrates with HTML elements with data-edit-field-id attributes. * For example: @@ -67,12 +67,12 @@ function hook_edit_editor_alter(&$editors) { * @return * A renderable array for the field value. * - * @see field_view_field() + * @see \Drupal\Core\Field\FieldItemListInterface::view() */ function hook_edit_render_field(Drupal\Core\Entity\EntityInterface $entity, $field_name, $view_mode_id, $langcode) { return array( '#prefix' => '
', - 'field' => field_view_field($entity, $field_name, $view_mode_id, $langcode), + 'field' => $entity->getTranslation($langcode)->get($field_name)->view($view_mode_id), '#suffix' => '
', ); } only in patch2: unchanged: --- a/core/modules/edit/edit.module +++ b/core/modules/edit/edit.module @@ -179,8 +179,9 @@ function edit_preprocess_field(&$variables) { $entity = $element['#object']; // Edit module only supports view modes, not dynamically defined "display - // options" (which field_view_field() always names the "_custom" view mode). - // @see field_view_field() + // options" (which \Drupal\Core\Field\FieldItemListInterface::view() always + // names the "_custom" view mode). + // @see \Drupal\Core\Field\FieldItemListInterface::view() // @see https://drupal.org/node/2120335 if ($element['#view_mode'] === '_custom') { return; only in patch2: unchanged: --- a/core/modules/edit/lib/Drupal/edit/EditController.php +++ b/core/modules/edit/lib/Drupal/edit/EditController.php @@ -241,7 +241,7 @@ public function fieldForm(EntityInterface $entity, $field_name, $langcode, $view // row index. $entity_view_mode_ids = array_keys(entity_get_view_modes($entity->entityType())); if (in_array($view_mode_id, $entity_view_mode_ids)) { - $output = field_view_field($entity, $field_name, $view_mode_id, $langcode); + $output = $entity->getTranslation($langcode)->get($field_name)->view($view_mode_id); } else { // Each part of a custom (non-Entity Display) view mode ID is separated @@ -249,6 +249,7 @@ public function fieldForm(EntityInterface $entity, $field_name, $langcode, $view $mode_id_parts = explode('-', $view_mode_id, 2); $module = reset($mode_id_parts); $args = array($entity, $field_name, $view_mode_id, $langcode); + // @todo: Modify hook_edit_render_field() signature as well. $output = $this->moduleHandler->invoke($module, 'edit_render_field', $args); } only in patch2: unchanged: --- a/core/modules/edit/lib/Drupal/edit/Tests/EditLoadingTest.php +++ b/core/modules/edit/lib/Drupal/edit/Tests/EditLoadingTest.php @@ -392,7 +392,7 @@ public function testDisplayOptions() { $display_settings = array( 'label' => 'inline', ); - $build = field_view_field($node, 'body', $display_settings); + $build = $node->body->view($display_settings); $output = drupal_render($build); $this->assertFalse(strpos($output, 'data-edit-field-id'), 'data-edit-field-id attribute not added when rendering field using dynamic display options.'); } only in patch2: unchanged: --- a/core/modules/edit/tests/modules/edit_test.module +++ b/core/modules/edit/tests/modules/edit_test.module @@ -43,8 +43,8 @@ function edit_test_entity_view_alter(&$build, EntityInterface $entity, EntityDis */ function edit_test_edit_render_field(Drupal\Core\Entity\EntityInterface $entity, $field_name, $view_mode_id, $langcode) { return array( - '#prefix' => '
', - 'field' => field_view_field($entity, $field_name), + '#prefix' => '
', + 'field' => $entity->getTranslation($langcode)->get($field_name)->view($view_mode_id), '#suffix' => '
', ); } only in patch2: unchanged: --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -376,7 +376,7 @@ function hook_field_attach_preprocess_alter(&$variables, $context) { } /** - * Perform alterations on field_attach_view() or field_view_field(). + * Perform alterations on field_attach_view() or FieldItemListInterface::view(). * * This hook is invoked after the field module has performed the operation. * @@ -388,11 +388,11 @@ function hook_field_attach_preprocess_alter(&$variables, $context) { * - view_mode: View mode; for example, 'full' or 'teaser'. * - display_options: Either a view mode string or an array of display * options. If this hook is being invoked from field_attach_view(), the - * 'display_options' element is set to the view mode string. If this hook - * is being invoked from field_view_field(), this element is set to the - * $display_options argument and the view_mode element is set to '_custom'. - * See field_view_field() for more information on what its $display_options - * argument contains. + * 'display_options' element is set to the view mode string. If this hook is + * being invoked from FieldItemListInterface::view(), this element is set to + * the $display_options argument and the view_mode element is set to + * '_custom'. See \Drupal\Core\Field\FieldItemListInterface::view() for more + * information on what its $display_options argument contains. * - langcode: The language code used for rendering. * * @deprecated as of Drupal 8.0. Use the entity system instead. only in patch2: unchanged: --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -324,155 +324,6 @@ function _field_filter_xss_display_allowed_tags() { } /** - * Returns a renderable array for a single field value. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity containing the field to display. Must at least contain the ID - * key and the field data to display. - * @param $field_name - * The name of the field to display. - * @param $item - * The field item value to display. - * @param $display - * Can be either the name of a view mode, or an array of display settings. See - * field_view_field() for more information. - * @param $langcode - * (Optional) The language of the value in $item. If not provided, the current - * language will be assumed. - * - * @return - * A renderable array for the field value. - */ -function field_view_value(EntityInterface $entity, $field_name, $item, $display = array(), $langcode = NULL) { - $output = array(); - - if ($field = field_info_field($entity->entityType(), $field_name)) { - // Determine the langcode that will be used by language fallback. - $langcode = field_language($entity, $field_name, $langcode); - - // Push the item as the single value for the field, and defer to - // field_view_field() to build the render array for the whole field. - $clone = clone $entity; - $clone->getTranslation($langcode)->{$field_name}->setValue(array($item)); - $elements = field_view_field($clone, $field_name, $display, $langcode); - - // Extract the part of the render array we need. - $output = isset($elements[0]) ? $elements[0] : array(); - if (isset($elements['#access'])) { - $output['#access'] = $elements['#access']; - } - } - - return $output; -} - -/** - * Returns a renderable array for the value of a single field in an entity. - * - * The resulting output is a fully themed field with label and multiple values. - * - * This function can be used by third-party modules that need to output an - * isolated field. - * - Do not use inside node (or any other entity) templates; use - * render($content[FIELD_NAME]) instead. - * - Do not use to display all fields in an entity; use - * field_attach_prepare_view() and field_attach_view() instead. - * - The field_view_value() function can be used to output a single formatted - * field value, without label or wrapping field markup. - * - * The function takes care of invoking the prepare_view steps. It also respects - * field access permissions. - * - * @param \Drupal\Core\Entity\ContentEntityInterface $entity - * The entity containing the field to display. - * @param $field_name - * The name of the field to display. - * @param $display_options - * Can be either: - * - The name of a view mode. The field will be displayed according to the - * display settings specified for this view mode in the $instance - * definition for the field in the entity's bundle. If no display settings - * are found for the view mode, the settings for the 'default' view mode - * will be used. - * - An array of display options. The following key/value pairs are allowed: - * - label: (string) Position of the label. The default 'field' theme - * implementation supports the values 'inline', 'above' and 'hidden'. - * Defaults to 'above'. - * - type: (string) The formatter to use. Defaults to the - * 'default_formatter' for the field type. The default formatter will also - * be used if the requested formatter is not available. - * - settings: (array) Settings specific to the formatter. Defaults to the - * formatter's default settings. - * - weight: (float) The weight to assign to the renderable element. - * Defaults to 0. - * @param $langcode - * (Optional) The language code the field values are to be shown in. The - * site's current language fallback logic will be applied when no values are - * available for the given language code. If no language code is provided the - * current language will be used. - * - * @return - * A renderable array for the field value. - * - * @see field_view_value() - */ -function field_view_field(ContentEntityInterface $entity, $field_name, $display_options = array(), $langcode = NULL) { - $output = array(); - $bundle = $entity->bundle(); - $entity_type = $entity->entityType(); - - // Return nothing if the field doesn't exist. - if (!$entity->hasField($field_name)) { - return $output; - } - $field_definition = $entity->get($field_name)->getFieldDefinition(); - - // Get the formatter object. - if (is_string($display_options)) { - $view_mode = $display_options; - $formatter = entity_get_render_display($entity, $view_mode)->getRenderer($field_name); - } - else { - $view_mode = '_custom'; - // hook_field_attach_display_alter() needs to receive the 'prepared' - // $display_options, so we cannot let preparation happen internally. - $formatter_manager = Drupal::service('plugin.manager.field.formatter'); - $display_options = $formatter_manager->prepareConfiguration($field_definition->getType(), $display_options); - $formatter = $formatter_manager->getInstance(array( - 'field_definition' => $field_definition, - 'view_mode' => $view_mode, - 'prepare' => FALSE, - 'configuration' => $display_options, - )); - } - - if ($formatter) { - $display_langcode = field_language($entity, $field_name, $langcode); - - // Invoke the formatter's prepareView() and view() methods. - $items = $entity->getTranslation($display_langcode)->get($field_name); - $formatter->prepareView(array($entity->id() => $items)); - $result = $formatter->view($items); - - // Invoke hook_field_attach_view_alter() to let other modules alter the - // renderable array, as in a full field_attach_view() execution. - $context = array( - 'entity' => $entity, - 'view_mode' => $view_mode, - 'display_options' => $display_options, - 'langcode' => $display_langcode, - ); - drupal_alter('field_attach_view', $result, $context); - - if (isset($result[$field_name])) { - $output = $result[$field_name]; - } - } - - return $output; -} - -/** * Extracts the bundle name from a bundle object. * * @param $entity_type only in patch2: unchanged: --- a/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php +++ b/core/modules/field/lib/Drupal/field/Plugin/views/field/Field.php @@ -686,7 +686,7 @@ public function getItems($values) { ); $langcode = $this->field_langcode($entity); - $render_array = field_view_field($entity, $this->definition['field_name'], $display, $langcode); + $render_array = $entity->getTranslation($langcode)->get($this->definition['field_name'])->view($display); $items = array(); if ($this->options['field_api_classes']) { @@ -695,10 +695,10 @@ public function getItems($values) { foreach (element_children($render_array) as $count) { $items[$count]['rendered'] = $render_array[$count]; - // field_view_field() adds an #access property to the render array that - // determines whether or not the current user is allowed to view the - // field in the context of the current entity. We need to respect this - // parameter when we pull out the children of the field array for + // FieldItemListInterface::view() adds an #access property to the render + // array that determines whether or not the current user is allowed to + // view the field in the context of the current entity. We need to respect + // this parameter when we pull out the children of the field array for // rendering. if (isset($render_array['#access'])) { $items[$count]['rendered']['#access'] = $render_array['#access']; @@ -868,6 +868,7 @@ function field_langcode(EntityInterface $entity) { // for the selected language. field_view_field() does this as well, but // since the returned language code is used before calling it, the // fallback needs to happen explicitly. + // @todo This might not be needed anymore. Check with plach. $langcode = $this->entityManager->getTranslationFromContext($entity, $langcode)->language()->id; return $langcode; only in patch2: unchanged: --- a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php @@ -116,11 +116,13 @@ function setUp() { } /** - * Test the field_view_field() function. + * Tests the FieldItemListInterface::view() method. */ - function testFieldViewField() { + function testFieldItemListView() { + $items = $this->entity->get($this->field_name); + // No display settings: check that default display settings are used. - $output = field_view_field($this->entity, $this->field_name); + $output = $items->view(); $this->content = drupal_render($output); $settings = \Drupal::service('plugin.manager.field.formatter')->getDefaultSettings('field_test_default'); $setting = $settings['test_formatter_setting']; @@ -138,7 +140,7 @@ function testFieldViewField() { 'alter' => TRUE, ), ); - $output = field_view_field($this->entity, $this->field_name, $display); + $output = $items->view($display); $this->content = drupal_render($output); $setting = $display['settings']['test_formatter_setting_multiple']; $this->assertNoText($this->label, 'Label was not displayed.'); @@ -158,7 +160,7 @@ function testFieldViewField() { 'test_formatter_setting_additional' => $this->randomName(), ), ); - $output = field_view_field($this->entity, $this->field_name, $display); + $output = $items->view($display); $view = drupal_render($output); $this->content = $view; $setting = $display['settings']['test_formatter_setting_additional']; @@ -170,7 +172,7 @@ function testFieldViewField() { // View mode: check that display settings specified in the display object // are used. - $output = field_view_field($this->entity, $this->field_name, 'teaser'); + $output = $items->view('teaser'); $this->content = drupal_render($output); $setting = $this->display_options['teaser']['settings']['test_formatter_setting']; $this->assertText($this->label, 'Label was displayed.'); @@ -180,7 +182,7 @@ function testFieldViewField() { // Unknown view mode: check that display settings for 'default' view mode // are used. - $output = field_view_field($this->entity, $this->field_name, 'unknown_view_mode'); + $output = $items->view('unknown_view_mode'); $this->content = drupal_render($output); $setting = $this->display_options['default']['settings']['test_formatter_setting']; $this->assertText($this->label, 'Label was displayed.'); @@ -190,15 +192,15 @@ function testFieldViewField() { } /** - * Test the field_view_value() function. + * Tests the FieldItemInterface::view() method. */ - function testFieldViewValue() { + function testFieldItemView() { // No display settings: check that default display settings are used. $settings = \Drupal::service('plugin.manager.field.formatter')->getDefaultSettings('field_test_default'); $setting = $settings['test_formatter_setting']; foreach ($this->values as $delta => $value) { - $item = $this->entity->{$this->field_name}[$delta]->getValue(); - $output = field_view_value($this->entity, $this->field_name, $item); + $item = $this->entity->{$this->field_name}[$delta]; + $output = $item->view(); $this->content = drupal_render($output); $this->assertText($setting . '|' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -212,8 +214,8 @@ function testFieldViewValue() { ); $setting = $display['settings']['test_formatter_setting_multiple']; foreach ($this->values as $delta => $value) { - $item = $this->entity->{$this->field_name}[$delta]->getValue(); - $output = field_view_value($this->entity, $this->field_name, $item, $display); + $item = $this->entity->{$this->field_name}[$delta]; + $output = $item->view($display); $this->content = drupal_render($output); $this->assertText($setting . '|0:' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -227,8 +229,8 @@ function testFieldViewValue() { ); $setting = $display['settings']['test_formatter_setting_additional']; foreach ($this->values as $delta => $value) { - $item = $this->entity->{$this->field_name}[$delta]->getValue(); - $output = field_view_value($this->entity, $this->field_name, $item, $display); + $item = $this->entity->{$this->field_name}[$delta]; + $output = $item->view($display); $this->content = drupal_render($output); $this->assertText($setting . '|' . $value['value'] . '|' . ($value['value'] + 1), format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -237,8 +239,8 @@ function testFieldViewValue() { // used. $setting = $this->display_options['teaser']['settings']['test_formatter_setting']; foreach ($this->values as $delta => $value) { - $item = $this->entity->{$this->field_name}[$delta]->getValue(); - $output = field_view_value($this->entity, $this->field_name, $item, 'teaser'); + $item = $this->entity->{$this->field_name}[$delta]; + $output = $item->view('teaser'); $this->content = drupal_render($output); $this->assertText($setting . '|' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -247,8 +249,8 @@ function testFieldViewValue() { // are used. $setting = $this->display_options['default']['settings']['test_formatter_setting']; foreach ($this->values as $delta => $value) { - $item = $this->entity->{$this->field_name}[$delta]->getValue(); - $output = field_view_value($this->entity, $this->field_name, $item, 'unknown_view_mode'); + $item = $this->entity->{$this->field_name}[$delta]; + $output = $item->view('unknown_view_mode'); $this->content = drupal_render($output); $this->assertText($setting . '|' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } @@ -268,7 +270,7 @@ function testFieldEmpty() { ); // $this->entity is set by the setUp() method and by default contains 4 // numeric values. We only want to test the display of this one field. - $output = field_view_field($this->entity, $this->field_name, $display); + $output = $this->entity->get($this->field_name)->view($display); $view = drupal_render($output); $this->content = $view; // The test field by default contains values, so should not display the @@ -278,7 +280,7 @@ function testFieldEmpty() { // Now remove the values from the test field and retest. $this->entity->{$this->field_name} = array(); $this->entity->save(); - $output = field_view_field($this->entity, $this->field_name, $display); + $output = $this->entity->get($this->field_name)->view($display); $view = drupal_render($output); $this->content = $view; // This time, as the field values have been removed, we *should* show the only in patch2: unchanged: --- a/core/modules/options/lib/Drupal/options/Tests/OptionsFormattersTest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsFormattersTest.php @@ -37,12 +37,13 @@ public function testFormatter() { $entity = entity_create('entity_test', array()); $entity->{$this->fieldName}->value = 1; - $build = field_view_field($entity, $this->fieldName, array()); + $items = $entity->get($this->fieldName); + $build = $items->view(); $this->assertEqual($build['#formatter'], 'list_default', 'Ensure to fall back to the default formatter.'); $this->assertEqual($build[0]['#markup'], 'One'); - $build = field_view_field($entity, $this->fieldName, array('type' => 'list_key')); + $build = $items->view(array('type' => 'list_key')); $this->assertEqual($build['#formatter'], 'list_key', 'The chosen formatter is used.'); $this->assertEqual($build[0]['#markup'], 1); } only in patch2: unchanged: --- a/core/modules/system/system.api.php +++ b/core/modules/system/system.api.php @@ -2851,7 +2851,7 @@ function hook_tokens_alter(array &$replacements, array $context) { // Alter the [node:title] token, and replace it with the rendered content // of a field (field_title). if (isset($context['tokens']['title'])) { - $title = field_view_field($node, 'field_title', 'default', $langcode); + $title = $node->field_title->view('default'); $replacements[$context['tokens']['title']] = drupal_render($title); } }