diff --git a/core/includes/entity.api.php b/core/includes/entity.api.php index fbf627122ef..c12e4db94a6 100644 --- a/core/includes/entity.api.php +++ b/core/includes/entity.api.php @@ -278,29 +278,6 @@ function hook_entity_view_mode_alter(&$view_mode, Drupal\Core\Entity\EntityInter } } -/** - * Alters the settings used for displaying an entity. - * - * @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display - * The entity_display object that will be used to display the entity - * components. - * @param array $context - * An associative array containing: - * - entity_type: The entity type, e.g., 'node' or 'user'. - * - bundle: The bundle, e.g., 'page' or 'article'. - * - view_mode: The view mode, e.g. 'full', 'teaser'... - */ -function hook_entity_display_alter(Drupal\field\Plugin\Core\Entity\EntityDisplay $display, array $context) { - // Leave field labels out of the search index. - if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') { - foreach ($display->content as $name => &$properties) { - if (isset($properties['label'])) { - $properties['label'] = 'hidden'; - } - } - } -} - /** * Define custom entity properties. * diff --git a/core/includes/entity.inc b/core/includes/entity.inc index d4ca7a528cf..a86686491fd 100644 --- a/core/includes/entity.inc +++ b/core/includes/entity.inc @@ -563,128 +563,6 @@ function entity_view_multiple(array $entities, $view_mode, $langcode = NULL) { return entity_render_controller(reset($entities)->entityType())->viewMultiple($entities, $view_mode, $langcode); } -/** - * Returns the entity_display object associated to a bundle and view mode. - * - * Use this function when assigning suggested display options for a component - * in a given view mode. Note that they will only be actually used at render - * time if the view mode itself is configured to use dedicated display settings - * for the bundle; if not, the 'default' display is used instead. - * - * The function reads the entity_display object from the current configuration, - * or returns a ready-to-use empty one if configuration entry exists yet for - * this bundle and view mode. This streamlines manipulation of display objects - * by always returning a consistent object that reflects the current state of - * the configuration. - * - * Example usage: - * - Set the 'body' field to be displayed and the 'field_image' field to be - * hidden on article nodes in the 'default' display. - * @code - * entity_get_display('article', 'node', 'default') - * ->setComponent('body', array( - * 'type' => 'text_summary_or_trimmed', - * 'settings' => array('trim_length' => '200') - * 'weight' => 1, - * )) - * ->removeComponent('field_image') - * ->save(); - * @endcode - * - * @param string $entity_type - * The entity type. - * @param string $bundle - * The bundle. - * @param string $view_mode - * The view mode, or 'default' to retrieve the 'default' display object for - * this bundle. - * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The display object associated to the view mode. - */ -function entity_get_display($entity_type, $bundle, $view_mode) { - // Try loading the display from configuration. - $display = entity_load('entity_display', $entity_type . '.' . $bundle . '.' . $view_mode); - - // If not found, create a fresh display object. We do not preemptively create - // new entity_display configuration entries for each existing entity type and - // bundle whenever a new view mode becomes available. Instead, configuration - // entries are only created when a display object is explicitly configured - // and saved. - if (!$display) { - $display = entity_create('entity_display', array( - 'targetEntityType' => $entity_type, - 'bundle' => $bundle, - 'viewMode' => $view_mode, - )); - } - - return $display; -} - -/** - * Returns the entity_display object used to render an entity. - * - * Depending on the configuration of the view mode for the bundle, this can be - * either the display object associated to the view mode, or the 'default' - * display. - * - * This function should only be used internally when rendering an entity. When - * assigning suggested display options for a component in a given view mode, - * entity_get_display() should be used instead, in order to avoid inadvertently - * modifying the output of other view modes that might happen to use the - * 'default' display too. Those options will then be effectively applied only - * if the view mode is configured to use them. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity being rendered. - * @param string $view_mode - * The view mode being rendered. - * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The display object that should be used to render the entity. - * - * @see entity_get_render_display(). - */ -function entity_get_render_display(EntityInterface $entity, $view_mode) { - $entity_type = $entity->entityType(); - $bundle = $entity->bundle(); - - // Determine the display to use for rendering this entity. Depending on the - // configuration of the view mode for this bundle, this will be either the - // display associated to the view mode, or the 'default' display. - $view_mode_settings = field_view_mode_settings($entity_type, $bundle); - $render_view_mode = !empty($view_mode_settings[$view_mode]['custom_settings']) ? $view_mode : 'default'; - - $display = entity_get_display($entity_type, $bundle, $render_view_mode); - $display->originalViewMode = $view_mode; - - return $display; -} - -/** - * Adjusts weights and visibility of components in displayed entities. - * - * This is used as a #pre_render callback. - */ -function _entity_view_pre_render($elements) { - $display = $elements['#entity_display']; - - $extra_fields = field_info_extra_fields($display->targetEntityType, $display->bundle, 'display'); - foreach (array_keys($extra_fields) as $name) { - if (isset($elements[$name]) && (!isset($elements[$name]['#access']) || $elements[$name]['#access'])) { - if ($options = $display->getComponent($name)) { - $elements[$name]['#weight'] = $options['weight']; - } - else { - $elements[$name]['#access'] = FALSE; - } - } - } - - return $elements; -} - /** * Returns the entity query object for this entity type. * diff --git a/core/lib/Drupal/Core/Entity/EntityRenderController.php b/core/lib/Drupal/Core/Entity/EntityRenderController.php index eb3147e40ab..2cd057859c6 100644 --- a/core/lib/Drupal/Core/Entity/EntityRenderController.php +++ b/core/lib/Drupal/Core/Entity/EntityRenderController.php @@ -30,64 +30,37 @@ class EntityRenderController implements EntityRenderControllerInterface { // Allow modules to change the view mode. $context = array('langcode' => $langcode); - $view_modes = array(); - $displays = array(); - - foreach ($entities as $entity) { + $prepare = array(); + foreach ($entities as $key => $entity) { // Remove previously built content, if exists. $entity->content = array(); drupal_alter('entity_view_mode', $view_mode, $entity, $context); $entity->content['#view_mode'] = $view_mode; - $view_modes[$view_mode][$entity->id()] = $entity; - - $bundle = $entity->bundle(); - - // Load the corresponding display settings if not stored yet. - if (!isset($displays[$view_mode][$bundle])) { - // Get the display object to use for rendering the entity.. - $display = entity_get_render_display($entity, $view_mode); - - // Let modules alter the display. - // Note: if config entities get a static cache at some point, the - // objects should be cloned before running drupal_alter(). - $display_context = array( - 'entity_type' => $this->entityType, - 'bundle' => $bundle, - 'view_mode' => $view_mode, - ); - drupal_alter('entity_display', $display, $display_context); - - $displays[$view_mode][$bundle] = $display; - } - - // Assigning weights to 'extra fields' is done in a pre_render callback. - $entity->content['#pre_render'] = array('_entity_view_pre_render'); - $entity->content['#entity_display'] = $displays[$view_mode][$bundle]; + $prepare[$view_mode][$key] = $entity; } // Prepare and build field content, grouped by view mode. - foreach ($view_modes as $view_mode => $view_mode_entities) { - $call_prepare = array(); + foreach ($prepare as $view_mode => $prepare_entities) { + $call = array(); // To ensure hooks are only run once per entity, check for an - // entity_view_prepared flag and only process relevant entities. - foreach ($view_mode_entities as $entity) { - if (empty($entity->entity_view_prepared) || $entity->entity_view_prepared != $view_mode) { + // entity_view_prepared flag and only process items without it. + foreach ($prepare_entities as $entity) { + if (empty($entity->entity_view_prepared)) { // Add this entity to the items to be prepared. - $call_prepare[$entity->id()] = $entity; + $call[$entity->id()] = $entity; - // Mark this item as prepared for this view mode. - $entity->entity_view_prepared = $view_mode; + // Mark this item as prepared. + $entity->entity_view_prepared = TRUE; } } - if (!empty($call_prepare)) { - field_attach_prepare_view($this->entityType, $call_prepare, $displays[$view_mode], $langcode); - module_invoke_all('entity_prepare_view', $call_prepare, $this->entityType); + if (!empty($call)) { + field_attach_prepare_view($this->entityType, $call, $view_mode, $langcode); + module_invoke_all('entity_prepare_view', $call, $this->entityType); } - - foreach ($view_mode_entities as $entity) { - $entity->content += field_attach_view($this->entityType, $entity, $displays[$view_mode][$entity->bundle()], $langcode); + foreach ($entities as $entity) { + $entity->content += field_attach_view($this->entityType, $entity, $view_mode, $langcode); } } } diff --git a/core/modules/comment/comment.module b/core/modules/comment/comment.module index b73857c85b0..f89d149e1d6 100644 --- a/core/modules/comment/comment.module +++ b/core/modules/comment/comment.module @@ -376,15 +376,15 @@ function _comment_body_field_create($info) { 'bundle' => 'comment_node_' . $info->type, 'settings' => array('text_processing' => 1), 'required' => TRUE, + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'type' => 'text_default', + 'weight' => 0, + ), + ), ); field_create_instance($instance); - entity_get_display('comment', 'comment_node_' . $info->type, 'default') - ->setComponent('comment_body', array( - 'label' => 'hidden', - 'type' => 'text_default', - 'weight' => 0, - )) - ->save(); } } diff --git a/core/modules/contact/lib/Drupal/contact/MessageRenderController.php b/core/modules/contact/lib/Drupal/contact/MessageRenderController.php index 7a1db0d1045..3044a85750f 100644 --- a/core/modules/contact/lib/Drupal/contact/MessageRenderController.php +++ b/core/modules/contact/lib/Drupal/contact/MessageRenderController.php @@ -23,8 +23,9 @@ class MessageRenderController extends EntityRenderController { foreach ($entities as $entity) { // Add the message extra field, if enabled. + $bundle = $entity->bundle(); $entity_view_mode = $entity->content['#view_mode']; - $fields = field_extra_fields_get_display($entity, $entity_view_mode); + $fields = field_extra_fields_get_display($this->entityType, $bundle, $entity_view_mode); if (!empty($entity->message) && !empty($fields['message']['visible'])) { $entity->content['message'] = array( '#type' => 'item', diff --git a/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php b/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php index db2679855ee..1aca55ddd9d 100644 --- a/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php +++ b/core/modules/edit/lib/Drupal/edit/Tests/EditorSelectionTest.php @@ -29,7 +29,7 @@ class EditorSelectionTest extends DrupalUnitTestBase { * * @var array */ - public static $modules = array('system', 'entity', 'field_test', 'field', 'number', 'text', 'edit', 'edit_test'); + public static $modules = array('system', 'field_test', 'field', 'number', 'text', 'edit', 'edit_test'); public static function getInfo() { return array( @@ -103,26 +103,24 @@ class EditorSelectionTest extends DrupalUnitTestBase { 'label' => $label, 'settings' => $widget_settings, ), + 'display' => array( + 'default' => array( + 'label' => 'above', + 'type' => $formatter_type, + 'settings' => $formatter_settings + ), + ), ); field_create_instance($this->$instance); - - entity_get_display('test_entity', 'test_bundle', 'default') - ->setComponent($field_name, array( - 'label' => 'above', - 'type' => $formatter_type, - 'settings' => $formatter_settings - )) - ->save(); } /** * Retrieves the FieldInstance object for the given field and returns the * editor that Edit selects. */ - function getSelectedEditor($items, $field_name, $view_mode = 'default') { - $options = entity_get_display('test_entity', 'test_bundle', $view_mode)->getComponent($field_name); + function getSelectedEditor($items, $field_name, $display = 'default') { $field_instance = field_info_instance('test_entity', $field_name, 'test_bundle'); - return $this->editorSelector->getEditor($options['type'], $field_instance, $items); + return $this->editorSelector->getEditor($field_instance['display'][$display]['type'], $field_instance, $items); } /** diff --git a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php index 37d4ee58f1f..c88f56342e5 100644 --- a/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php +++ b/core/modules/email/lib/Drupal/email/Tests/EmailFieldTest.php @@ -60,14 +60,13 @@ class EmailFieldTest extends WebTestBase { 'placeholder' => 'example@example.com', ), ), + 'display' => array( + 'full' => array( + 'type' => 'email_mailto', + ), + ), ); field_create_instance($this->instance); - // Create a display for the full view mode. - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field['field_name'], array( - 'type' => 'email_mailto', - )) - ->save(); // Display creation form. $this->drupalGet('test-entity/add/test_bundle'); @@ -88,8 +87,7 @@ class EmailFieldTest extends WebTestBase { // Verify that a mailto link is displayed. $entity = field_test_entity_test_load($id); - $display = entity_get_display($entity->entityType(), $entity->bundle(), 'full'); - $entity->content = field_attach_view('test_entity', $entity, $display); + $entity->content = field_attach_view('test_entity', $entity, 'full'); $this->drupalSetContent(drupal_render($entity->content)); $this->assertLinkByHref('mailto:test@example.com'); } diff --git a/core/modules/entity/entity.install b/core/modules/entity/entity.install deleted file mode 100644 index 2e1efd751ba..00000000000 --- a/core/modules/entity/entity.install +++ /dev/null @@ -1,47 +0,0 @@ -get()) { - return $config; - } - - // Initialize a fresh structure. - $uuid = new Uuid(); - $properties = array( - 'id' => $id, - 'uuid' => $uuid->generate(), - 'targetEntityType' => $entity_type, - 'bundle' => $bundle, - 'viewMode' => $view_mode, - 'content' => array(), - ); - foreach ($properties as $key => $value) { - $config->set($key, $value); - } - return $config; -} diff --git a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php b/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php deleted file mode 100644 index 9048788c623..00000000000 --- a/core/modules/entity/lib/Drupal/entity/Plugin/Core/Entity/EntityDisplay.php +++ /dev/null @@ -1,345 +0,0 @@ -originalViewMode = $this->viewMode; - } - - /** - * Overrides \Drupal\Core\Entity\Entity::id(). - */ - public function id() { - return $this->targetEntityType . '.' . $this->bundle . '.' . $this->viewMode; - } - - /** - * Overrides \Drupal\config\ConfigEntityBase::save(). - */ - public function save() { - // Build an ID if none is set. - if (empty($this->id)) { - $this->id = $this->id(); - } - return parent::save(); - } - - /** - * Overrides \Drupal\config\ConfigEntityBase::getExportProperties(); - */ - public function getExportProperties() { - $names = array( - 'id', - 'uuid', - 'targetEntityType', - 'bundle', - 'viewMode', - 'content', - ); - $properties = array(); - foreach ($names as $name) { - $properties[$name] = $this->get($name); - } - return $properties; - } - - /** - * Creates a duplicate of the EntityDisplay object on a different view mode. - * - * The new object necessarily has the same $targetEntityType and $bundle - * properties than the original one. - * - * @param $view_mode - * The view mode for the new object. - * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The new object. - */ - public function createCopy($view_mode) { - $display = $this->createDuplicate(); - $display->viewMode = $display->originalViewMode = $view_mode; - return $display; - } - - /** - * Gets the display options for all components. - * - * @return array - * The array of display options, keyed by component name. - */ - public function getComponents() { - $result = array(); - foreach ($this->content as $name => $options) { - if (!isset($options['visible']) || $options['visible'] === TRUE) { - unset($options['visible']); - $result[$name] = $options; - } - } - return $result; - } - - /** - * Gets the display options set for a component. - * - * @param string $name - * The name of the component. - * - * @return array|null - * The display options for the component, or NULL if the component is not - * displayed. - */ - public function getComponent($name) { - // We always store 'extra fields', whether they are visible or hidden. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); - if (isset($extra_fields[$name])) { - // If we have explicit settings, return an array or NULL depending on - // visibility. - if (isset($this->content[$name])) { - if ($this->content[$name]['visible']) { - return array( - 'weight' => $this->content[$name]['weight'], - ); - } - else { - return NULL; - } - } - - // If no explicit settings for the extra field, look at the default - // visibility in its definition. - $definition = $extra_fields[$name]; - if (!isset($definition['visible']) || $definition['visible'] == TRUE) { - return array( - 'weight' => $definition['weight'] - ); - } - else { - return NULL; - } - } - - if (isset($this->content[$name])) { - return $this->content[$name]; - } - } - - /** - * Sets the display options for a component. - * - * @param string $name - * The name of the component. - * @param array $options - * The display options. - * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The EntityDisplay object. - */ - public function setComponent($name, array $options = array()) { - // If no weight specified, make sure the field sinks at the bottom. - if (!isset($options['weight'])) { - $max = $this->getHighestWeight(); - $options['weight'] = isset($max) ? $max + 1 : 0; - } - - if ($instance = field_info_instance($this->targetEntityType, $name, $this->bundle)) { - $field = field_info_field($instance['field_name']); - $options = drupal_container()->get('plugin.manager.field.formatter')->prepareConfiguration($field['type'], $options); - - // Clear the persisted formatter, if any. - unset($this->formatters[$name]); - } - - // We always store 'extra fields', whether they are visible or hidden. - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); - if (isset($extra_fields[$name])) { - $options['visible'] = TRUE; - } - - $this->content[$name] = $options; - - return $this; - } - - /** - * Sets a component to be hidden. - * - * @param string $name - * The name of the component. - * - * @return \Drupal\entity\Plugin\Core\Entity\EntityDisplay - * The EntityDisplay object. - */ - public function removeComponent($name) { - $extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'display'); - if (isset($extra_fields[$name])) { - // 'Extra fields' are exposed in hooks and can appear at any given time. - // Therefore we store extra fields that are explicitly being hidden, so - // that we can differenciate with those that are simply not configured - // yet. - $this->content[$name] = array( - 'visible' => FALSE, - ); - } - else { - unset($this->content[$name]); - unset($this->formatters[$name]); - } - - return $this; - } - - /** - * Returns the highest weight of the components in the display. - * - * @return int|null - * The highest weight of the components in the display, or NULL if the - * display is empty. - */ - public function getHighestWeight() { - $weights = array(); - - // Collect weights for the components in the display. - foreach ($this->content as $options) { - if (isset($options['weight'])) { - $weights[] = $options['weight']; - } - } - - // Let other modules feedback about their own additions. - $weights = array_merge($weights, module_invoke_all('field_info_max_weight', $this->targetEntityType, $this->bundle, $this->viewMode)); - - return $weights ? max($weights) : NULL; - } - - /** - * Returns the Formatter plugin for a field. - * - * @param string $field_name - * The field name. - * - * @return \Drupal\field\Plugin\Type\Formatter\FormatterInterface - * If the field is not hidden, the Formatter plugin to use for rendering - * it. - */ - public function getFormatter($field_name) { - if (isset($this->formatters[$field_name])) { - return $this->formatters[$field_name]; - } - - // Instantiate the formatter object from the stored display properties. - if ($configuration = $this->getComponent($field_name)) { - $instance = field_info_instance($this->targetEntityType, $field_name, $this->bundle); - $formatter = drupal_container()->get('plugin.manager.field.formatter')->getInstance(array( - 'instance' => $instance, - 'view_mode' => $this->originalViewMode, - // No need to prepare, defaults have been merged in setComponent(). - 'prepare' => FALSE, - 'configuration' => $configuration - )); - } - else { - $formatter = NULL; - } - - // Persist the formatter object. - $this->formatters[$field_name] = $formatter; - return $formatter; - } - -} diff --git a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php b/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php deleted file mode 100644 index 8b0ce69290d..00000000000 --- a/core/modules/entity/lib/Drupal/entity/Tests/EntityDisplayTest.php +++ /dev/null @@ -1,201 +0,0 @@ - 'Entity display configuration entities', - 'description' => 'Tests the entity display configuration entities.', - 'group' => 'Entity API', - ); - } - - protected function setUp() { - parent::setUp(); - - $this->enableModules(array('system', 'entity', 'field')); - } - - /** - * Tests basic CRUD operations on EntityDisplay objects. - */ - public function testEntityDisplayCRUD() { - $display = entity_create('entity_display', array( - 'targetEntityType' => 'entity_test', - 'bundle' => 'entity_test', - 'viewMode' => 'default', - )); - - $expected = array(); - - // Check that providing no 'weight' results in the highest current weight - // being assigned. - $expected['component_1'] = array('weight' => 0); - $expected['component_2'] = array('weight' => 1); - $display->setComponent('component_1'); - $display->setComponent('component_2'); - $this->assertEqual($display->getComponent('component_1'), $expected['component_1']); - $this->assertEqual($display->getComponent('component_2'), $expected['component_2']); - - // Check that arbitrary options are correctly stored. - $expected['component_3'] = array('weight' => 10, 'foo' => 'bar'); - $display->setComponent('component_3', $expected['component_3']); - $this->assertEqual($display->getComponent('component_3'), $expected['component_3']); - - // Check that the display can be properly saved and read back. - $display->save(); - $display = entity_load('entity_display', $display->id()); - foreach (array('component_1', 'component_2', 'component_3') as $name) { - $this->assertEqual($display->getComponent($name), $expected[$name]); - } - - // Check that getComponents() returns options for all components. - $this->assertEqual($display->getComponents(), $expected); - - // Check that a component can be removed. - $display->removeComponent('component_3'); - $this->assertNULL($display->getComponent('component_3')); - - // Check that the removal is correctly persisted. - $display->save(); - $display = entity_load('entity_display', $display->id()); - $this->assertNULL($display->getComponent('component_3')); - - // Check that CreateCopy() creates a new component that can be correclty - // saved. - $new_display = $display->createCopy('other_view_mode'); - $new_display->save(); - $new_display = entity_load('entity_display', $new_display->id()); - $this->assertEqual($new_display->targetEntityType, $display->targetEntityType); - $this->assertEqual($new_display->bundle, $display->bundle); - $this->assertEqual($new_display->viewMode, 'other_view_mode'); - $this->assertEqual($new_display->getComponents(), $display->getComponents()); - } - - /** - * Tests entity_get_display(). - */ - public function testEntityGetDisplay() { - // Check that entity_get_display() returns a fresh object when no - // configuration entry exists. - $display = entity_get_display('entity_test', 'entity_test', 'default'); - $this->assertTrue($display->isNew()); - - // Add some components and save the display. - $display->setComponent('component_1', array('weight' => 10)) - ->save(); - - // Check that entity_get_display() returns the correct object. - $display = entity_get_display('entity_test', 'entity_test', 'default'); - $this->assertFalse($display->isNew()); - $this->assertEqual($display->id, 'entity_test.entity_test.default'); - $this->assertEqual($display->getComponent('component_1'), array('weight' => 10)); - } - - /** - * Tests the behavior of a field component within an EntityDisplay object. - */ - public function testExtraFieldComponent() { - $display = entity_create('entity_display', array( - 'targetEntityType' => 'entity_test', - 'bundle' => 'entity_test', - 'viewMode' => 'default', - )); - - // Check that the default visibility taken into account for extra fields - // unknown in the display. - $this->assertEqual($display->getComponent('display_extra_field'), array('weight' => 5)); - $this->assertNull($display->getComponent('display_extra_field_hidden')); - - // Check that setting explicit options overrides the defaults. - $display->removeComponent('display_extra_field'); - $display->setComponent('display_extra_field_hidden', array('weight' => 10)); - $this->assertNull($display->getComponent('display_extra_field')); - $this->assertEqual($display->getComponent('display_extra_field_hidden'), array('weight' => 10)); - } - - /** - * Tests the behavior of a field component within an EntityDisplay object. - */ - public function testFieldComponent() { - $this->enableModules(array('field_sql_storage', 'field_test')); - - $display = entity_create('entity_display', array( - 'targetEntityType' => 'entity_test', - 'bundle' => 'entity_test', - 'viewMode' => 'default', - )); - - // Create a field and an instance. - $field = array( - 'field_name' => 'test_field', - 'type' => 'test_field' - ); - field_create_field($field); - $instance = array( - 'field_name' => $field['field_name'], - 'entity_type' => 'entity_test', - 'bundle' => 'entity_test', - ); - field_create_instance($instance); - - // Check that providing no options results in default values being used. - $display->setComponent($field['field_name']); - $field_type_info = field_info_field_types($field['type']); - $default_formatter = $field_type_info['default_formatter']; - $default_settings = field_info_formatter_settings($default_formatter); - $expected = array( - 'weight' => 0, - 'label' => 'above', - 'type' => $default_formatter, - 'settings' => $default_settings, - ); - $this->assertEqual($display->getComponent($field['field_name']), $expected); - - // Check that the getFormatter() method returns the correct formatter plugin. - $formatter = $display->getFormatter($field['field_name']); - $this->assertEqual($formatter->getPluginId(), $default_formatter); - $this->assertEqual($formatter->getSettings(), $default_settings); - - // Check that the formatter is statically persisted, by assigning an - // arbitrary property and reading it back. - $random_value = $this->randomString(); - $formatter->randomValue = $random_value; - $formatter = $display->getFormatter($field['field_name']); - $this->assertEqual($formatter->randomValue, $random_value ); - - // Check that changing the definition creates a new formatter. - $display->setComponent($field['field_name'], array( - 'type' => 'field_test_multiple', - )); - $formatter = $display->getFormatter($field['field_name']); - $this->assertEqual($formatter->getPluginId(), 'field_test_multiple'); - $this->assertFalse(isset($formatter->randomValue)); - - // Check that specifying an unknown formatter (e.g. case of a disabled - // module) gets stored as is in the display, but results in the default - // formatter being used. - $display->setComponent($field['field_name'], array( - 'type' => 'unknown_formatter', - )); - $options = $display->getComponent($field['field_name']); - $this->assertEqual($options['type'], 'unknown_formatter'); - $formatter = $display->getFormatter($field['field_name']); - $this->assertEqual($formatter->getPluginId(), $default_formatter); - } - -} diff --git a/core/modules/field/field.api.php b/core/modules/field/field.api.php index c97c6ef4d9a..2620844179b 100644 --- a/core/modules/field/field.api.php +++ b/core/modules/field/field.api.php @@ -1105,13 +1105,12 @@ function hook_field_attach_purge($entity_type, $entity, $field, $instance) { * - entity_type: The type of $entity; for example, 'node' or 'user'. * - entity: The entity with fields to render. * - 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: Either a view mode string or an array of display settings. If + * this hook is being invoked from field_attach_view(), the 'display' + * 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 argument and + * the view_mode element is set to '_custom'. See field_view_field() for + * more information on what its $display argument contains. * - language: The language code used for rendering. */ function hook_field_attach_view_alter(&$output, $context) { @@ -1943,6 +1942,94 @@ function hook_field_info_max_weight($entity_type, $bundle, $context) { return $weights ? max($weights) : NULL; } +/** + * Alters the display settings of a field before it is displayed. + * + * Note that instead of hook_field_display_alter(), which is called for all + * fields on all entity types, hook_field_display_ENTITY_TYPE_alter() may be + * used to alter display settings for fields on a specific entity type only. + * + * This hook is called once per field per displayed entity. If the result of the + * hook involves reading from the database, it is highly recommended to + * statically cache the information. + * + * @param array $display_properties + * The display settings that will be used to display the field values, as + * found in the 'display' key of $instance definitions. + * @param array $context + * An associative array containing: + * - entity_type: The entity type, e.g., 'node' or 'user'. + * - bundle: The bundle, e.g., 'page' or 'article'. + * - field: The field being rendered. + * - instance: The instance being rendered. + * - view_mode: The view mode, e.g. 'full', 'teaser'... + * + * @see hook_field_display_ENTITY_TYPE_alter() + */ +function hook_field_display_alter(array &$display_properties, array $context) { + // Leave field labels out of the search index. + // Note: The check against $context['entity_type'] == 'node' could be avoided + // by using hook_field_display_node_alter() instead of + // hook_field_display_alter(), resulting in less function calls when + // rendering non-node entities. + if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') { + $display_properties['label'] = 'hidden'; + } +} + +/** + * Alters the display settings of a field before it is displayed. + * + * Modules can implement hook_field_display_ENTITY_TYPE_alter() to alter display + * settings for fields on a specific entity type, rather than implementing + * hook_field_display_alter(). + * + * This hook is called once per field per displayed entity. If the result of the + * hook involves reading from the database, it is highly recommended to + * statically cache the information. + * + * @param array $display_properties + * The display settings that will be used to display the field values, as + * found in the 'display' key of $instance definitions. + * @param array $context + * An associative array containing: + * - entity_type: The entity type, e.g., 'node' or 'user'. + * - bundle: The bundle, e.g., 'page' or 'article'. + * - field: The field being rendered. + * - instance: The instance being rendered. + * - view_mode: The view mode, e.g. 'full', 'teaser'... + * + * @see hook_field_display_alter() + */ +function hook_field_display_ENTITY_TYPE_alter(array &$display_properties, array $context) { + // Leave field labels out of the search index. + if ($context['view_mode'] == 'search_index') { + $display_properties['label'] = 'hidden'; + } +} + +/** + * Alters the display settings of pseudo-fields before an entity is displayed. + * + * This hook is called once per displayed entity. If the result of the hook + * involves reading from the database, it is highly recommended to statically + * cache the information. + * + * @param $displays + * An array of display settings for the pseudo-fields in the entity, keyed by + * pseudo-field names. + * @param $context + * An associative array containing: + * - entity_type: The entity type; e.g., 'node' or 'user'. + * - bundle: The bundle name. + * - view_mode: The view mode, e.g. 'full', 'teaser'... + */ +function hook_field_extra_fields_display_alter(&$displays, $context) { + if ($context['entity_type'] == 'taxonomy_term' && $context['view_mode'] == 'full') { + $displays['description']['visible'] = FALSE; + } +} + /** * Alters the widget properties of a field instance on a given entity type * before it gets displayed. diff --git a/core/modules/field/field.attach.inc b/core/modules/field/field.attach.inc index 1a006ec5118..29ebd3b6345 100644 --- a/core/modules/field/field.attach.inc +++ b/core/modules/field/field.attach.inc @@ -7,7 +7,6 @@ use Drupal\field\FieldValidationException; use Drupal\Core\Entity\EntityInterface; -use Drupal\entity\Plugin\Core\Entity\EntityDisplay; /** * @defgroup field_storage Field Storage API @@ -715,6 +714,26 @@ function _field_invoke_widget_target() { }; } +/** + * Defines a 'target function' for field_invoke_method(). + * + * Used to invoke methods on an instance's formatter. + * + * @param mixed $display + * Can be either: + * - The name of a view mode. + * - An array of display properties, as found in + * $instance['display'][$view_mode]. + * + * @return callable $target_function + * A 'target function' for field_invoke_method(). + */ +function _field_invoke_formatter_target($display) { + return function ($instance) use ($display) { + return $instance->getFormatter($display); + }; +} + /** * Adds form elements for all fields for an entity to a form structure. * @@ -1342,10 +1361,10 @@ function field_attach_delete_revision($entity_type, $entity) { * * @param $entity_type * The type of entities in $entities; e.g. 'node' or 'user'. - * @param array $entities + * @param $entities * An array of entities, keyed by entity ID. - * @param array $displays - * An array of entity display objects, keyed by bundle name. + * @param $view_mode + * View mode, e.g. 'full', 'teaser'... * @param $langcode * (Optional) The language the field values are to be shown in. If no language * is provided the current language is used. @@ -1353,7 +1372,7 @@ function field_attach_delete_revision($entity_type, $entity) { * An associative array of additional options. See field_invoke_method() for * details. */ -function field_attach_prepare_view($entity_type, array $entities, array $displays, $langcode = NULL, array $options = array()) { +function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcode = NULL, array $options = array()) { $options['langcode'] = array(); // To ensure hooks are only run once per entity, only process items without @@ -1377,15 +1396,8 @@ function field_attach_prepare_view($entity_type, array $entities, array $display $null = NULL; // First let the field types do their preparation. _field_invoke_multiple('prepare_view', $entity_type, $prepare, $null, $null, $options); - // Then let the formatters do their own specific massaging. For each - // instance, call the prepareView() method on the formatter object handed by - // the entity display. - $target_function = function ($instance) use ($displays) { - if (isset($displays[$instance['bundle']])) { - return $displays[$instance['bundle']]->getFormatter($instance['field_name']); - } - }; - field_invoke_method_multiple('prepareView', $target_function, $prepare, $null, $null, $options); + // Then let the formatters do their own specific massaging. + field_invoke_method_multiple('prepareView', _field_invoke_formatter_target($view_mode), $prepare, $view_mode, $null, $options); } /** @@ -1425,38 +1437,37 @@ function field_attach_prepare_view($entity_type, array $entities, array $display * The type of $entity; e.g. 'node' or 'user'. * @param Drupal\Core\Entity\EntityInterface $entity * The entity with fields to render. - * @param \Drupal\entity\Plugin\Core\Entity\EntityDisplay $display - * The entity display object. + * @param $view_mode + * View mode, e.g. 'full', 'teaser'... * @param $langcode * The language the field values are to be shown in. If no language is * provided the current language is used. * @param array $options * An associative array of additional options. See field_invoke_method() for * details. - - * @return array + * @return * A renderable array for the field values. */ -function field_attach_view($entity_type, EntityInterface $entity, EntityDisplay $display, $langcode = NULL, array $options = array()) { +function field_attach_view($entity_type, EntityInterface $entity, $view_mode, $langcode = NULL, array $options = array()) { // Determine the actual language code to display for each field, given the // language codes available in the field data. $options['langcode'] = field_language($entity_type, $entity, NULL, $langcode); - // For each instance, call the view() method on the formatter object handed - // by the entity display. - $target_function = function ($instance) use ($display) { - return $display->getFormatter($instance['field_name']); - }; + // Invoke field_default_view(). $null = NULL; - $output = field_invoke_method('view', $target_function, $entity, $null, $null, $options); + $output = field_invoke_method('view', _field_invoke_formatter_target($view_mode), $entity, $view_mode, $null, $options); + + // Add custom weight handling. + $output['#pre_render'][] = '_field_extra_fields_pre_render'; + $output['#entity_type'] = $entity_type; + $output['#bundle'] = $entity->bundle(); // Let other modules alter the renderable array. - $view_mode = $display->originalViewMode; $context = array( 'entity_type' => $entity_type, 'entity' => $entity, 'view_mode' => $view_mode, - 'display_options' => $view_mode, + 'display' => $view_mode, 'langcode' => $langcode, ); drupal_alter('field_attach_view', $output, $context); diff --git a/core/modules/field/field.crud.inc b/core/modules/field/field.crud.inc index a62ad2ef73a..ac66c77857b 100644 --- a/core/modules/field/field.crud.inc +++ b/core/modules/field/field.crud.inc @@ -588,6 +588,7 @@ function _field_write_instance(&$instance, $update = FALSE) { // Set defaults. $instance += array( 'settings' => array(), + 'display' => array(), 'widget' => array(), 'required' => FALSE, 'label' => $instance['field_name'], @@ -614,6 +615,30 @@ function _field_write_instance(&$instance, $update = FALSE) { $instance['widget']['module'] = $widget_type['module']; $instance['widget']['settings'] += field_info_widget_settings($instance['widget']['type']); + // Make sure there are at least display settings for the 'default' view mode, + // and fill in defaults for each view mode specified in the definition. + $instance['display'] += array( + 'default' => array(), + ); + foreach ($instance['display'] as $view_mode => $display) { + $display += array( + 'label' => 'above', + 'type' => isset($field_type['default_formatter']) ? $field_type['default_formatter'] : 'hidden', + 'settings' => array(), + ); + if ($display['type'] != 'hidden') { + $formatter_type = field_info_formatter_types($display['type']); + $display['module'] = $formatter_type['module']; + $display['settings'] += field_info_formatter_settings($display['type']); + } + // If no weight specified, make sure the field sinks at the bottom. + if (!isset($display['weight'])) { + $max_weight = field_info_max_weight($instance['entity_type'], $instance['bundle'], $view_mode); + $display['weight'] = isset($max_weight) ? $max_weight + 1 : 0; + } + $instance['display'][$view_mode] = $display; + } + // The serialized 'data' column contains everything from $instance that does // not have its own column and is not automatically populated when the // instance is read. diff --git a/core/modules/field/field.info.inc b/core/modules/field/field.info.inc index 688d6116e6c..5fab889826d 100644 --- a/core/modules/field/field.info.inc +++ b/core/modules/field/field.info.inc @@ -522,7 +522,7 @@ function field_info_extra_fields($entity_type, $bundle, $context) { } /** - * Returns the maximum weight of all the components in a form entity. + * Returns the maximum weight of all the components in an entity. * * This includes fields, 'extra_fields', and other components added by * third-party modules (e.g. field_group). @@ -531,25 +531,33 @@ function field_info_extra_fields($entity_type, $bundle, $context) { * The type of entity; e.g. 'node' or 'user'. * @param $bundle * The bundle name. + * @param $context + * The context for which the maximum weight is requested. Either 'form', or + * the name of a view mode. * * @return * The maximum weight of the entity's components, or NULL if no components * were found. */ -function field_info_max_weight($entity_type, $bundle) { +function field_info_max_weight($entity_type, $bundle, $context) { $weights = array(); // Collect weights for fields. foreach (field_info_instances($entity_type, $bundle) as $instance) { - $weights[] = $instance['widget']['weight']; + if ($context == 'form') { + $weights[] = $instance['widget']['weight']; + } + elseif (isset($instance['display'][$context]['weight'])) { + $weights[] = $instance['display'][$context]['weight']; + } } // Collect weights for extra fields. - foreach (field_info_extra_fields($entity_type, $bundle, 'form') as $extra) { + foreach (field_info_extra_fields($entity_type, $bundle, $context) as $extra) { $weights[] = $extra['weight']; } // Let other modules feedback about their own additions. - $weights = array_merge($weights, module_invoke_all('field_info_max_weight', $entity_type, $bundle, 'form')); + $weights = array_merge($weights, module_invoke_all('field_info_max_weight', $entity_type, $bundle, $context)); $max_weight = $weights ? max($weights) : NULL; return $max_weight; diff --git a/core/modules/field/field.install b/core/modules/field/field.install index 695fd898043..b88faa8b839 100644 --- a/core/modules/field/field.install +++ b/core/modules/field/field.install @@ -357,6 +357,15 @@ function _update_7000_field_create_instance($field, &$instance) { 'deleted' => 0, ); + // Merge in display defaults. + if (isset($instance['display'])) { + foreach ($instance['display'] as &$display) { + $display += array( + 'weight' => 0, + ); + } + } + // The serialized 'data' column contains everything from $instance that does // not have its own column and is not automatically populated when the // instance is read. @@ -393,98 +402,7 @@ function field_update_8001() { ->execute(); } -/** - * Migrate all instance display settings to configuration. - * - * @ingroup config_upgrade - */ -function field_update_8002() { - $displays = array(); - module_load_install('entity'); - - $query = db_select('field_config_instance', 'fc')->fields('fc'); - foreach ($query->execute() as $record) { - // Unserialize the data array and start investigating the display key - // which holds the configuration of this instance for all view modes. - $data = unserialize($record->data); - - // Skip field instances that were created directly with the new API earlier - // in the upgrade path. - if (!isset($data['display'])) { - continue; - } - - foreach ($data['display'] as $view_mode => $display_options) { - // Determine name and create initial entry in the $displays array if it - // does not exist yet. - $display_id = $record->entity_type . '.' . $record->bundle . '.' . $view_mode; - if (!isset($displays[$display_id])) { - $displays[$display_id] = _update_8000_entity_get_display($record->entity_type, $record->bundle, $view_mode); - } - - // The display object does not store hidden fields. - if ($display_options['type'] != 'hidden') { - // We do not need the 'module' key anymore. - unset($display_options['module']); - $displays[$display_id]->set("content.$record->field_name", $display_options); - } - } - - // Remove the 'display' key and save the record back into the table. - unset($data['display']); - db_update('field_config_instance') - ->condition('id', $record->id) - ->fields(array( - 'data' => serialize($data), - )) - ->execute(); - } - - // Migration of 'extra_fields' display settings. Avoid calling - // entity_get_info() by fetching the relevant variables directly in the - // cariables table. - $variables = array_map('unserialize', db_query("SELECT name, value FROM {variable} WHERE name LIKE '%field_bundle_settings_%'")->fetchAllKeyed()); - foreach ($variables as $variable_name => $variable_value) { - if (preg_match('/field_bundle_settings_(.*)__(.*)/', $variable_name, $matches)) { - $entity_type = $matches[1]; - $bundle = $matches[2]; - if (isset($variable_value['extra_fields']['display'])) { - foreach ($variable_value['extra_fields']['display'] as $field_name => $field_settings) { - foreach ($field_settings as $view_mode => $display_options) { - // Determine name and create initial entry in the $displays array - // if it does not exist yet. - $display_id = $entity_type . '.' . $bundle . '.' . $view_mode; - if (!isset($displays[$display_id])) { - $displays[$display_id] = _update_8000_entity_get_display($entity_type, $bundle, $view_mode); - } - - // Set options in the display. - $new_options = array('visible' => $display_options['visible']); - // The display object only stores the weight for 'visible' extra - // fields. - if ($display_options['visible']) { - $new_options['weight'] = $display_options['weight']; - } - $displays[$display_id]->set("content.$field_name", $new_options); - - // Remove the old entry. - unset($variable_value['extra_fields']['display']); - variable_set($variable_name, $variable_value); - } - } - } - } - } - - // Save the displays to configuration. - foreach ($displays as $config) { - $config->save(); - } - update_config_manifest_add('entity.display', array_keys($displays)); -} - /** * @} End of "addtogroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ - diff --git a/core/modules/field/field.module b/core/modules/field/field.module index 01b012211a5..59340c3cdb7 100644 --- a/core/modules/field/field.module +++ b/core/modules/field/field.module @@ -682,6 +682,7 @@ function field_bundle_settings($entity_type, $bundle, $settings = NULL) { ); $settings['extra_fields'] += array( 'form' => array(), + 'display' => array(), ); return $settings; @@ -724,30 +725,39 @@ function field_view_mode_settings($entity_type, $bundle) { } /** - * Returns the display options to use for pseudo-fields in a given view mode. + * Returns the display settings to use for pseudo-fields in a given view mode. * - * @todo Remove when all steps in the view callstack receive the - * entity_display. - * - * @param $entity - * The entity. + * @param $entity_type + * The type of $entity; e.g., 'node' or 'user'. + * @param $bundle + * The bundle name. * @param $view_mode * The view mode. * * @return - * The display options to be used when viewing the entity's pseudo-fields in - * the view mode. + * The display settings to be used when viewing the bundle's pseudo-fields. */ -function field_extra_fields_get_display($entity, $view_mode) { - $entity_display = entity_get_render_display($entity, $view_mode); - $extra_fields = field_info_extra_fields($entity->entityType(), $entity->bundle(), 'display'); +function field_extra_fields_get_display($entity_type, $bundle, $view_mode) { + // Check whether the view mode uses custom display settings or the 'default' + // mode. + $view_mode_settings = field_view_mode_settings($entity_type, $bundle); + $actual_mode = (!empty($view_mode_settings[$view_mode]['custom_settings'])) ? $view_mode : 'default'; + $extra_fields = field_info_extra_fields($entity_type, $bundle, 'display'); - $options = array(); + $displays = array(); foreach ($extra_fields as $name => $value) { - $options[$name] = $entity_display->getComponent($name); + $displays[$name] = $extra_fields[$name]['display'][$actual_mode]; } - return $options; + // Let modules alter the display settings. + $context = array( + 'entity_type' => $entity_type, + 'bundle' => $bundle, + 'view_mode' => $view_mode, + ); + drupal_alter('field_extra_fields_display', $displays, $context); + + return $displays; } /** @@ -757,10 +767,23 @@ function _field_extra_fields_pre_render($elements) { $entity_type = $elements['#entity_type']; $bundle = $elements['#bundle']; - $extra_fields = field_info_extra_fields($entity_type, $bundle, 'form'); - foreach ($extra_fields as $name => $settings) { - if (isset($elements[$name])) { - $elements[$name]['#weight'] = $settings['weight']; + if (isset($elements['#type']) && $elements['#type'] == 'form') { + $extra_fields = field_info_extra_fields($entity_type, $bundle, 'form'); + foreach ($extra_fields as $name => $settings) { + if (isset($elements[$name])) { + $elements[$name]['#weight'] = $settings['weight']; + } + } + } + elseif (isset($elements['#view_mode'])) { + $view_mode = $elements['#view_mode']; + $extra_fields = field_extra_fields_get_display($entity_type, $bundle, $view_mode); + foreach ($extra_fields as $name => $settings) { + if (isset($elements[$name])) { + $elements[$name]['#weight'] = $settings['weight']; + // Visibility: make sure we do not accidentally show a hidden element. + $elements[$name]['#access'] = isset($elements[$name]['#access']) ? ($elements[$name]['#access'] && $settings['visible']) : $settings['visible']; + } } } @@ -879,14 +902,15 @@ function field_view_value($entity_type, $entity, $field_name, $item, $display = * key and the field data to display. * @param $field_name * The name of the field to display. - * @param $display_options + * @param $display * 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: + * - An array of display settings, as found in the 'display' entry of + * $instance definitions. 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'. @@ -909,70 +933,51 @@ function field_view_value($entity_type, $entity, $field_name, $item, $display = * * @see field_view_value() */ -function field_view_field($entity_type, $entity, $field_name, $display_options = array(), $langcode = NULL) { +function field_view_field($entity_type, $entity, $field_name, $display = array(), $langcode = NULL) { $output = array(); - $bundle = $entity->bundle(); - // Return nothing if the field doesn't exist. - $instance = field_info_instance($entity_type, $field_name, $bundle); - if (!$instance) { - return $output; - } - - // Get the formatter object. - if (is_string($display_options)) { - $view_mode = $display_options; - $formatter = entity_get_render_display($entity, $view_mode)->getFormatter($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. - $field = field_info_field($field_name); - $formatter_manager = drupal_container()->get('plugin.manager.field.formatter'); - $display_options = $formatter_manager->prepareConfiguration($field['type'], $display_options); - $formatter = $formatter_manager->getInstance(array( - 'instance' => $instance, - 'view_mode' => $view_mode, - 'prepare' => FALSE, - 'configuration' => $display_options, - )); - } - - if ($formatter) { - $display_langcode = field_language($entity_type, $entity, $field_name, $langcode); - $items = $entity->{$field_name}[$display_langcode]; - - // Invoke prepare_view steps if needed. - if (empty($entity->_field_view_prepared)) { - $id = $entity->id(); - - // First let the field types do their preparation. - $options = array('field_name' => $field_name, 'langcode' => $display_langcode); - $null = NULL; - _field_invoke_multiple('prepare_view', $entity_type, array($id => $entity), $null, $null, $options); - - // Then let the formatter do its own specific massaging. - $items_multi = array($id => $entity->{$field_name}[$display_langcode]); - $formatter->prepareView(array($id => $entity), $display_langcode, $items_multi); - $items = $items_multi[$id]; + if ($instance = field_info_instance($entity_type, $field_name, $entity->bundle())) { + if (is_array($display) && empty($display['type'])) { + $field = field_info_field($instance['field_name']); + $field_type_info = field_info_field_types($field['type']); + $display['type'] = $field_type_info['default_formatter']; } + if ($formatter = $instance->getFormatter($display)) { + $display_langcode = field_language($entity_type, $entity, $field_name, $langcode); + $items = $entity->{$field_name}[$display_langcode]; - // Build the renderable array. - $result = $formatter->view($entity, $display_langcode, $items); + // Invoke prepare_view steps if needed. + if (empty($entity->_field_view_prepared)) { + $id = $entity->id(); - // 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_type' => $entity_type, - 'entity' => $entity, - 'view_mode' => $view_mode, - 'display_options' => $display_options, - ); - drupal_alter('field_attach_view', $result, $context); + // First let the field types do their preparation. + // @todo invoke hook_field_prepare_view() directly ? + $options = array('field_name' => $field_name, 'langcode' => $display_langcode); + $null = NULL; + _field_invoke_multiple('prepare_view', $entity_type, array($id => $entity), $display, $null, $options); - if (isset($result[$field_name])) { - $output = $result[$field_name]; + // Then let the formatters do their own specific massaging. + $items_multi = array($id => $entity->{$field_name}[$display_langcode]); + $formatter->prepareView(array($id => $entity), $display_langcode, $items_multi); + $items = $items_multi[$id]; + } + + // Build the renderable array. + $result = $formatter->view($entity, $display_langcode, $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_type' => $entity_type, + 'entity' => $entity, + 'view_mode' => '_custom', + 'display' => $display, + ); + drupal_alter('field_attach_view', $result, $context); + + if (isset($result[$field_name])) { + $output = $result[$field_name]; + } } } diff --git a/core/modules/field/lib/Drupal/field/FieldInfo.php b/core/modules/field/lib/Drupal/field/FieldInfo.php index 7ff68500199..65fce2192e4 100644 --- a/core/modules/field/lib/Drupal/field/FieldInfo.php +++ b/core/modules/field/lib/Drupal/field/FieldInfo.php @@ -549,7 +549,25 @@ class FieldInfo { } // Extra fields in displayed entities. - $result['display'] = $extra_fields['display']; + $data = $extra_fields['display']; + foreach ($extra_fields['display'] as $name => $field_data) { + $settings = isset($bundle_settings['extra_fields']['display'][$name]) ? $bundle_settings['extra_fields']['display'][$name] : array(); + $view_modes = array_merge(array('default'), array_keys($entity_type_info['view_modes'])); + foreach ($view_modes as $view_mode) { + if (isset($settings[$view_mode])) { + $field_data['display'][$view_mode] = $settings[$view_mode]; + } + else { + $field_data['display'][$view_mode] = array( + 'weight' => $field_data['weight'], + 'visible' => isset($field_data['visible']) ? $field_data['visible'] : TRUE, + ); + } + } + unset($field_data['weight']); + unset($field_data['visible']); + $result['display'][$name] = $field_data; + } return $result; } diff --git a/core/modules/field/lib/Drupal/field/FieldInstance.php b/core/modules/field/lib/Drupal/field/FieldInstance.php index ba6ea44b3a0..a1e7a4fdc0f 100644 --- a/core/modules/field/lib/Drupal/field/FieldInstance.php +++ b/core/modules/field/lib/Drupal/field/FieldInstance.php @@ -26,6 +26,13 @@ class FieldInstance implements \ArrayAccess { */ protected $widget; + /** + * The formatter objects used for this instance, keyed by view mode. + * + * @var array + */ + protected $formatters; + /** * Constructs a FieldInstance object. * @@ -67,6 +74,88 @@ class FieldInstance implements \ArrayAccess { return $this->widget; } + /** + * Returns a Formatter plugin for the instance. + * + * @param mixed $display_properties + * Can be either: + * - The name of a view mode. + * - An array of display properties, as found in the 'display' entry of + * $instance definitions. + * + * @return Drupal\field\Plugin\Type\Formatter\FormatterInterface|null + * The Formatter plugin to be used for the instance, or NULL if the field + * is hidden. + */ + public function getFormatter($display_properties) { + if (is_string($display_properties)) { + // A view mode was provided. Switch to 'default' if the view mode is not + // configured to use dedicated settings. + $view_mode = $display_properties; + $view_mode_settings = field_view_mode_settings($this->definition['entity_type'], $this->definition['bundle']); + $actual_mode = (!empty($view_mode_settings[$view_mode]['custom_settings']) ? $view_mode : 'default'); + + if (isset($this->formatters[$actual_mode])) { + return $this->formatters[$actual_mode]; + } + + // Switch to 'hidden' if the instance has no properties for the view + // mode. + if (isset($this->definition['display'][$actual_mode])) { + $display_properties = $this->definition['display'][$actual_mode]; + } + else { + $display_properties = array( + 'type' => 'hidden', + 'settings' => array(), + 'label' => 'above', + 'weight' => 0, + ); + } + + // Let modules alter the widget properties. + $context = array( + 'entity_type' => $this->definition['entity_type'], + 'bundle' => $this->definition['bundle'], + 'field' => field_info_field($this->definition['field_name']), + 'instance' => $this, + 'view_mode' => $view_mode, + ); + drupal_alter(array('field_display', 'field_display_' . $this->definition['entity_type']), $display_properties, $context); + } + else { + // Arbitrary display settings. Make sure defaults are present. + $display_properties += array( + 'settings' => array(), + 'label' => 'above', + 'weight' => 0, + ); + $view_mode = '_custom_display'; + } + + if (!empty($display_properties['type']) && $display_properties['type'] != 'hidden') { + $options = array( + 'instance' => $this, + 'type' => $display_properties['type'], + 'settings' => $display_properties['settings'], + 'label' => $display_properties['label'], + 'weight' => $display_properties['weight'], + 'view_mode' => $view_mode, + ); + $formatter = drupal_container()->get('plugin.manager.field.formatter')->getInstance($options); + } + else { + $formatter = NULL; + } + + // Persist the object if we were not passed custom display settings. + if (isset($actual_mode)) { + $this->formatters[$actual_mode] = $formatter; + } + + return $formatter; + } + /** * Implements ArrayAccess::offsetExists(). */ @@ -96,6 +185,9 @@ class FieldInstance implements \ArrayAccess { if ($offset == 'widget') { unset($this->widget); } + if ($offset == 'display') { + unset($this->formatters); + } } /** @@ -109,6 +201,9 @@ class FieldInstance implements \ArrayAccess { if ($offset == 'widget') { unset($this->widget); } + if ($offset == 'display') { + unset($this->formatters); + } } /** diff --git a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php index 939df9ceae8..55d0e3fc008 100644 --- a/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php +++ b/core/modules/field/lib/Drupal/field/Plugin/Type/Formatter/FormatterPluginManager.php @@ -11,9 +11,8 @@ use Drupal\Component\Plugin\PluginManagerBase; use Drupal\Component\Plugin\Discovery\ProcessDecorator; use Drupal\Core\Plugin\Discovery\CacheDecorator; use Drupal\Core\Plugin\Discovery\AnnotatedClassDiscovery; -use Drupal\Core\Plugin\Discovery\AlterDecorator; use Drupal\field\Plugin\Type\Formatter\FormatterLegacyDiscoveryDecorator; -use Drupal\field\FieldInstance; +use Drupal\Core\Plugin\Discovery\AlterDecorator; /** * Plugin type manager for field formatters. @@ -43,87 +42,31 @@ class FormatterPluginManager extends PluginManagerBase { /** * Overrides PluginManagerBase::getInstance(). - * - * @param array $options - * An array with the following key/value pairs: - * - instance: (FieldInstance) The field instance. - * - view_mode: (string) The view mode. - * - prepare: (bool, optional) Whether default values should get merged in - * the 'configuration' array. Defaults to TRUE. - * - configuration: (array) the configuration for the formatter. The - * following key value pairs are allowed, and are all optional if - * 'prepare' is TRUE: - * - 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, specified in - * hook_field_info(). The default formatter will also be used if the - * requested formatter is not available. - * - settings: (array) Settings specific to the formatter. Each setting - * defaults to the default value specified in the formatter definition. - * - weight: (float) The weight to assign to the renderable element. - * Defaults to 0. - * - * @return \Drupal\field\Plugin\Type\Formatter\FormatterInterface - * A formatter object. */ public function getInstance(array $options) { - $configuration = $options['configuration']; $instance = $options['instance']; + $type = $options['type']; + + $definition = $this->getDefinition($type); $field = field_info_field($instance['field_name']); - // Fill in default configuration if needed. - if (!isset($options['prepare']) || $options['prepare'] == TRUE) { - $configuration = $this->prepareConfiguration($field['type'], $configuration); - } - - $plugin_id = $configuration['type']; - // Switch back to default formatter if either: // - $type_info doesn't exist (the widget type is unknown), // - the field type is not allowed for the widget. - $definition = $this->getDefinition($configuration['type']); if (!isset($definition['class']) || !in_array($field['type'], $definition['field_types'])) { // Grab the default widget for the field type. $field_type_definition = field_info_field_types($field['type']); - $plugin_id = $field_type_definition['default_formatter']; + $type = $field_type_definition['default_formatter']; } - $configuration += array( + $configuration = array( 'instance' => $instance, + 'settings' => $options['settings'], + 'weight' => $options['weight'], + 'label' => $options['label'], 'view_mode' => $options['view_mode'], ); - return $this->createInstance($plugin_id, $configuration); - } - - /** - * Merges default values for formatter configuration. - * - * @param string $field_type - * The field type. - * @param array $properties - * An array of formatter configuration. - * - * @return array - * The display properties with defaults added. - */ - public function prepareConfiguration($field_type, array $configuration) { - // Fill in defaults for missing properties. - $configuration += array( - 'label' => 'above', - 'settings' => array(), - 'weight' => 0, - ); - // If no formatter is specified, use the default formatter. - if (!isset($configuration['type'])) { - $field_type = field_info_field_types($field_type); - $configuration['type'] = $field_type['default_formatter']; - } - // Fill in default settings values for the formatter. - $configuration['settings'] += field_info_formatter_settings($configuration['type']); - - return $configuration; + return $this->createInstance($type, $configuration); } } diff --git a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php index 32f91fd1d9e..1c8f166aebf 100644 --- a/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/DisplayApiTest.php @@ -42,33 +42,23 @@ class DisplayApiTest extends FieldTestBase { 'entity_type' => 'test_entity', 'bundle' => 'test_bundle', 'label' => $this->label, - ); - - $this->display_options = array( - 'default' => array( - 'type' => 'field_test_default', - 'settings' => array( - 'test_formatter_setting' => $this->randomName(), + 'display' => array( + 'default' => array( + 'type' => 'field_test_default', + 'settings' => array( + 'test_formatter_setting' => $this->randomName(), + ), ), - ), - 'teaser' => array( - 'type' => 'field_test_default', - 'settings' => array( - 'test_formatter_setting' => $this->randomName(), + 'teaser' => array( + 'type' => 'field_test_default', + 'settings' => array( + 'test_formatter_setting' => $this->randomName(), + ), ), ), ); - field_create_field($this->field); field_create_instance($this->instance); - // Create a display for the default view mode. - entity_get_display($this->instance['entity_type'], $this->instance['bundle'], 'default') - ->setComponent($this->field_name, $this->display_options['default']) - ->save(); - // Create a display for the teaser view mode. - entity_get_display($this->instance['entity_type'], $this->instance['bundle'], 'teaser') - ->setComponent($this->field_name, $this->display_options['teaser']) - ->save(); // Create an entity with values. $this->values = $this->_generateTestFieldValues($this->cardinality); @@ -130,11 +120,11 @@ class DisplayApiTest extends FieldTestBase { $this->assertText($setting . '|' . $value['value'] . '|' . ($value['value'] + 1), format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); } - // View mode: check that display settings specified in the display object - // are used. + // View mode: check that display settings specified in the instance are + // used. $output = field_view_field('test_entity', $this->entity, $this->field_name, 'teaser'); $this->drupalSetContent(drupal_render($output)); - $setting = $this->display_options['teaser']['settings']['test_formatter_setting']; + $setting = $this->instance['display']['teaser']['settings']['test_formatter_setting']; $this->assertText($this->label, 'Label was displayed.'); foreach ($this->values as $delta => $value) { $this->assertText($setting . '|' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); @@ -144,7 +134,7 @@ class DisplayApiTest extends FieldTestBase { // are used. $output = field_view_field('test_entity', $this->entity, $this->field_name, 'unknown_view_mode'); $this->drupalSetContent(drupal_render($output)); - $setting = $this->display_options['default']['settings']['test_formatter_setting']; + $setting = $this->instance['display']['default']['settings']['test_formatter_setting']; $this->assertText($this->label, 'Label was displayed.'); foreach ($this->values as $delta => $value) { $this->assertText($setting . '|' . $value['value'], format_string('Value @delta was displayed with expected setting.', array('@delta' => $delta))); @@ -199,7 +189,7 @@ class DisplayApiTest extends FieldTestBase { // View mode: check that display settings specified in the instance are // used. - $setting = $this->display_options['teaser']['settings']['test_formatter_setting']; + $setting = $this->instance['display']['teaser']['settings']['test_formatter_setting']; foreach ($this->values as $delta => $value) { $item = $this->entity->{$this->field_name}[LANGUAGE_NOT_SPECIFIED][$delta]; $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, 'teaser'); @@ -209,7 +199,7 @@ class DisplayApiTest extends FieldTestBase { // Unknown view mode: check that display settings for 'default' view mode // are used. - $setting = $this->display_options['default']['settings']['test_formatter_setting']; + $setting = $this->instance['display']['default']['settings']['test_formatter_setting']; foreach ($this->values as $delta => $value) { $item = $this->entity->{$this->field_name}[LANGUAGE_NOT_SPECIFIED][$delta]; $output = field_view_value('test_entity', $this->entity, $this->field_name, $item, 'unknown_view_mode'); diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php index bc1a3805516..7f8788714dd 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAccessTest.php @@ -49,16 +49,14 @@ class FieldAccessTest extends FieldTestBase { 'widget' => array( 'type' => 'text_textfield', ), + 'display' => array( + 'default' => array( + 'type' => 'text_default', + ), + ), ); field_create_instance($this->instance); - // Assign display properties for the 'default' and 'teaser' view modes. - foreach (array('default', 'teaser') as $view_mode) { - entity_get_display('node', $this->content_type, $view_mode) - ->setComponent($this->field['field_name']) - ->save(); - } - // Create test node. $this->test_view_field_value = 'This is some text'; $settings = array(); diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php index 5f8ad5dc278..f971099b975 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldAttachOtherTest.php @@ -40,32 +40,31 @@ class FieldAttachOtherTest extends FieldAttachTestBase { // Simple formatter, label displayed. $entity = clone($entity_init); - $display = entity_get_display($entity_type, $entity->bundle(), 'full'); - $displays = array($entity->bundle() => $display); - $formatter_setting = $this->randomName(); - $display_options = array( - 'label' => 'above', - 'type' => 'field_test_default', - 'settings' => array( - 'test_formatter_setting' => $formatter_setting, + $this->instance['display'] = array( + 'full' => array( + 'label' => 'above', + 'type' => 'field_test_default', + 'settings' => array( + 'test_formatter_setting' => $formatter_setting, + ) ), ); - $display->setComponent($this->field['field_name'], $display_options); - + field_update_instance($this->instance); $formatter_setting_2 = $this->randomName(); - $display_options_2 = array( - 'label' => 'above', - 'type' => 'field_test_default', - 'settings' => array( - 'test_formatter_setting' => $formatter_setting_2, + $this->instance_2['display'] = array( + 'full' => array( + 'label' => 'above', + 'type' => 'field_test_default', + 'settings' => array( + 'test_formatter_setting' => $formatter_setting_2, + ) ), ); - $display->setComponent($this->field_2['field_name'], $display_options_2); - + field_update_instance($this->instance_2); // View all fields. - field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays); - $entity->content = field_attach_view($entity_type, $entity, $display); + field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full'); + $entity->content = field_attach_view($entity_type, $entity, 'full'); $output = drupal_render($entity->content); $this->content = $output; $this->assertRaw($this->instance['label'], "First field's label is displayed."); @@ -79,8 +78,8 @@ class FieldAttachOtherTest extends FieldAttachTestBase { $this->assertRaw("$formatter_setting_2|{$value['value']}", "Value $delta is displayed, formatter settings are applied."); } // View single field (the second field). - field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays, $langcode, $options); - $entity->content = field_attach_view($entity_type, $entity, $display, $langcode, $options); + field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full', $langcode, $options); + $entity->content = field_attach_view($entity_type, $entity, 'full', $langcode, $options); $output = drupal_render($entity->content); $this->content = $output; $this->assertNoRaw($this->instance['label'], "First field's label is not displayed."); @@ -96,19 +95,25 @@ class FieldAttachOtherTest extends FieldAttachTestBase { // Label hidden. $entity = clone($entity_init); - $display_options['label'] = 'hidden'; - $display->setComponent($this->field['field_name'], $display_options); - field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays); - $entity->content = field_attach_view($entity_type, $entity, $display); + $this->instance['display']['full']['label'] = 'hidden'; + field_update_instance($this->instance); + field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full'); + $entity->content = field_attach_view($entity_type, $entity, 'full'); $output = drupal_render($entity->content); $this->content = $output; $this->assertNoRaw($this->instance['label'], "Hidden label: label is not displayed."); // Field hidden. $entity = clone($entity_init); - $display->removeComponent($this->field['field_name']); - field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays); - $entity->content = field_attach_view($entity_type, $entity, $display); + $this->instance['display'] = array( + 'full' => array( + 'label' => 'above', + 'type' => 'hidden', + ), + ); + field_update_instance($this->instance); + field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full'); + $entity->content = field_attach_view($entity_type, $entity, 'full'); $output = drupal_render($entity->content); $this->content = $output; $this->assertNoRaw($this->instance['label'], "Hidden field: label is not displayed."); @@ -119,38 +124,45 @@ class FieldAttachOtherTest extends FieldAttachTestBase { // Multiple formatter. $entity = clone($entity_init); $formatter_setting = $this->randomName(); - $display->setComponent($this->field['field_name'], array( - 'label' => 'above', - 'type' => 'field_test_multiple', - 'settings' => array( - 'test_formatter_setting_multiple' => $formatter_setting, + $this->instance['display'] = array( + 'full' => array( + 'label' => 'above', + 'type' => 'field_test_multiple', + 'settings' => array( + 'test_formatter_setting_multiple' => $formatter_setting, + ) ), - )); - field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays); - $entity->content = field_attach_view($entity_type, $entity, $display); + ); + field_update_instance($this->instance); + field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full'); + $entity->content = field_attach_view($entity_type, $entity, 'full'); $output = drupal_render($entity->content); - $expected_output = $formatter_setting; + $display = $formatter_setting; foreach ($values as $delta => $value) { - $expected_output .= "|$delta:{$value['value']}"; + $display .= "|$delta:{$value['value']}"; } $this->content = $output; - $this->assertRaw($expected_output, "Multiple formatter: all values are displayed, formatter settings are applied."); + $this->assertRaw($display, "Multiple formatter: all values are displayed, formatter settings are applied."); // Test a formatter that uses hook_field_formatter_prepare_view(). $entity = clone($entity_init); $formatter_setting = $this->randomName(); - $display->setComponent($this->field['field_name'], array( - 'label' => 'above', - 'type' => 'field_test_with_prepare_view', - 'settings' => array( - 'test_formatter_setting_additional' => $formatter_setting, + $this->instance['display'] = array( + 'full' => array( + 'label' => 'above', + 'type' => 'field_test_with_prepare_view', + 'settings' => array( + 'test_formatter_setting_additional' => $formatter_setting, + ) ), - )); - field_attach_prepare_view($entity_type, array($entity->ftid => $entity), $displays); - $entity->content = field_attach_view($entity_type, $entity, $display); + ); + field_update_instance($this->instance); + field_attach_prepare_view($entity_type, array($entity->ftid => $entity), 'full'); + $entity->content = field_attach_view($entity_type, $entity, 'full'); $output = drupal_render($entity->content); $this->content = $output; foreach ($values as $delta => $value) { + $this->content = $output; $expected = $formatter_setting . '|' . $value['value'] . '|' . ($value['value'] + 1); $this->assertRaw($expected, "Value $delta is displayed, formatter settings are applied."); } @@ -179,8 +191,8 @@ class FieldAttachOtherTest extends FieldAttachTestBase { $langcode = LANGUAGE_NOT_SPECIFIED; // Set the instance to be hidden. - $display = entity_get_display('test_entity', 'test_bundle', 'full') - ->removeComponent($this->field['field_name']); + $this->instance['display']['full']['type'] = 'hidden'; + field_update_instance($this->instance); // Set up a second instance on another bundle, with a formatter that uses // hook_field_formatter_prepare_view(). @@ -188,18 +200,14 @@ class FieldAttachOtherTest extends FieldAttachTestBase { $formatter_setting = $this->randomName(); $this->instance2 = $this->instance; $this->instance2['bundle'] = 'test_bundle_2'; + $this->instance2['display']['full'] = array( + 'type' => 'field_test_with_prepare_view', + 'settings' => array( + 'test_formatter_setting_additional' => $formatter_setting, + ) + ); field_create_instance($this->instance2); - $display_2 = entity_get_display('test_entity', 'test_bundle_2', 'full') - ->setComponent($this->field['field_name'], array( - 'type' => 'field_test_with_prepare_view', - 'settings' => array( - 'test_formatter_setting_additional' => $formatter_setting, - ), - )); - - $displays = array('test_bundle' => $display, 'test_bundle_2' => $display_2); - // Create one entity in each bundle. $entity1_init = field_test_create_entity(1, 1, 'test_bundle'); $values1 = $this->_generateTestFieldValues($this->field['cardinality']); @@ -212,16 +220,14 @@ class FieldAttachOtherTest extends FieldAttachTestBase { // Run prepare_view, and check that the entities come out as expected. $entity1 = clone($entity1_init); $entity2 = clone($entity2_init); - $entities = array($entity1->ftid => $entity1, $entity2->ftid => $entity2); - field_attach_prepare_view($entity_type, $entities, $displays); + field_attach_prepare_view($entity_type, array($entity1->ftid => $entity1, $entity2->ftid => $entity2), 'full'); $this->assertFalse(isset($entity1->{$this->field_name}[$langcode][0]['additional_formatter_value']), 'Entity 1 did not run through the prepare_view hook.'); $this->assertTrue(isset($entity2->{$this->field_name}[$langcode][0]['additional_formatter_value']), 'Entity 2 ran through the prepare_view hook.'); // Same thing, reversed order. $entity1 = clone($entity1_init); $entity2 = clone($entity2_init); - $entities = array($entity1->ftid => $entity1, $entity2->ftid => $entity2); - field_attach_prepare_view($entity_type, $entities, $displays); + field_attach_prepare_view($entity_type, array($entity2->ftid => $entity2, $entity1->ftid => $entity1), 'full'); $this->assertFalse(isset($entity1->{$this->field_name}[$langcode][0]['additional_formatter_value']), 'Entity 1 did not run through the prepare_view hook.'); $this->assertTrue(isset($entity2->{$this->field_name}[$langcode][0]['additional_formatter_value']), 'Entity 2 ran through the prepare_view hook.'); } diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php index 3115851b950..323b8e81336 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldInfoTest.php @@ -178,13 +178,15 @@ class FieldInfoTest extends FieldTestBase { field_create_instance($instance_definition); // Simulate a stored instance definition missing various settings (e.g. a - // third-party module adding instance or widget settings has been enabled, - // but existing instances do not know the new settings). + // third-party module adding instance, widget or display settings has been + // enabled, but existing instances do not know the new settings). $data = db_query('SELECT data FROM {field_config_instance} WHERE field_name = :field_name AND bundle = :bundle', array(':field_name' => $instance_definition['field_name'], ':bundle' => $instance_definition['bundle']))->fetchField(); $data = unserialize($data); $data['settings'] = array(); $data['widget']['settings'] = 'unavailable_widget'; $data['widget']['settings'] = array(); + $data['display']['default']['type'] = 'unavailable_formatter'; + $data['display']['default']['settings'] = array(); db_update('field_config_instance') ->fields(array('data' => serialize($data))) ->condition('field_name', $instance_definition['field_name']) @@ -205,6 +207,13 @@ class FieldInfoTest extends FieldTestBase { $this->assertIdentical($widget->getPluginId(), $field_type['default_widget'], 'Unavailable widget replaced with default widget.'); $widget_type = $widget->getDefinition(); $this->assertIdentical($widget->getSettings(), $widget_type['settings'] , 'All expected widget settings are present.'); + + // Check that display settings are set for the 'default' mode. + $formatter = $instance->getFormatter('default'); + $this->assertIdentical($formatter->getPluginId(), $field_type['default_formatter'], "Formatter is set for the 'default' view mode"); + $formatter_type = $formatter->getDefinition(); + $this->assertIdentical($formatter->getSettings(), $formatter_type['settings'] , "Formatter settings are set for the 'default' view mode"); + } /** diff --git a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php index 90fcc051080..84cee726f93 100644 --- a/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php +++ b/core/modules/field/lib/Drupal/field/Tests/FieldInstanceCrudTest.php @@ -62,6 +62,7 @@ class FieldInstanceCrudTest extends FieldTestBase { $field_type = field_info_field_types($this->field['type']); $widget_type = field_info_widget_types($field_type['default_widget']); + $formatter_type = field_info_formatter_types($field_type['default_formatter']); // Check that the ID key is filled in. $this->assertIdentical($record['id'], $this->instance_definition['id'], 'The instance id is filled in'); @@ -71,10 +72,13 @@ class FieldInstanceCrudTest extends FieldTestBase { $this->assertIdentical($record['data']['label'], $this->instance_definition['field_name'], 'Label defaults to field name.'); $this->assertIdentical($record['data']['description'], '', 'Description defaults to empty string.'); $this->assertIdentical($record['data']['widget']['type'], $field_type['default_widget'], 'Default widget has been written.'); + $this->assertTrue(isset($record['data']['display']['default']), 'Display for "full" view_mode has been written.'); + $this->assertIdentical($record['data']['display']['default']['type'], $field_type['default_formatter'], 'Default formatter for "full" view_mode has been written.'); // Check that default settings are set. $this->assertIdentical($record['data']['settings'], $field_type['instance_settings'] , 'Default instance settings have been written.'); $this->assertIdentical($record['data']['widget']['settings'], $widget_type['settings'] , 'Default widget settings have been written.'); + $this->assertIdentical($record['data']['display']['default']['settings'], $formatter_type['settings'], 'Default formatter settings for "full" view_mode have been written.'); // Guarantee that the field/bundle combination is unique. try { @@ -147,6 +151,7 @@ class FieldInstanceCrudTest extends FieldTestBase { */ function testUpdateFieldInstance() { field_create_instance($this->instance_definition); + $field_type = field_info_field_types($this->field['type']); // Check that basic changes are saved. $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); @@ -156,6 +161,8 @@ class FieldInstanceCrudTest extends FieldTestBase { $instance['settings']['test_instance_setting'] = $this->randomName(); $instance['widget']['settings']['test_widget_setting'] =$this->randomName(); $instance['widget']['weight']++; + $instance['display']['default']['settings']['test_formatter_setting'] = $this->randomName(); + $instance['display']['default']['weight']++; field_update_instance($instance); $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); @@ -164,16 +171,35 @@ class FieldInstanceCrudTest extends FieldTestBase { $this->assertEqual($instance['description'], $instance_new['description'], '"description" change is saved'); $this->assertEqual($instance['widget']['settings']['test_widget_setting'], $instance_new['widget']['settings']['test_widget_setting'], 'Widget setting change is saved'); $this->assertEqual($instance['widget']['weight'], $instance_new['widget']['weight'], 'Widget weight change is saved'); + $this->assertEqual($instance['display']['default']['settings']['test_formatter_setting'], $instance_new['display']['default']['settings']['test_formatter_setting'], 'Formatter setting change is saved'); + $this->assertEqual($instance['display']['default']['weight'], $instance_new['display']['default']['weight'], 'Widget weight change is saved'); - // Check that changing the widget type updates the default settings. + // Check that changing widget and formatter types updates the default settings. $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); $instance['widget']['type'] = 'test_field_widget_multiple'; + $instance['display']['default']['type'] = 'field_test_multiple'; field_update_instance($instance); $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); $this->assertEqual($instance['widget']['type'], $instance_new['widget']['type'] , 'Widget type change is saved.'); $settings = field_info_widget_settings($instance_new['widget']['type']); $this->assertIdentical($settings, array_intersect_key($instance_new['widget']['settings'], $settings) , 'Widget type change updates default settings.'); + $this->assertEqual($instance['display']['default']['type'], $instance_new['display']['default']['type'] , 'Formatter type change is saved.'); + $info = field_info_formatter_types($instance_new['display']['default']['type']); + $settings = $info['settings']; + $this->assertIdentical($settings, array_intersect_key($instance_new['display']['default']['settings'], $settings) , 'Changing formatter type updates default settings.'); + + // Check that adding a new view mode is saved and gets default settings. + $instance = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); + $instance['display']['teaser'] = array(); + field_update_instance($instance); + + $instance_new = field_read_instance('test_entity', $this->instance_definition['field_name'], $this->instance_definition['bundle']); + $this->assertTrue(isset($instance_new['display']['teaser']), 'Display for the new view_mode has been written.'); + $this->assertIdentical($instance_new['display']['teaser']['type'], $field_type['default_formatter'], 'Default formatter for the new view_mode has been written.'); + $info = field_info_formatter_types($instance_new['display']['teaser']['type']); + $settings = $info['settings']; + $this->assertIdentical($settings, $instance_new['display']['teaser']['settings'] , 'Default formatter settings for the new view_mode have been written.'); // TODO: test failures. } diff --git a/core/modules/field/tests/modules/field_test/field_test.module b/core/modules/field/tests/modules/field_test/field_test.module index 47d61b17421..5b8242f5d92 100644 --- a/core/modules/field/tests/modules/field_test/field_test.module +++ b/core/modules/field/tests/modules/field_test/field_test.module @@ -206,7 +206,7 @@ function field_test_entity_label_callback($entity_type, $entity, $langcode = NUL * Implements hook_field_attach_view_alter(). */ function field_test_field_attach_view_alter(&$output, $context) { - if (!empty($context['display_options']['settings']['alter'])) { + if (!empty($context['display']['settings']['alter'])) { $output['test_field'][] = array('#markup' => 'field_test_field_attach_view_alter'); } } diff --git a/core/modules/field_ui/field_ui.admin.inc b/core/modules/field_ui/field_ui.admin.inc index 27dad1e1e12..00cb8de5c8b 100644 --- a/core/modules/field_ui/field_ui.admin.inc +++ b/core/modules/field_ui/field_ui.admin.inc @@ -373,6 +373,51 @@ function field_ui_display_overview($entity_type, $bundle, $view_mode) { return drupal_build_form('field_ui_display_overview_form', $form_state); } +/** + * Populates display settings for a new view mode from the default view mode. + * + * When an administrator decides to use custom display settings for a view mode, + * that view mode needs to be initialized with the display settings for the + * 'default' view mode, which it was previously using. This helper function + * adds the new custom display settings to this bundle's instances, and saves + * them. It also modifies the passed-in $settings array, which the caller can + * then save using field_bundle_settings(). + * + * @param $entity_type + * The bundle's entity type. + * @param $bundle + * The bundle whose view mode is being customized. + * @param $view_mode + * The view mode that the administrator has set to use custom settings. + * @param $settings + * An associative array of bundle settings, as expected by + * field_bundle_settings(). + * + * @see Drupal\field_ui\DisplayOverview::submit(). + * @see field_bundle_settings() + */ +function _field_ui_add_default_view_mode_settings($entity_type, $bundle, $view_mode, &$settings) { + // Update display settings for field instances. + $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle)); + foreach ($instances as $instance) { + // If this field instance has display settings defined for this view mode, + // respect those settings. + if (!isset($instance['display'][$view_mode])) { + // The instance doesn't specify anything for this view mode, so use the + // default display settings. + $instance['display'][$view_mode] = $instance['display']['default']; + field_update_instance($instance); + } + } + + // Update display settings for 'extra fields'. + foreach (array_keys($settings['extra_fields']['display']) as $name) { + if (!isset($settings['extra_fields']['display'][$name][$view_mode])) { + $settings['extra_fields']['display'][$name][$view_mode] = $settings['extra_fields']['display'][$name]['default']; + } + } +} + /** * Returns an array of field_type options. */ diff --git a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php index 0a86f78a296..6117de97a5c 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/DisplayOverview.php @@ -49,7 +49,6 @@ class DisplayOverview extends OverviewBase { $instances = field_info_instances($this->entity_type, $this->bundle); $field_types = field_info_field_types(); $extra_fields = field_info_extra_fields($this->entity_type, $this->bundle, 'display'); - $entity_display = entity_get_display($this->entity_type, $this->bundle, $this->view_mode); $form_state += array( 'formatter_settings_edit' => NULL, @@ -95,14 +94,24 @@ class DisplayOverview extends OverviewBase { 'hidden' => t(''), ); $extra_visibility_options = array( - 'visible' => t('Visible'), + 'content' => t('Visible'), 'hidden' => t('Hidden'), ); // Field rows. foreach ($instances as $name => $instance) { - $field = field_info_field($name); - $display_options = $entity_display->getComponent($name); + $field = field_info_field($instance['field_name']); + + if (isset($instance['display'][$this->view_mode])) { + $display = $instance['display'][$this->view_mode]; + } + else { + $display = array( + 'type' => 'hidden', + 'label' => 'above', + 'weight' => 0, + ); + } $table[$name] = array( '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), @@ -119,7 +128,7 @@ class DisplayOverview extends OverviewBase { '#type' => 'textfield', '#title' => t('Weight for @title', array('@title' => $instance['label'])), '#title_display' => 'invisible', - '#default_value' => $display_options ? $display_options['weight'] : '0', + '#default_value' => $display['weight'], '#size' => 3, '#attributes' => array('class' => array('field-weight')), ), @@ -144,7 +153,7 @@ class DisplayOverview extends OverviewBase { '#title' => t('Label display for @title', array('@title' => $instance['label'])), '#title_display' => 'invisible', '#options' => $field_label_options, - '#default_value' => $display_options ? $display_options['label'] : 'above', + '#default_value' => $display['label'], ), ); @@ -156,7 +165,7 @@ class DisplayOverview extends OverviewBase { '#title' => t('Formatter for @title', array('@title' => $instance['label'])), '#title_display' => 'invisible', '#options' => $formatter_options, - '#default_value' => $display_options ? $display_options['type'] : 'hidden', + '#default_value' => $display['type'], '#parents' => array('fields', $name, 'type'), '#attributes' => array('class' => array('field-formatter-type')), ), @@ -166,23 +175,12 @@ class DisplayOverview extends OverviewBase { // Check the currently selected formatter, and merge persisted values for // formatter settings. if (isset($form_state['values']['fields'][$name]['type'])) { - $display_options['type'] = $form_state['values']['fields'][$name]['type']; + $display['type'] = $form_state['values']['fields'][$name]['type']; } if (isset($form_state['formatter_settings'][$name])) { - $display_options['settings'] = $form_state['formatter_settings'][$name]; - } - - // Get the corresponding formatter object. - if ($display_options && $display_options['type'] != 'hidden') { - $formatter = drupal_container()->get('plugin.manager.field.formatter')->getInstance(array( - 'instance' => $instance, - 'view_mode' => $this->view_mode, - 'configuration' => $display_options - )); - } - else { - $formatter = NULL; + $display['settings'] = $form_state['formatter_settings'][$name]; } + $formatter = $instance->getFormatter($display); // Base button element for the various formatter settings actions. $base_button = array( @@ -289,8 +287,7 @@ class DisplayOverview extends OverviewBase { // Non-field elements. foreach ($extra_fields as $name => $extra_field) { - $display_options = $entity_display->getComponent($name); - + $display = $extra_field['display'][$this->view_mode]; $table[$name] = array( '#attributes' => array('class' => array('draggable', 'tabledrag-leaf')), '#row_type' => 'extra_field', @@ -303,7 +300,7 @@ class DisplayOverview extends OverviewBase { '#type' => 'textfield', '#title' => t('Weight for @title', array('@title' => $extra_field['label'])), '#title_display' => 'invisible', - '#default_value' => $display_options ? $display_options['weight'] : 0, + '#default_value' => $display['weight'], '#size' => 3, '#attributes' => array('class' => array('field-weight')), ), @@ -332,7 +329,7 @@ class DisplayOverview extends OverviewBase { '#title' => t('Visibility for @title', array('@title' => $extra_field['label'])), '#title_display' => 'invisible', '#options' => $extra_visibility_options, - '#default_value' => $display_options ? 'visible' : 'hidden', + '#default_value' => $display['visible'] ? 'content' : 'hidden', '#parents' => array('fields', $name, 'type'), '#attributes' => array('class' => array('field-formatter-type')), ), @@ -421,87 +418,74 @@ class DisplayOverview extends OverviewBase { */ public function submit(array $form, array &$form_state) { $form_values = $form_state['values']; - $display = entity_get_display($this->entity_type, $this->bundle, $this->view_mode); - // Collect data for 'regular' fields. + // Save data for 'regular' fields. foreach ($form['#fields'] as $field_name) { // Retrieve the stored instance settings to merge with the incoming // values. + $instance = field_read_instance($this->entity_type, $field_name, $this->bundle); $values = $form_values['fields'][$field_name]; - - if ($values['type'] == 'hidden') { - $display->removeComponent($field_name); + // Get formatter settings. They lie either directly in submitted form + // values (if the whole form was submitted while some formatter + // settings were being edited), or have been persisted in + // $form_state. + $settings = array(); + if (isset($values['settings_edit_form']['settings'])) { + $settings = $values['settings_edit_form']['settings']; } - else { - // Get formatter settings. They lie either directly in submitted form - // values (if the whole form was submitted while some formatter - // settings were being edited), or have been persisted in $form_state. - $settings = array(); - if (isset($values['settings_edit_form']['settings'])) { - $settings = $values['settings_edit_form']['settings']; - } - elseif (isset($form_state['formatter_settings'][$field_name])) { - $settings = $form_state['formatter_settings'][$field_name]; - } - elseif ($current_options = $display->getComponent($field_name)) { - $settings = $current_options['settings']; - } - - // Only save settings actually used by the selected formatter. - $default_settings = field_info_formatter_settings($values['type']); - $settings = array_intersect_key($settings, $default_settings); - - $display->setComponent($field_name, array( - 'label' => $values['label'], - 'type' => $values['type'], - 'weight' => $values['weight'], - 'settings' => $settings, - )); + elseif (isset($form_state['formatter_settings'][$field_name])) { + $settings = $form_state['formatter_settings'][$field_name]; } + elseif (isset($instance['display'][$this->view_mode]['settings'])) { + $settings = $instance['display'][$this->view_mode]['settings']; + } + + // Only save settings actually used by the selected formatter. + $default_settings = field_info_formatter_settings($values['type']); + $settings = array_intersect_key($settings, $default_settings); + + $instance['display'][$this->view_mode] = array( + 'label' => $values['label'], + 'type' => $values['type'], + 'weight' => $values['weight'], + 'settings' => $settings, + ); + field_update_instance($instance); } - // Collect data for 'extra' fields. + // Get current bundle settings. + $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle); + + // Save data for 'extra' fields. foreach ($form['#extra'] as $name) { - if ($form_values['fields'][$name]['type'] == 'hidden') { - $display->removeComponent($name); - } - else { - $display->setComponent($name, array( - 'weight' => $form_values['fields'][$name]['weight'], - )); - } + $bundle_settings['extra_fields']['display'][$name][$this->view_mode] = array( + 'weight' => $form_values['fields'][$name]['weight'], + 'visible' => $form_values['fields'][$name]['type'] == 'content', + ); } - // Save the display. - $display->save(); - - // Handle the 'view modes' checkboxes if present. + // Save view modes data. if ($this->view_mode == 'default' && !empty($form_values['view_modes_custom'])) { $entity_info = entity_get_info($this->entity_type); - $bundle_settings = field_bundle_settings($this->entity_type, $this->bundle); - $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle); - - foreach ($form_values['view_modes_custom'] as $view_mode => $value) { - if (!empty($value) && empty($view_mode_settings[$view_mode]['custom_settings'])) { - // If no display exists for the newly enabled view mode, initialize - // it with those from the 'default' view mode, which were used so - // far. - if (!entity_load('entity_display', $this->entity_type . '.' . $this->bundle . '.' . $view_mode)) { - $display = entity_get_display($this->entity_type, $this->bundle, 'default')->createCopy($view_mode); - $display->save(); - } - - $view_mode_label = $entity_info['view_modes'][$view_mode]['label']; - $path = field_ui_bundle_admin_path($this->entity_type, $this->bundle) . "/display/$view_mode"; + foreach ($form_values['view_modes_custom'] as $view_mode_name => $value) { + // Display a message for each view mode newly configured to use custom + // settings. + $view_mode_settings = field_view_mode_settings($this->entity_type, $this->bundle); + if (!empty($value) && empty($view_mode_settings[$view_mode_name]['custom_settings'])) { + $view_mode_label = $entity_info['view_modes'][$view_mode_name]['label']; + $path = field_ui_bundle_admin_path($this->entity_type, $this->bundle) . "/display/$view_mode_name"; drupal_set_message(t('The %view_mode mode now uses custom display settings. You might want to configure them.', array('%view_mode' => $view_mode_label, '@url' => url($path)))); + // Initialize the newly customized view mode with the display settings + // from the default view mode. + _field_ui_add_default_view_mode_settings($this->entity_type, $this->bundle, $view_mode_name, $bundle_settings); } - $bundle_settings['view_modes'][$view_mode]['custom_settings'] = !empty($value); + $bundle_settings['view_modes'][$view_mode_name]['custom_settings'] = !empty($value); } - - // Save updated bundle settings. - field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings); } + // Save updated bundle settings. + field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings); + drupal_set_message(t('Your settings have been saved.')); } diff --git a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php index a977df938b9..2d88051dd44 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/FieldOverview.php @@ -586,13 +586,6 @@ class FieldOverview extends OverviewBase { field_create_field($field); field_create_instance($instance); - // Make sure the field is displayed in the 'default' view mode (using - // default formatter and settings). It stays hidden for other view - // modes until it is explicitly configured. - entity_get_display($this->entity_type, $this->bundle, 'default') - ->setComponent($field['field_name']) - ->save(); - // Always show the field settings step, as the cardinality needs to be // configured for new fields. $destinations[] = $this->adminPath. '/fields/' . $field['field_name'] . '/field-settings'; @@ -627,14 +620,6 @@ class FieldOverview extends OverviewBase { try { field_create_instance($instance); - - // Make sure the field is displayed in the 'default' view mode (using - // default formatter and settings). It stays hidden for other view - // modes until it is explicitly configured. - entity_get_display($this->entity_type, $this->bundle, 'default') - ->setComponent($field['field_name']) - ->save(); - $destinations[] = $this->adminPath . '/fields/' . $instance['field_name']; // Store new field information for any additional submit handlers. $form_state['fields_added']['_add_existing_field'] = $instance['field_name']; diff --git a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php index 45de66eb9d2..8396c7f238b 100644 --- a/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php +++ b/core/modules/field_ui/lib/Drupal/field_ui/Tests/ManageDisplayTest.php @@ -44,12 +44,12 @@ class ManageDisplayTest extends FieldUiTestBase { $this->fieldUIAddNewField($manage_fields, $edit); // Clear the test-side cache and get the saved field instance. - $display = entity_get_display('node', $this->type, 'default'); - $display_options = $display->getComponent('field_test'); - $format = $display_options['type']; + field_info_cache_clear(); + $instance = field_info_instance('node', 'field_test', $this->type); + $format = $instance['display']['default']['type']; $default_settings = field_info_formatter_settings($format); $setting_name = key($default_settings); - $setting_value = $display_options['settings'][$setting_name]; + $setting_value = $instance['display']['default']['settings'][$setting_name]; // Display the "Manage display" screen and check that the expected formatter is // selected. @@ -67,12 +67,12 @@ class ManageDisplayTest extends FieldUiTestBase { $this->assertFieldByName('fields[field_test][type]', $format, 'The expected formatter is selected.'); $this->assertText("$setting_name: $setting_value", 'The expected summary is displayed.'); - // Submit the form and check that the display is updated. + // Submit the form and check that the instance is updated. $this->drupalPost(NULL, array(), t('Save')); - $display = entity_get_display('node', $this->type, 'default'); - $display_options = $display->getComponent('field_test'); - $current_format = $display_options['type']; - $current_setting_value = $display_options['settings'][$setting_name]; + field_info_cache_clear(); + $instance = field_info_instance('node', 'field_test', $this->type); + $current_format = $instance['display']['default']['type']; + $current_setting_value = $instance['display']['default']['settings'][$setting_name]; $this->assertEqual($current_format, $format, 'The formatter was updated.'); $this->assertEqual($current_setting_value, $setting_value, 'The setting was updated.'); diff --git a/core/modules/forum/forum.install b/core/modules/forum/forum.install index b1e63de5817..728172ef54b 100644 --- a/core/modules/forum/forum.install +++ b/core/modules/forum/forum.install @@ -90,22 +90,18 @@ function forum_enable() { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + 'teaser' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + ), ); field_create_instance($instance); - - // Assign display settings for the 'default' and 'teaser' view modes. - entity_get_display('node', 'forum', 'default') - ->setComponent('taxonomy_forums', array( - 'type' => 'taxonomy_term_reference_link', - 'weight' => 10, - )) - ->save(); - entity_get_display('node', 'forum', 'teaser') - ->setComponent('taxonomy_forums', array( - 'type' => 'taxonomy_term_reference_link', - 'weight' => 10, - )) - ->save(); } // Ensure the forum node type is available. diff --git a/core/modules/image/image.module b/core/modules/image/image.module index 83124204f12..221e07cacf9 100644 --- a/core/modules/image/image.module +++ b/core/modules/image/image.module @@ -334,23 +334,21 @@ function image_image_style_save($style) { // Loop through all fields searching for image fields. foreach ($instances as $instance) { if ($instance['widget']['module'] == 'image') { - $entity_info = entity_get_info($instance['entity_type']); - $view_modes = array('default') + array_keys($entity_info['view_modes']); - foreach ($view_modes as $view_mode) { - $display = entity_get_display($instance['entity_type'], $instance['bundle'], $view_mode); - $display_options = $display->getComponent($instance['field_name']); - + $instance_changed = FALSE; + foreach ($instance['display'] as $view_mode => $display) { // Check if the formatter involves an image style. - if ($display_options && $display_options['type'] == 'image' && $display_options['settings']['image_style'] == $style->getOriginalID()) { + if ($display['type'] == 'image' && $display['settings']['image_style'] == $style->getOriginalID()) { // Update display information for any instance using the image // style that was just deleted. - $display_options['settings']['image_style'] = $style->id(); - $display->setComponent($instance['field_name'], $display_options) - ->save(); + $instance['display'][$view_mode]['settings']['image_style'] = $style->id(); + $instance_changed = TRUE; } } if ($instance['widget']['settings']['preview_image_style'] == $style->getOriginalID()) { $instance['widget']['settings']['preview_image_style'] = $style->id(); + $instance_changed = TRUE; + } + if ($instance_changed) { field_update_instance($instance); } } diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php index 0d09461860c..958610d88e0 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageAdminStylesTest.php @@ -253,12 +253,10 @@ class ImageAdminStylesTest extends ImageFieldTestBase { // Create an image field that uses the new style. $field_name = strtolower($this->randomName(10)); $this->createImageField($field_name, 'article'); - entity_get_display('node', 'article', 'default') - ->setComponent($field_name, array( - 'type' => 'image', - 'settings' => array('image_style' => $style_name), - )) - ->save(); + $instance = field_info_instance('node', $field_name, 'article'); + $instance['display']['default']['type'] = 'image'; + $instance['display']['default']['settings']['image_style'] = $style_name; + field_update_instance($instance); // Create a new node with an image attached. $test_image = current($this->drupalGetTestFiles('image')); diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php index 01fa5f42f39..46ce6c5768b 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDefaultImagesTest.php @@ -69,9 +69,6 @@ class ImageFieldDefaultImagesTest extends ImageFieldTestBase { ); field_create_instance($instance2); $instance2 = field_info_instance('node', $field_name, 'page'); - entity_get_display('node', 'page', 'default') - ->setComponent($field['field_name']) - ->save(); // Confirm the defaults are present on the article field settings form. $this->drupalGet("admin/structure/types/manage/article/fields/$field_name/field-settings"); diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php index 924bd2dce12..85361acbf93 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldDisplayTest.php @@ -49,7 +49,6 @@ class ImageFieldDisplayTest extends ImageFieldTestBase { function _testImageFieldFormatters($scheme) { $field_name = strtolower($this->randomName()); $this->createImageField($field_name, 'article', array('uri_scheme' => $scheme)); - // Create a new node with an image attached. $test_image = current($this->drupalGetTestFiles('image')); $nid = $this->uploadNodeImage($test_image, $field_name, 'article'); @@ -66,14 +65,10 @@ class ImageFieldDisplayTest extends ImageFieldTestBase { $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.'); // Test the image linked to file formatter. - $display_options = array( - 'type' => 'image', - 'settings' => array('image_link' => 'file'), - ); - $display = entity_get_display('node', $node->type, 'default'); - $display->setComponent($field_name, $display_options) - ->save(); - + $instance = field_info_instance('node', $field_name, 'article'); + $instance['display']['default']['type'] = 'image'; + $instance['display']['default']['settings']['image_link'] = 'file'; + field_update_instance($instance); $default_output = l(theme('image', $image_info), file_create_url($image_uri), array('html' => TRUE)); $this->drupalGet('node/' . $nid); $this->assertRaw($default_output, 'Image linked to file formatter displaying correctly on full node view.'); @@ -96,19 +91,16 @@ class ImageFieldDisplayTest extends ImageFieldTestBase { } // Test the image linked to content formatter. - $display_options['settings']['image_link'] = 'content'; - $display->setComponent($field_name, $display_options) - ->save(); + $instance['display']['default']['settings']['image_link'] = 'content'; + field_update_instance($instance); $default_output = l(theme('image', $image_info), 'node/' . $nid, array('html' => TRUE, 'attributes' => array('class' => 'active'))); $this->drupalGet('node/' . $nid); $this->assertRaw($default_output, 'Image linked to content formatter displaying correctly on full node view.'); // Test the image style 'thumbnail' formatter. - $display_options['settings']['image_link'] = ''; - $display_options['settings']['image_style'] = 'thumbnail'; - $display->setComponent($field_name, $display_options) - ->save(); - + $instance['display']['default']['settings']['image_link'] = ''; + $instance['display']['default']['settings']['image_style'] = 'thumbnail'; + field_update_instance($instance); // Ensure the derivative image is generated so we do not have to deal with // image style callback paths. $this->drupalGet(image_style_url('thumbnail', $image_uri)); @@ -272,9 +264,6 @@ class ImageFieldDisplayTest extends ImageFieldTestBase { 'files[field_settings_default_image]' => drupal_realpath($images[1]->uri), ); $this->drupalPost('admin/structure/types/manage/article/fields/' . $private_field_name . '/field-settings', $edit, t('Save field settings')); - // Clear field info cache so the new default image is detected. - field_info_cache_clear(); - $private_field = field_info_field($private_field_name); $image = file_load($private_field['settings']['default_image']); $this->assertEqual('private', file_uri_scheme($image->uri), 'Default image uses private:// scheme.'); diff --git a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php index 439db01ebc8..fc964ac1b3b 100644 --- a/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php +++ b/core/modules/image/lib/Drupal/image/Tests/ImageFieldTestBase.php @@ -93,15 +93,7 @@ abstract class ImageFieldTestBase extends WebTestBase { ); $instance['settings'] = array_merge($instance['settings'], $instance_settings); $instance['widget']['settings'] = array_merge($instance['widget']['settings'], $widget_settings); - - $field_instance = field_create_instance($instance); - - entity_get_display('node', $type_name, 'default') - ->setComponent($field['field_name']) - ->save(); - - return $field_instance; - + return field_create_instance($instance); } /** diff --git a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php index a04a43f1d86..a3366d2d885 100644 --- a/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php +++ b/core/modules/link/lib/Drupal/link/Tests/LinkFieldTest.php @@ -62,14 +62,13 @@ class LinkFieldTest extends WebTestBase { 'placeholder_url' => 'http://example.com', ), ), + 'display' => array( + 'full' => array( + 'type' => 'link', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field['field_name'], array( - 'type' => 'link', - )) - ->save(); - $langcode = LANGUAGE_NOT_SPECIFIED; // Display creation form. @@ -131,15 +130,14 @@ class LinkFieldTest extends WebTestBase { 'placeholder_title' => 'Enter a title for this link', ), ), + 'display' => array( + 'full' => array( + 'type' => 'link', + 'label' => 'hidden', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field['field_name'], array( - 'type' => 'link', - 'label' => 'hidden', - )) - ->save(); - $langcode = LANGUAGE_NOT_SPECIFIED; // Verify that the title field works according to the field setting. @@ -237,16 +235,14 @@ class LinkFieldTest extends WebTestBase { 'widget' => array( 'type' => 'link_default', ), - ); - $display_options = array( - 'type' => 'link', - 'label' => 'hidden', + 'display' => array( + 'full' => array( + 'type' => 'link', + 'label' => 'hidden', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field['field_name'], $display_options) - ->save(); - $langcode = LANGUAGE_NOT_SPECIFIED; // Create an entity with two link field values: @@ -292,14 +288,12 @@ class LinkFieldTest extends WebTestBase { foreach ($values as $new_value) { // Update the field formatter settings. if (!is_array($new_value)) { - $display_options['settings'] = array($setting => $new_value); + $this->instance['display']['full']['settings'] = array($setting => $new_value); } else { - $display_options['settings'] = $new_value; + $this->instance['display']['full']['settings'] = $new_value; } - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field['field_name'], $display_options) - ->save(); + field_update_instance($this->instance); $this->renderTestEntity($id); switch ($setting) { @@ -373,16 +367,14 @@ class LinkFieldTest extends WebTestBase { 'widget' => array( 'type' => 'link_default', ), - ); - $display_options = array( - 'type' => 'link_separate', - 'label' => 'hidden', + 'display' => array( + 'full' => array( + 'type' => 'link_separate', + 'label' => 'hidden', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field['field_name'], $display_options) - ->save(); - $langcode = LANGUAGE_NOT_SPECIFIED; // Create an entity with two link field values: @@ -414,10 +406,8 @@ class LinkFieldTest extends WebTestBase { foreach ($options as $setting => $values) { foreach ($values as $new_value) { // Update the field formatter settings. - $display_options['settings'] = array($setting => $new_value); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field['field_name'], $display_options) - ->save(); + $this->instance['display']['full']['settings'] = array($setting => $new_value); + field_update_instance($this->instance); $this->renderTestEntity($id); switch ($setting) { @@ -471,9 +461,8 @@ class LinkFieldTest extends WebTestBase { entity_get_controller('test_entity')->resetCache(array($id)); } $entity = field_test_entity_test_load($id); - $display = entity_get_display($entity->entityType(), $entity->bundle(), $view_mode); - field_attach_prepare_view('test_entity', array($entity->id() => $entity), array($entity->bundle() => $display)); - $entity->content = field_attach_view('test_entity', $entity, $display); + field_attach_prepare_view('test_entity', array($entity->id() => $entity), $view_mode); + $entity->content = field_attach_view('test_entity', $entity, $view_mode); $output = drupal_render($entity->content); $this->drupalSetContent($output); diff --git a/core/modules/node/lib/Drupal/node/NodeFormController.php b/core/modules/node/lib/Drupal/node/NodeFormController.php index 4f5315e40b6..0b892eb13ff 100644 --- a/core/modules/node/lib/Drupal/node/NodeFormController.php +++ b/core/modules/node/lib/Drupal/node/NodeFormController.php @@ -398,19 +398,4 @@ class NodeFormController extends EntityFormController { $node = $this->getEntity($form_state); $form_state['redirect'] = array('node/' . $node->nid . '/delete', array('query' => $destination)); } - - /** - * Overrides \Drupal\Core\Entity\EntityFormController::buildEntity(). - */ - public function buildEntity(array $form, array &$form_state) { - $node = parent::buildEntity($form, $form_state); - // If the node went through 'Preview', it got stored back in $form_state - // with values out of the 'prepare_view' steps, and with the - // entity_view_prepared flag set. Since buildEntity() resets the values to - // those in the form submission, the entity_view_prepared flag needs to be - // reset too so that the next 'Preview' can work on a consistent $node. - unset($node->entity_view_prepared); - return $node; - } - } diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php index 1794e899737..8dd2ab697c4 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeAccessFieldTest.php @@ -45,9 +45,6 @@ class NodeAccessFieldTest extends NodeTestBase { 'bundle' => 'page', ); $this->instance = field_create_instance($instance); - entity_get_display('node', 'page', 'default') - ->setComponent($this->field_name) - ->save(); } /** diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php index b68914130c4..5c906d79d24 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeTypeInitialLanguageTest.php @@ -118,11 +118,11 @@ class NodeTypeInitialLanguageTest extends NodeTestBase { // Changes Language field visibility to true and check if it is saved. $edit = array( - 'fields[language][type]' => 'visible', + 'fields[language][type]' => 'content', ); $this->drupalPost('admin/structure/types/manage/article/display', $edit, t('Save')); $this->drupalGet('admin/structure/types/manage/article/display'); - $this->assertOptionSelected('edit-fields-language-type', 'visible', 'Language field has been set to visible.'); + $this->assertOptionSelected('edit-fields-language-type', 'content', 'Language field has been set to visible.'); // Loads node page and check if Language field is shown. $this->drupalGet('node/' . $node->nid); diff --git a/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php b/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php index 6b966e8a75b..42761468c54 100644 --- a/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php +++ b/core/modules/node/lib/Drupal/node/Tests/SummaryLengthTest.php @@ -46,11 +46,9 @@ class SummaryLengthTest extends NodeTestBase { $this->assertRaw($expected); // Change the teaser length for "Basic page" content type. - $display = entity_get_display('node', $node->type, 'teaser'); - $display_options = $display->getComponent('body'); - $display_options['settings']['trim_length'] = 200; - $display->setComponent('body', $display_options) - ->save(); + $instance = field_info_instance('node', 'body', $node->type); + $instance['display']['teaser']['settings']['trim_length'] = 200; + field_update_instance($instance); // Render the node as a teaser again and check that the summary is now only // 200 characters in length and so does not include 'What is a Drupalism?'. diff --git a/core/modules/node/node.module b/core/modules/node/node.module index d56bee5f142..a37679c18e4 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -19,7 +19,6 @@ use Drupal\Core\Template\Attribute; use Drupal\node\Plugin\Core\Entity\Node; use Drupal\file\Plugin\Core\Entity\File; use Drupal\Core\Entity\EntityInterface; -use Drupal\entity\Plugin\Core\Entity\EntityDisplay; /** * Denotes that the node is not published. @@ -213,17 +212,12 @@ function node_entity_info(&$info) { } /** - * Implements hook_entity_display_alter(). + * Implements hook_field_display_ENTITY_TYPE_alter(). */ -function node_entity_display_alter(EntityDisplay $display, $context) { +function node_field_display_node_alter(&$display, $context) { // Hide field labels in search index. - if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') { - foreach ($display->getComponents() as $name => $options) { - if (isset($options['label'])) { - $options['label'] = 'hidden'; - $display->setComponent($name, $options); - } - } + if ($context['view_mode'] == 'search_index') { + $display['label'] = 'hidden'; } } @@ -565,24 +559,19 @@ function node_add_body_field($type, $label = 'Body') { 'label' => $label, 'widget' => array('type' => 'text_textarea_with_summary'), 'settings' => array('display_summary' => TRUE), + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'type' => 'text_default', + ), + 'teaser' => array( + 'label' => 'hidden', + 'type' => 'text_summary_or_trimmed', + ), + ), ); $instance = field_create_instance($instance); - - // Assign display settings for the 'default' and 'teaser' view modes. - entity_get_display('node', $type->type, 'default') - ->setComponent($field['field_name'], array( - 'label' => 'hidden', - 'type' => 'text_default', - )) - ->save(); - entity_get_display('node', $type->type, 'teaser') - ->setComponent($field['field_name'], array( - 'label' => 'hidden', - 'type' => 'text_summary_or_trimmed', - )) - ->save(); } - return $instance; } diff --git a/core/modules/node/node.pages.inc b/core/modules/node/node.pages.inc index 245fef79392..0a18ec10d26 100644 --- a/core/modules/node/node.pages.inc +++ b/core/modules/node/node.pages.inc @@ -144,6 +144,8 @@ function node_preview(Node $node) { } $node->changed = REQUEST_TIME; + $nodes = array($node->nid => $node); + field_attach_prepare_view('node', $nodes, 'full'); // Display a preview of the node. if (!form_get_errors()) { @@ -173,7 +175,9 @@ function theme_node_preview($variables) { $output = ''; - $elements = node_view($node, 'teaser'); + $preview_trimmed_version = FALSE; + + $elements = node_view(clone $node, 'teaser'); $elements['#attached']['library'][] = array('node', 'drupal.node.preview'); $trimmed = drupal_render($elements); $elements = node_view($node, 'full'); diff --git a/core/modules/node/node.tokens.inc b/core/modules/node/node.tokens.inc index 8827b981f48..2d783c99ca9 100644 --- a/core/modules/node/node.tokens.inc +++ b/core/modules/node/node.tokens.inc @@ -149,19 +149,7 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr // A summary was requested. if ($name == 'summary') { // Generate an optionally trimmed summary of the body field. - - // Get the 'trim_length' size used for the 'teaser' mode, if - // present, or use the default trim_length size. - $display_options = entity_get_display('node', $node->type, 'teaser')->getComponent('body'); - if (isset($display_options['settings']['trim_length'])) { - $length = $display_options['settings']['trim_length']; - } - else { - $settings = field_info_formatter_settings('text_summary_or_trimmed'); - $length = $settings['trim_length']; - } - - $output = text_summary($output, $instance['settings']['text_processing'] ? $items[0]['format'] : NULL, $length); + $output = text_summary($output, $instance['settings']['text_processing'] ? $items[0]['format'] : NULL, $instance['display']['teaser']['settings']['trim_length']); } } $replacements[$original] = $output; diff --git a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php index 232aceaf47f..7588942136d 100644 --- a/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php +++ b/core/modules/number/lib/Drupal/number/Tests/NumberFieldTest.php @@ -70,9 +70,6 @@ class NumberFieldTest extends WebTestBase { ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'default') - ->setComponent($this->field['field_name']) - ->save(); // Display creation form. $this->drupalGet('test-entity/add/test_bundle'); diff --git a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php index 6804b6a3478..d61eebb5a4b 100644 --- a/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php +++ b/core/modules/options/lib/Drupal/options/Tests/OptionsWidgetsTest.php @@ -489,9 +489,9 @@ class OptionsWidgetsTest extends FieldTestBase { 'entity_type' => 'node', 'bundle' => 'page', 'widget' => array( - 'type' => 'options_onoff', - 'module' => 'options', - ), + 'type' => 'options_onoff', + 'module' => 'options', + ), ); field_create_instance($instance); diff --git a/core/modules/picture/lib/Drupal/picture/Tests/PictureFieldDisplayTest.php b/core/modules/picture/lib/Drupal/picture/Tests/PictureFieldDisplayTest.php index de0f782a039..69b0231794e 100644 --- a/core/modules/picture/lib/Drupal/picture/Tests/PictureFieldDisplayTest.php +++ b/core/modules/picture/lib/Drupal/picture/Tests/PictureFieldDisplayTest.php @@ -120,6 +120,11 @@ class PictureFieldDisplayTest extends ImageFieldTestBase { $nid = $this->uploadNodeImage($test_image, $field_name, 'article'); $node = node_load($nid, TRUE); + // Use the picture formatter. + $instance = field_info_instance('node', $field_name, 'article'); + $instance['display']['default']['type'] = 'picture'; + $instance['display']['default']['module'] = 'picture'; + // Test that the default formatter is being used. $image_uri = file_load($node->{$field_name}[LANGUAGE_NOT_SPECIFIED][0]['fid'])->uri; $image_info = array( @@ -131,15 +136,11 @@ class PictureFieldDisplayTest extends ImageFieldTestBase { $this->assertRaw($default_output, 'Default formatter displaying correctly on full node view.'); // Use the picture formatter linked to file formatter. - $display_options = array( - 'type' => 'picture', - 'module' => 'picture', - 'settings' => array('image_link' => 'file'), - ); - $display = entity_get_display('node', 'article', 'default'); - $display->setComponent($field_name, $display_options) - ->save(); - + $instance = field_info_instance('node', $field_name, 'article'); + $instance['display']['default']['type'] = 'picture'; + $instance['display']['default']['module'] = 'picture'; + $instance['display']['default']['settings']['image_link'] = 'file'; + field_update_instance($instance); $default_output = l(theme('image', $image_info), file_create_url($image_uri), array('html' => TRUE)); $this->drupalGet('node/' . $nid); $this->assertRaw($default_output, 'Image linked to file formatter displaying correctly on full node view.'); @@ -162,10 +163,8 @@ class PictureFieldDisplayTest extends ImageFieldTestBase { } // Use the picture formatter with a picture mapping. - $display_options['settings']['picture_mapping'] = 'mapping_one'; - $display->setComponent($field_name, $display_options) - ->save(); - + $instance['display']['default']['settings']['picture_mapping'] = 'mapping_one'; + field_update_instance($instance); // Output should contain all image styles and all breakpoints. $this->drupalGet('node/' . $nid); $this->assertRaw('/styles/thumbnail/'); @@ -176,10 +175,9 @@ class PictureFieldDisplayTest extends ImageFieldTestBase { $this->assertRaw('media="(min-width: 600px)"'); // Test the fallback image style. - $display_options['settings']['image_link'] = ''; - $display_options['settings']['fallback_image_style'] = 'large'; - $display->setComponent($field_name, $display_options) - ->save(); + $instance['display']['default']['settings']['image_link'] = ''; + $instance['display']['default']['settings']['fallback_image_style'] = 'large'; + field_update_instance($instance); $this->drupalGet(image_style_url('large', $image_uri)); $image_info['uri'] = $image_uri; diff --git a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php index 368d221d0c3..db24097ed22 100644 --- a/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php +++ b/core/modules/rdf/lib/Drupal/rdf/Tests/RdfaMarkupTest.php @@ -115,13 +115,13 @@ class RdfaMarkupTest extends WebTestBase { 'field_name' => $field_name, 'entity_type' => 'node', 'bundle' => $bundle_name, + 'display' => array( + 'teaser' => array( + 'type' => 'file_default', + ), + ), ); field_create_instance($instance); - entity_get_display('node', $bundle_name, 'teaser') - ->setComponent($field_name, array( - 'type' => 'file_default', - )) - ->save(); // Set the RDF mapping for the new field. $rdf_mapping = rdf_mapping_load('node', $bundle_name); diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php deleted file mode 100644 index c0de21bb729..00000000000 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/FieldUpgradePathTest.php +++ /dev/null @@ -1,90 +0,0 @@ - 'Field upgrade test', - 'description' => 'Tests upgrade of Field API.', - 'group' => 'Upgrade path', - ); - } - - public function setUp() { - $this->databaseDumpFiles = array( - drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.bare.standard_all.database.php.gz', - drupal_get_path('module', 'system') . '/tests/upgrade/drupal-7.field.database.php', - ); - parent::setUp(); - } - - /** - * Tests upgrade of entity displays. - */ - public function testEntityDisplayUpgrade() { - $this->assertTrue($this->performUpgrade(), 'The upgrade was completed successfully.'); - - // Check that the configuration entries were created. - $displays = array( - 'default' => config('entity.display.node.article.default')->get(), - 'teaser' => config('entity.display.node.article.teaser')->get(), - ); - $this->assertTrue(!empty($displays['default'])); - $this->assertTrue(!empty($displays['teaser'])); - - // Check that manifest entries for the 'article' node type were correctly - // created. - $manifest = config('manifest.entity.display'); - $data = $manifest->get(); - $this->assertEqual($data['node.article.default'], array('name' => 'entity.display.node.article.default')); - $this->assertEqual($data['node.article.teaser'], array('name' => 'entity.display.node.article.teaser')); - - // Check that the 'body' field is configured as expected. - $expected = array( - 'default' => array( - 'label' => 'hidden', - 'type' => 'text_default', - 'weight' => 0, - 'settings' => array(), - ), - 'teaser' => array( - 'label' => 'hidden', - 'type' => 'text_summary_or_trimmed', - 'weight' => 0, - 'settings' => array( - 'trim_length' => 600, - ), - ), - ); - $this->assertEqual($displays['default']['content']['body'], $expected['default']); - $this->assertEqual($displays['teaser']['content']['body'], $expected['teaser']); - - // Check that the display key in the instance data was removed. - $body_instance = field_info_instance('node', 'body', 'article'); - $this->assertTrue(!isset($body_instance['display'])); - - // Check that the 'language' extra field is configured as expected. - $expected = array( - 'default' => array( - 'weight' => -1, - 'visible' => 1, - ), - 'teaser' => array( - 'visible' => 0, - ), - ); - $this->assertEqual($displays['default']['content']['language'], $expected['default']); - $this->assertEqual($displays['teaser']['content']['language'], $expected['teaser']); - } - -} diff --git a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php index 04070c922bb..d86f7cde2c1 100644 --- a/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php +++ b/core/modules/system/lib/Drupal/system/Tests/Upgrade/UserPictureUpgradePathTest.php @@ -57,9 +57,7 @@ class UserPictureUpgradePathTest extends UpgradePathTestBase { $this->assertEqual($instance['settings']['max_filesize'], '700 KB', 'User picture maximum filesize has been migrated.'); $this->assertEqual($instance['description'], 'These are user picture guidelines.', 'User picture guidelines are now the user picture field description.'); $this->assertEqual($instance['settings']['file_directory'], 'user_pictures_dir', 'User picture directory path has been migrated.'); - - $display_options = entity_get_display('user', 'user', 'default')->getComponent('user_picture'); - $this->assertEqual($display_options['settings']['image_style'], 'thumbnail', 'User picture image style setting has been migrated.'); + $this->assertEqual($instance['display']['default']['settings']['image_style'], 'thumbnail', 'User picture image style setting has been migrated.'); // Verify compact view mode default settings. $this->drupalGet('admin/config/people/accounts/display/compact'); diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index f2b5b380e8c..dcc020a5c09 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -18,32 +18,6 @@ function entity_test_entity_info_alter(&$info) { } } -/** - * Implements hook_field_extra_fields(). - */ -function entity_test_field_extra_fields() { - $extra['entity_test']['entity_test'] = array( - 'display' => array( - // Note: those extra fields do not currently display anything, they are - // just used in \Drupal\entity\Tests\EntityDisplayTest to test the - // behavior of entity display objects, - 'display_extra_field' => array( - 'label' => t('Display extra field'), - 'description' => t('An extra field on the display side.'), - 'weight' => 5, - 'visible' => TRUE, - ), - 'display_extra_field_hidden' => array( - 'label' => t('Display extra field (hidden)'), - 'description' => t('An extra field on the display side, hidden by default.'), - 'visible' => FALSE, - ), - ) - ); - - return $extra; -} - /** * Implements hook_permission(). */ diff --git a/core/modules/system/tests/upgrade/drupal-7.field.database.php b/core/modules/system/tests/upgrade/drupal-7.field.database.php deleted file mode 100644 index 0862650bb97..00000000000 --- a/core/modules/system/tests/upgrade/drupal-7.field.database.php +++ /dev/null @@ -1,51 +0,0 @@ - array( - 'teaser' => array( - 'custom_settings' => 1, - ), - 'full' => array( - 'custom_settings' => 0, - ), - 'rss' => array( - 'custom_settings' => 0, - ), - 'search_index' => array( - 'custom_settings' => 0, - ), - 'search_result' => array( - 'custom_settings' => 0, - ), - ), - 'extra_fields' => array( - 'form' => array(), - 'display' => array( - 'language' => array( - 'default' => array( - 'weight' => -1, - 'visible' => 1, - ), - 'teaser' => array( - 'weight' => 0, - 'visible' => 0, - ), - ), - ), - ), -); -db_insert('variable') - ->fields(array( - 'name' => 'field_bundle_settings_node__article', - 'value' => serialize($value), - )) - ->execute(); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php index ac444486eb1..c22f6e3a42d 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermRenderController.php @@ -23,12 +23,13 @@ class TermRenderController extends EntityRenderController { foreach ($entities as $entity) { // Add the description if enabled. + $bundle = $entity->bundle(); $entity_view_mode = $entity->content['#view_mode']; - $display = field_extra_fields_get_display($entity, $entity_view_mode); - if (!empty($entity->description) && !empty($display['description'])) { + $fields = field_extra_fields_get_display($this->entityType, $bundle, $entity_view_mode); + if (!empty($entity->description) && isset($fields['description']) && $fields['description']['visible']) { $entity->content['description'] = array( '#markup' => check_markup($entity->description, $entity->format, '', TRUE), - '#weight' => $display['description']['weight'], + '#weight' => $fields['description']['weight'], '#prefix' => '
', '#suffix' => '
', ); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php index 278db90dd7b..505f8504a97 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/RssTest.php @@ -56,13 +56,13 @@ class RssTest extends TaxonomyTestBase { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), ); field_create_instance($this->instance); - entity_get_display('node', 'article', 'default') - ->setComponent('taxonomy_' . $this->vocabulary->id(), array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); } /** diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php index 25bcc074dcc..565bb98991b 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldMultipleVocabularyTest.php @@ -66,13 +66,13 @@ class TermFieldMultipleVocabularyTest extends TaxonomyTestBase { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'full' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field_name, array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); } /** @@ -98,9 +98,8 @@ class TermFieldMultipleVocabularyTest extends TaxonomyTestBase { // Render the entity. $entity = field_test_entity_test_load($id); $entities = array($id => $entity); - $display = entity_get_display($entity->entityType(), $entity->bundle(), 'full'); - field_attach_prepare_view('test_entity', $entities, array($entity->bundle() => $display)); - $entity->content = field_attach_view('test_entity', $entity, $display); + field_attach_prepare_view('test_entity', $entities, 'full'); + $entity->content = field_attach_view('test_entity', $entity, 'full'); $this->content = drupal_render($entity->content); $this->assertText($term1->name, 'Term 1 name is displayed.'); $this->assertText($term2->name, 'Term 2 name is displayed.'); @@ -111,9 +110,8 @@ class TermFieldMultipleVocabularyTest extends TaxonomyTestBase { // Re-render the content. $entity = field_test_entity_test_load($id); $entities = array($id => $entity); - $display = entity_get_display($entity->entityType(), $entity->bundle(), 'full'); - field_attach_prepare_view('test_entity', $entities, array($entity->bundle() => $display)); - $entity->content = field_attach_view('test_entity', $entity, $display); + field_attach_prepare_view('test_entity', $entities, 'full'); + $entity->content = field_attach_view('test_entity', $entity, 'full'); $this->plainTextContent = FALSE; $this->content = drupal_render($entity->content); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php index c20acf7d3ef..a82a1fac06c 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermFieldTest.php @@ -61,13 +61,13 @@ class TermFieldTest extends TaxonomyTestBase { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'full' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field_name, array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); } /** @@ -123,9 +123,8 @@ class TermFieldTest extends TaxonomyTestBase { // Display the object. $entity = field_test_entity_test_load($id); $entities = array($id => $entity); - $display = entity_get_display($entity->entityType(), $entity->bundle(), 'full'); - field_attach_prepare_view('test_entity', $entities, array($entity->bundle() => $display)); - $entity->content = field_attach_view('test_entity', $entity, $display); + field_attach_prepare_view('test_entity', $entities, 'full'); + $entity->content = field_attach_view('test_entity', $entity, 'full'); $this->content = drupal_render($entity->content); $this->assertText($term->label(), 'Term label is displayed.'); diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php index f9cba0da262..fe918639120 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermIndexTest.php @@ -52,13 +52,13 @@ class TermIndexTest extends TaxonomyTestBase { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), ); field_create_instance($this->instance_1); - entity_get_display('node', 'article', 'default') - ->setComponent($this->field_name_1, array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); $this->field_name_2 = drupal_strtolower($this->randomName()); $this->field_2 = array( @@ -82,13 +82,13 @@ class TermIndexTest extends TaxonomyTestBase { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), ); field_create_instance($this->instance_2); - entity_get_display('node', 'article', 'default') - ->setComponent($this->field_name_2, array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); } /** diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php index 93cc8d4c8f6..1dbe5f82a02 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TermTest.php @@ -48,13 +48,13 @@ class TermTest extends TaxonomyTestBase { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), ); field_create_instance($this->instance); - entity_get_display('node', 'article', 'default') - ->setComponent($this->instance['field_name'], array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); } /** diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php index ea731520132..6a28ca34e1a 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/TokenReplaceTest.php @@ -49,13 +49,13 @@ class TokenReplaceTest extends TaxonomyTestBase { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), ); field_create_instance($this->instance); - entity_get_display('node', 'article', 'default') - ->setComponent('taxonomy_' . $this->vocabulary->id(), array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); } /** diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php index 67adc3a5ac8..e1b3935c3bc 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Tests/Views/TaxonomyTestBase.php @@ -104,21 +104,18 @@ abstract class TaxonomyTestBase extends ViewTestBase { 'type' => 'taxonomy_autocomplete', 'weight' => -4, ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + 'teaser' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + ), ); field_create_instance($instance); - - entity_get_display('node', 'article', 'default') - ->setComponent($instance['field_name'], array( - 'type' => 'taxonomy_term_reference_link', - 'weight' => 10, - )) - ->save(); - entity_get_display('node', 'article', 'teaser') - ->setComponent($instance['field_name'], array( - 'type' => 'taxonomy_term_reference_link', - 'weight' => 10, - )) - ->save(); } /** diff --git a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php index 6bf7fe472b8..8efc516b43b 100644 --- a/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php +++ b/core/modules/text/lib/Drupal/text/Tests/TextFieldTest.php @@ -65,12 +65,13 @@ class TextFieldTest extends WebTestBase { 'widget' => array( 'type' => 'text_textfield', ), + 'display' => array( + 'default' => array( + 'type' => 'text_default', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'default') - ->setComponent($this->field['field_name']) - ->save(); - // Test valid and invalid values with field_attach_validate(). $entity = field_test_create_entity(); $langcode = LANGUAGE_NOT_SPECIFIED; @@ -117,12 +118,13 @@ class TextFieldTest extends WebTestBase { 'placeholder' => 'A placeholder on ' . $widget_type, ), ), + 'display' => array( + 'full' => array( + 'type' => 'text_default', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field_name) - ->save(); - $langcode = LANGUAGE_NOT_SPECIFIED; // Display creation form. @@ -143,8 +145,7 @@ class TextFieldTest extends WebTestBase { // Display the entity. $entity = field_test_entity_test_load($id); - $display = entity_get_display($entity->entityType(), $entity->bundle(), 'full'); - $entity->content = field_attach_view($entity_type, $entity, $display); + $entity->content = field_attach_view($entity_type, $entity, 'full'); $this->content = drupal_render($entity->content); $this->assertText($value, 'Filtered tags are not displayed'); } @@ -177,12 +178,13 @@ class TextFieldTest extends WebTestBase { 'widget' => array( 'type' => $widget_type, ), + 'display' => array( + 'full' => array( + 'type' => 'text_default', + ), + ), ); field_create_instance($this->instance); - entity_get_display('test_entity', 'test_bundle', 'full') - ->setComponent($this->field_name) - ->save(); - $langcode = LANGUAGE_NOT_SPECIFIED; // Disable all text formats besides the plain text fallback format. @@ -212,8 +214,7 @@ class TextFieldTest extends WebTestBase { // Display the entity. $entity = field_test_entity_test_load($id); - $display = entity_get_display($entity->entityType(), $entity->bundle(), 'full'); - $entity->content = field_attach_view($entity_type, $entity, $display); + $entity->content = field_attach_view($entity_type, $entity, 'full'); $this->content = drupal_render($entity->content); $this->assertNoRaw($value, 'HTML tags are not displayed.'); $this->assertRaw(check_plain($value), 'Escaped HTML is displayed correctly.'); @@ -253,8 +254,7 @@ class TextFieldTest extends WebTestBase { // Display the entity. entity_get_controller('test_entity')->resetCache(array($id)); $entity = field_test_entity_test_load($id); - $display = entity_get_display($entity->entityType(), $entity->bundle(), 'full'); - $entity->content = field_attach_view($entity_type, $entity, $display); + $entity->content = field_attach_view($entity_type, $entity, 'full'); $this->content = drupal_render($entity->content); $this->assertRaw($value, 'Value is displayed unfiltered'); } diff --git a/core/modules/user/user.install b/core/modules/user/user.install index cc0bfeba666..705a725c833 100644 --- a/core/modules/user/user.install +++ b/core/modules/user/user.install @@ -388,32 +388,34 @@ function user_install_picture_field() { ), 'weight' => -1, ), + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'type' => 'image', + 'settings' => array( + 'image_style' => 'thumbnail', + 'image_link' => 'content', + ), + ), + 'compact' => array( + 'label' => 'hidden', + 'type' => 'image', + 'settings' => array( + 'image_style' => 'thumbnail', + 'image_link' => 'content', + ), + ), + ), ); field_create_instance($instance); - // Assign display settings for the 'default' and 'compact' view modes. - entity_get_display('user', 'user', 'default') - ->setComponent('user_picture', array( - 'label' => 'hidden', - 'type' => 'image', - 'settings' => array( - 'image_style' => 'thumbnail', - 'image_link' => 'content', - ), - )) - ->save(); - entity_get_display('user', 'user', 'compact') - ->setComponent('user_picture', array( - 'label' => 'hidden', - 'type' => 'image', - 'settings' => array( - 'image_style' => 'thumbnail', - 'image_link' => 'content', - ), - )) - // Additionally, hide 'summary' pseudo-field from compact view mode.. - ->removeComponent('member_for') - ->save(); + // Remove 'summary' pseudo-field from compact view mode on the User entity. + $bundle_settings = field_bundle_settings('user', 'user'); + $bundle_settings['extra_fields']['display']['member_for']['compact'] = array( + 'visible' => FALSE, + 'weight' => 10, + ); + field_bundle_settings('user', 'user', $bundle_settings); } /** @@ -759,6 +761,14 @@ function user_update_8011() { ); _update_7000_field_create_field($field); + // In D7, user pictures did not require Image module to work. Image module + // only allowed usage of an image style to format user pictures in the + // output. The 'user_pictures' variable had a global effect on the presence + // of the user picture functionality before. The new user picture image field + // is created regardless of that global setting, which means the field + // appears on the user account form after migration, even if user pictures + // were disabled previously. The picture is only hidden in the output. + $formatter = update_variable_get('user_pictures', 0) ? 'image' : 'hidden'; $instance = array( 'field_name' => 'user_picture', 'entity_type' => 'user', @@ -785,46 +795,27 @@ function user_update_8011() { ), 'weight' => -1, ), + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'type' => $formatter, + 'settings' => array( + 'image_style' => 'thumbnail', + 'image_link' => 'content', + ), + ), + 'compact' => array( + 'label' => 'hidden', + 'type' => $formatter, + 'settings' => array( + 'image_style' => update_variable_get('user_picture_style', ''), + 'image_link' => 'content', + ), + ), + ), ); _update_7000_field_create_instance($field, $instance); - // Assign display settings for the 'default' and 'compact' view modes. In D7, - // user pictures did not require Image module to work. Image module only - // allowed usage of an image style to format user pictures in the output. - // The 'user_pictures' variable had a global effect on the presence of the - // user picture functionality before. The new user picture image field is - // created regardless of that global setting, which means the field appears - // on the user account form after migration, even if user pictures were - // disabled previously. The picture is only hidden in the output. - $formatter = update_variable_get('user_pictures', 0) ? 'image' : 'hidden'; - module_load_install('entity'); - - $display = _update_8000_entity_get_display('user', 'user', 'default'); - $display->set('content.user_picture', array( - 'label' => 'hidden', - 'type' => $formatter, - 'settings' => array( - 'image_style' => 'thumbnail', - 'image_link' => 'content', - ), - 'weight' => 0, - )) - ->save(); - update_config_manifest_add('entity.display', array($display->get('id'))); - - $display = _update_8000_entity_get_display('user', 'user', 'compact'); - $display->set('content.user_picture', array( - 'label' => 'hidden', - 'type' => $formatter, - 'settings' => array( - 'image_style' => update_variable_get('user_picture_style', ''), - 'image_link' => 'content', - ), - 'weight' => 0, - )) - ->save(); - update_config_manifest_add('entity.display', array($display->get('id'))); - // Add file usage for the default field. if (!empty($default_image_fid)) { db_insert('file_usage') diff --git a/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php b/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php index 1e5b72ffac2..201fdae0e4d 100644 --- a/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/DefaultViewsTest.php @@ -77,13 +77,13 @@ class DefaultViewsTest extends WebTestBase { 'widget' => array( 'type' => 'options_select', ), + 'display' => array( + 'full' => array( + 'type' => 'taxonomy_term_reference_link', + ), + ), ); field_create_instance($this->instance); - entity_get_display('node', 'page', 'full') - ->setComponent($this->field_name, array( - 'type' => 'taxonomy_term_reference_link', - )) - ->save(); // Create a time in the past for the archive. $time = time() - 3600; diff --git a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php index 693ed68c56d..8e51e56ad3a 100644 --- a/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php +++ b/core/modules/views/lib/Drupal/views/Tests/Wizard/TaggedWithTest.php @@ -77,21 +77,18 @@ class TaggedWithTest extends WizardTestBase { 'widget' => array( 'type' => 'taxonomy_autocomplete', ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + 'teaser' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + ), ); field_create_instance($this->tag_instance); - - entity_get_display('node', $this->node_type_with_tags->type, 'default') - ->setComponent('field_views_testing_tags', array( - 'type' => 'taxonomy_term_reference_link', - 'weight' => 10, - )) - ->save(); - entity_get_display('node', $this->node_type_with_tags->type, 'teaser') - ->setComponent('field_views_testing_tags', array( - 'type' => 'taxonomy_term_reference_link', - 'weight' => 10, - )) - ->save(); } /** diff --git a/core/profiles/standard/standard.install b/core/profiles/standard/standard.install index 0961820be32..48da6b1c77a 100644 --- a/core/profiles/standard/standard.install +++ b/core/profiles/standard/standard.install @@ -295,22 +295,19 @@ function standard_install() { 'type' => 'taxonomy_autocomplete', 'weight' => -4, ), + 'display' => array( + 'default' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + 'teaser' => array( + 'type' => 'taxonomy_term_reference_link', + 'weight' => 10, + ), + ), ); field_create_instance($instance); - // Assign display settings for the 'default' and 'teaser' view modes. - entity_get_display('node', 'article', 'default') - ->setComponent($instance['field_name'], array( - 'type' => 'taxonomy_term_reference_link', - 'weight' => 10, - )) - ->save(); - entity_get_display('node', 'article', 'teaser') - ->setComponent($instance['field_name'], array( - 'type' => 'taxonomy_term_reference_link', - 'weight' => 10, - )) - ->save(); // Create an image field named "Image", enabled for the 'article' content type. // Many of the following values will be defaulted, they're included here as an illustrative examples. @@ -362,27 +359,24 @@ function standard_install() { ), 'weight' => -1, ), + + 'display' => array( + 'default' => array( + 'label' => 'hidden', + 'type' => 'image', + 'settings' => array('image_style' => 'large', 'image_link' => ''), + 'weight' => -1, + ), + 'teaser' => array( + 'label' => 'hidden', + 'type' => 'image', + 'settings' => array('image_style' => 'medium', 'image_link' => 'content'), + 'weight' => -1, + ), + ), ); field_create_instance($instance); - // Assign display settings for the 'default' and 'teaser' view modes. - entity_get_display('node', 'article', 'default') - ->setComponent($instance['field_name'], array( - 'label' => 'hidden', - 'type' => 'image', - 'settings' => array('image_style' => 'large', 'image_link' => ''), - 'weight' => -1, - )) - ->save(); - entity_get_display('node', 'article', 'teaser') - ->setComponent($instance['field_name'], array( - 'label' => 'hidden', - 'type' => 'image', - 'settings' => array('image_style' => 'medium', 'image_link' => 'content'), - 'weight' => -1, - )) - ->save(); - // Create user picture field. module_load_install('user'); user_install_picture_field();