Commit 10b43b95 authored by alexpott's avatar alexpott

Issue #1953528 by swentel, Hydra: Store 'per-bundle view mode settings' in...

Issue #1953528 by swentel, Hydra: Store 'per-bundle view mode settings' in CMI, get rid of field_bundle_settings() & its variable.
parent 57f6c6f0
......@@ -717,6 +717,7 @@ function entity_get_display($entity_type, $bundle, $view_mode) {
'targetEntityType' => $entity_type,
'bundle' => $bundle,
'mode' => $view_mode,
'status' => TRUE,
));
}
......@@ -750,12 +751,20 @@ function entity_get_display($entity_type, $bundle, $view_mode) {
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]['status']) ? $view_mode : 'default';
$render_view_mode = 'default';
// Look at the default display and display for the view mode, and fallback to
// the former if the latter does not exist is disabled.
if ($view_mode != 'default') {
$ids = array(
'default' => $entity_type . '.' . $bundle . '.default',
$view_mode => $entity_type . '.' . $bundle . '.' . $view_mode,
);
$entity_displays = entity_load_multiple('entity_display', $ids);
if (isset($entity_displays[$ids[$view_mode]]) && $entity_displays[$ids[$view_mode]]->status()) {
$render_view_mode = $view_mode;
}
}
$display = entity_get_display($entity_type, $bundle, $render_view_mode);
$display->originalMode = $view_mode;
......@@ -812,6 +821,7 @@ function entity_get_form_display($entity_type, $bundle, $form_mode) {
'targetEntityType' => $entity_type,
'bundle' => $bundle,
'mode' => $form_mode,
'status' => TRUE,
));
}
......@@ -841,12 +851,20 @@ function entity_get_form_display($entity_type, $bundle, $form_mode) {
function entity_get_render_form_display(EntityInterface $entity, $form_mode) {
$entity_type = $entity->entityType();
$bundle = $entity->bundle();
// Determine the form display to use for rendering this entity form. Depending
// on the configuration of the form mode for this bundle, this will be either
// the form display associated to the form mode, or the 'default' display.
$form_mode_settings = field_form_mode_settings($entity_type, $bundle);
$render_form_mode = !empty($form_mode_settings[$form_mode]['status']) ? $form_mode : 'default';
$render_form_mode = 'default';
// Look at the default form display and form display for the view mode, and
// fallback to the former if the latter does not exist is disabled.
if ($form_mode != 'default') {
$ids = array(
'default' => $entity_type . '.' . $bundle . '.default',
$form_mode => $entity_type . '.' . $bundle . '.' . $form_mode,
);
$entity_form_displays = entity_load_multiple('entity_form_display', $ids);
if (isset($entity_form_displays[$ids[$form_mode]]) && $entity_form_displays[$ids[$form_mode]]->status()) {
$render_form_mode = $form_mode;
}
}
$form_display = entity_get_form_display($entity_type, $bundle, $render_form_mode);
$form_display->originalMode = $form_mode;
......
......@@ -186,12 +186,16 @@ public function processForm($element, $form_state, $form) {
}
}
// Hide extra fields.
// Hide or assign weights for extra fields.
$extra_fields = field_info_extra_fields($this->entity->entityType(), $this->entity->bundle(), 'form');
foreach ($extra_fields as $extra_field => $info) {
if (!$this->getFormDisplay($form_state)->getComponent($extra_field)) {
$component = $this->getFormDisplay($form_state)->getComponent($extra_field);
if (!$component) {
$element[$extra_field]['#access'] = FALSE;
}
else {
$element[$extra_field]['#weight'] = $component['weight'];
}
}
return $element;
......
......@@ -46,9 +46,7 @@ public function form(array $form, array &$form_state) {
$form += $form_state['comment_preview'];
}
$form['author'] = array(
'#weight' => 10,
);
$form['author'] = array();
// Display author information in a details element for comment moderators.
if ($is_admin) {
$form['author'] += array(
......
......@@ -37,6 +37,7 @@ function _update_8000_entity_get_display($entity_type, $bundle, $view_mode) {
'bundle' => $bundle,
'mode' => $view_mode,
'content' => array(),
'status' => TRUE,
);
foreach ($properties as $key => $value) {
$config->set($key, $value);
......@@ -76,6 +77,7 @@ function _update_8000_entity_get_form_display($entity_type, $bundle, $form_mode)
'bundle' => $bundle,
'mode' => $form_mode,
'content' => array(),
'status' => TRUE,
);
foreach ($properties as $key => $value) {
$config->set($key, $value);
......
......@@ -26,7 +26,8 @@
* config_prefix = "entity.display",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid"
* "uuid" = "uuid",
* "status" = "status"
* }
* )
*/
......
......@@ -26,7 +26,8 @@
* config_prefix = "entity.form_display",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid"
* "uuid" = "uuid",
* "status" = "status"
* }
* )
*/
......
......@@ -50,6 +50,14 @@ abstract class EntityDisplayBase extends ConfigEntityBase implements EntityDispl
*/
public $mode;
/**
* Whether this display is enabled or not. If the entity (form) display
* is disabled, we'll fall back to the 'default' display.
*
* @var boolean
*/
public $status;
/**
* List of component display options, keyed by component name.
*
......@@ -143,6 +151,7 @@ public function getExportProperties() {
'bundle',
'mode',
'content',
'status',
);
$properties = array();
foreach ($names as $name) {
......
......@@ -240,16 +240,16 @@ function field_update_8002() {
->execute();
}
// Migration of 'extra_fields' display settings. Avoid calling
// entity_get_info() by fetching the relevant variables directly in the
// variable table.
// Migration of the content of the old 'bundle_settings_*'' variables.
// Avoid calling entity_get_info() by fetching the relevant variables
// directly in the variable 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)) {
$variable_needs_update = FALSE;
$entity_type = $matches[1];
$bundle = $matches[2];
// Migrate form settings for extra fields.
if (isset($variable_value['extra_fields']['form'])) {
foreach ($variable_value['extra_fields']['form'] as $field_name => $field_settings) {
// Determine name and create initial entry in the $form_displays
......@@ -260,12 +260,9 @@ function field_update_8002() {
}
$form_displays[$form_display_id]->set("content.$field_name", $field_settings);
}
// Remove the old entry.
unset($variable_value['extra_fields']['form']);
$variable_needs_update = TRUE;
}
// Migrate display settings for extra fields.
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) {
......@@ -286,16 +283,24 @@ function field_update_8002() {
$displays[$display_id]->set("content.$field_name", $new_options);
}
}
// Remove the old entry.
unset($variable_value['extra_fields']['display']);
$variable_needs_update = TRUE;
}
if ($variable_needs_update) {
variable_set($variable_name, $variable_value);
// Migrate view mode settings.
if (isset($variable_value['view_modes'])) {
foreach ($variable_value['view_modes'] as $view_mode => $view_mode_settings) {
// 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);
}
$displays[$display_id]->set('status', $view_mode_settings['custom_settings']);
}
}
// Remove the variable.
update_variable_del($variable_name);
}
}
// Save the form displays to configuration.
......
......@@ -295,11 +295,6 @@ function field_entity_bundle_rename($entity_type, $bundle_old, $bundle_new) {
// Clear the field cache.
field_cache_clear();
// Update bundle settings.
$settings = variable_get('field_bundle_settings_' . $entity_type . '__' . $bundle_old, array());
variable_set('field_bundle_settings_' . $entity_type . '__' . $bundle_new, $settings);
variable_del('field_bundle_settings_' . $entity_type . '__' . $bundle_old);
}
/**
......@@ -323,9 +318,6 @@ function field_entity_bundle_delete($entity_type, $bundle) {
// Clear the cache.
field_cache_clear();
// Clear bundle display settings.
variable_del('field_bundle_settings_' . $entity_type . '__' . $bundle);
}
/**
......@@ -408,124 +400,6 @@ function field_sync_field_status() {
field_cache_clear();
}
/**
* Gets or sets administratively defined bundle settings.
*
* @param string $entity_type
* The type of $entity; e.g., 'node' or 'user'.
* @param string $bundle
* The bundle name.
* @param array|null $settings
* (optional) The settings to store, an associative array with the following
* elements:
* - view_modes: An associative array keyed by view mode, with the following
* key/value pairs:
* - status: Boolean specifying whether the view mode uses a dedicated set
* of display options (TRUE), or the 'default' options (FALSE). Defaults
* to FALSE.
* - extra_fields: An associative array containing the form and display
* settings for extra fields (also known as pseudo-fields):
* - form: An associative array whose keys are the names of extra fields,
* and whose values are associative arrays with the following elements:
* - weight: The weight of the extra field, determining its position on an
* entity form.
* - display: An associative array whose keys are the names of extra fields,
* and whose values are associative arrays keyed by the name of view
* modes. This array must include an item for the 'default' view mode.
* Each view mode sub-array contains the following elements:
* - weight: The weight of the extra field, determining its position when
* an entity is viewed.
* - visible: TRUE if the extra field is visible, FALSE otherwise.
*
* @return array|null
* If no $settings are passed, the current settings are returned.
*/
function field_bundle_settings($entity_type, $bundle, $settings = NULL) {
if (isset($settings)) {
variable_set('field_bundle_settings_' . $entity_type . '__' . $bundle, $settings);
field_info_cache_clear();
}
else {
$settings = variable_get('field_bundle_settings_' . $entity_type . '__' . $bundle, array());
$settings += array(
'view_modes' => array(),
'form_modes' => array(),
);
return $settings;
}
}
/**
* Returns form mode settings in a given bundle.
*
* @param string $entity_type
* The type of entity; e.g. 'node' or 'user'.
* @param string $bundle
* The bundle name to return form mode settings for.
*
* @return
* An array keyed by form mode, with the following key/value pairs:
* - status: Boolean specifying whether the form mode uses a dedicated set of
* display options (TRUE), or the 'default' options (FALSE). Defaults to
* FALSE.
*/
function field_form_mode_settings($entity_type, $bundle) {
$cache = &drupal_static(__FUNCTION__, array());
if (!isset($cache[$entity_type][$bundle])) {
$bundle_settings = field_bundle_settings($entity_type, $bundle);
$settings = $bundle_settings['form_modes'];
// Include form modes for which nothing has been stored yet, but whose
// definition in hook_entity_info_alter() specify they should use custom
// settings by default.
$form_modes = entity_get_form_modes($entity_type);
foreach ($form_modes as $form_mode => $form_mode_info) {
if (!isset($settings[$form_mode]['status']) && $form_mode_info['status']) {
$settings[$form_mode]['status'] = TRUE;
}
}
$cache[$entity_type][$bundle] = $settings;
}
return $cache[$entity_type][$bundle];
}
/**
* Returns view mode settings in a given bundle.
*
* @param $entity_type
* The type of entity; e.g. 'node' or 'user'.
* @param $bundle
* The bundle name to return view mode settings for.
*
* @return
* An array keyed by view mode, with the following key/value pairs:
* - status: Boolean specifying whether the view mode uses a dedicated set of
* display options (TRUE), or the 'default' options (FALSE). Defaults to
* FALSE.
*/
function field_view_mode_settings($entity_type, $bundle) {
$cache = &drupal_static(__FUNCTION__, array());
if (!isset($cache[$entity_type][$bundle])) {
$bundle_settings = field_bundle_settings($entity_type, $bundle);
$settings = $bundle_settings['view_modes'];
// Include view modes for which nothing has been stored yet, but whose
// definition in hook_entity_info_alter() specify they should use custom
// settings by default.
$view_modes = entity_get_view_modes($entity_type);
foreach ($view_modes as $view_mode => $view_mode_info) {
if (!isset($settings[$view_mode]['status']) && $view_mode_info['status']) {
$settings[$view_mode]['status'] = TRUE;
}
}
$cache[$entity_type][$bundle] = $settings;
}
return $cache[$entity_type][$bundle];
}
/**
* Clears the field info and field data caches.
*/
......
......@@ -545,13 +545,10 @@ public function getBundleExtraFields($entity_type, $bundle) {
// Cache miss: read from hook_field_extra_fields(). Note: given the current
// shape of the hook, we have no other way than collecting extra fields on
// all bundles.
$info = array();
$extra = $this->moduleHandler->invokeAll('field_extra_fields');
drupal_alter('field_extra_fields', $extra);
// Merge in saved settings.
if (isset($extra[$entity_type][$bundle])) {
$info = $this->prepareExtraFields($extra[$entity_type][$bundle], $entity_type, $bundle);
}
$info = isset($extra[$entity_type][$bundle]) ? $extra[$entity_type][$bundle] : array();
$info += array('form' => array(), 'display' => array());
// Store in the 'static' and persistent caches.
$this->bundleExtraFields[$entity_type][$bundle] = $info;
......@@ -599,38 +596,4 @@ public function prepareInstance($instance, $field_type) {
return $instance;
}
/**
* Prepares 'extra fields' for the current run-time context.
*
* @param $extra_fields
* The array of extra fields, as collected in hook_field_extra_fields().
* @param $entity_type
* The entity type.
* @param $bundle
* The bundle name.
*
* @return
* The list of extra fields completed for the current runtime context.
*/
public function prepareExtraFields($extra_fields, $entity_type, $bundle) {
$entity_type_info = entity_get_info($entity_type);
$bundle_settings = field_bundle_settings($entity_type, $bundle);
$extra_fields += array('form' => array(), 'display' => array());
$result = array();
// Extra fields in forms.
foreach ($extra_fields['form'] as $name => $field_data) {
$settings = isset($bundle_settings['extra_fields']['form'][$name]) ? $bundle_settings['extra_fields']['form'][$name] : array();
if (isset($settings['weight'])) {
$field_data['weight'] = $settings['weight'];
}
$result['form'][$name] = $field_data;
}
// Extra fields in displayed entities.
$result['display'] = $extra_fields['display'];
return $result;
}
}
......@@ -31,8 +31,16 @@ public function access(Route $route, Request $request) {
$bundle = $request->attributes->get('bundle');
$form_mode = $request->attributes->get('mode');
$form_mode_settings = field_form_mode_settings($entity_type, $bundle);
$visibility = ($form_mode == 'default') || !empty($form_mode_settings[$form_mode]['status']);
if ($form_mode == 'default') {
$visibility = TRUE;
}
elseif ($entity_form_display = entity_load('entity_form_display', $entity_type . '.' . $bundle . '.' . $form_mode)) {
$visibility = $entity_form_display->status();
}
else {
$visibility = FALSE;
}
if ($visibility) {
$permission = $route->getRequirement('_field_ui_form_mode_access');
return user_access($permission) ? static::ALLOW : static::DENY;
......
......@@ -31,8 +31,16 @@ public function access(Route $route, Request $request) {
$bundle = $request->attributes->get('bundle');
$view_mode = $request->attributes->get('mode');
$view_mode_settings = field_view_mode_settings($entity_type, $bundle);
$visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['status']);
if ($view_mode == 'default') {
$visibility = TRUE;
}
elseif ($entity_display = entity_load('entity_display', $entity_type . '.' . $bundle . '.' . $view_mode)) {
$visibility = $entity_display->status();
}
else {
$visibility = FALSE;
}
if ($visibility) {
$permission = $route->getRequirement('_field_ui_view_mode_access');
return user_access($permission) ? static::ALLOW : static::DENY;
......
......@@ -139,17 +139,8 @@ protected function getDisplayModes() {
/**
* {@inheritdoc}
*/
protected function getDisplayModeSettings() {
return field_view_mode_settings($this->entity_type, $this->bundle);
}
/**
* {@inheritdoc}
*/
protected function saveDisplayModeSettings($display_mode_settings) {
$bundle_settings = field_bundle_settings($this->entity_type, $this->bundle);
$bundle_settings['view_modes'] = NestedArray::mergeDeep($bundle_settings['view_modes'], $display_mode_settings);
field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings);
protected function getDisplayType() {
return 'entity_display';
}
/**
......
......@@ -149,10 +149,10 @@ public function buildForm(array $form, array &$form_state, $entity_type = NULL,
// checkboxes.
$options = array();
$default = array();
$display_mode_settings = $this->getDisplayModeSettings();
$display_statuses = $this->getDisplayStatuses();
foreach ($display_modes as $mode_name => $mode_info) {
$options[$mode_name] = $mode_info['label'];
if (!empty($display_mode_settings[$mode_name]['status'])) {
if (!empty($display_statuses[$mode_name])) {
$default[] = $mode_name;
}
}
......@@ -506,14 +506,14 @@ public function submitForm(array &$form, array &$form_state) {
// Save the display.
$display->save();
// Handle the 'view modes' checkboxes if present.
// Handle the 'display modes' checkboxes if present.
if ($this->mode == 'default' && !empty($form_values['display_modes_custom'])) {
$display_modes = $this->getDisplayModes();
$display_mode_settings = $this->getDisplayModeSettings();
$current_statuses = $this->getDisplayStatuses();
$display_mode_bundle_settings = array();
$statuses = array();
foreach ($form_values['display_modes_custom'] as $mode => $value) {
if (!empty($value) && empty($display_mode_settings[$mode]['status'])) {
if (!empty($value) && empty($current_statuses[$mode])) {
// If no display exists for the newly enabled view mode, initialize
// it with those from the 'default' view mode, which were used so
// far.
......@@ -526,11 +526,10 @@ public function submitForm(array &$form, array &$form_state) {
$path = $this->getOverviewPath($mode);
drupal_set_message($this->t('The %display_mode mode now uses custom display settings. You might want to <a href="@url">configure them</a>.', array('%display_mode' => $display_mode_label, '@url' => url($path))));
}
$display_mode_bundle_settings[$mode]['status'] = !empty($value);
$statuses[$mode] = !empty($value);
}
// Save updated bundle settings.
$this->saveDisplayModeSettings($display_mode_bundle_settings);
$this->saveDisplayStatuses($statuses);
}
drupal_set_message($this->t('Your settings have been saved.'));
......@@ -679,20 +678,12 @@ protected function getPluginOptions($field_type) {
abstract protected function getDisplayModes();
/**
* Returns form or view modes settings for the bundle used by this form.
* Returns the display entity type.
*
* @return array
* An array of form or view mode settings.
*/
abstract protected function getDisplayModeSettings();
/**
* Saves the updated display mode settings.
*
* @param array $display_mode_settings
* An array holding updated form or view mode settings.
* @return string
* The name of the display entity type.
*/
abstract protected function saveDisplayModeSettings($display_mode_settings);
abstract protected function getDisplayType();
/**
* Returns the region to which a row in the display overview belongs.
......@@ -724,6 +715,57 @@ protected function getExtraFieldVisibilityOptions() {
);
}
/**
* Returns entity (form) displays for the current entity display type.
*
* @return array
* An array holding entity displays or entity form displays.
*/
protected function getDisplays() {
$load_ids = array();
$display_entity_type = $this->getDisplayType();
$entity_info = $this->entityManager->getDefinition($display_entity_type);
$config_prefix = $entity_info['config_prefix'];
$ids = config_get_storage_names_with_prefix($config_prefix . '.' . $this->entity_type . '.' . $this->bundle);
foreach ($ids as $id) {
$config_id = str_replace($config_prefix . '.', '', $id);
list(,, $display_mode) = explode('.', $config_id);
if ($display_mode != 'default') {
$load_ids[] = $config_id;
}
}
return entity_load_multiple($display_entity_type, $load_ids);
}
/**
* Returns form or view modes statuses for the bundle used by this form.
*
* @return array
* An array of form or view mode statuses.
*/
protected function getDisplayStatuses() {
$display_statuses = array();
$displays = $this->getDisplays();
foreach ($displays as $display) {
$display_statuses[$display->get('mode')] = $display->status();
}
return $display_statuses;
}
/**
* Saves the updated display mode statuses.
*
* @param array $display_statuses
* An array holding updated form or view mode statuses.
*/
protected function saveDisplayStatuses($display_statuses) {
$displays = $this->getDisplays();
foreach ($displays as $display) {
$display->set('status', $display_statuses[$display->get('mode')]);
$display->save();
}
}
/**
* Returns an array containing the table headers.
*
......
......@@ -99,17 +99,8 @@ protected function getDisplayModes() {
/**
* {@inheritdoc}
*/
protected function getDisplayModeSettings() {
return field_form_mode_settings($this->entity_type, $this->bundle);
}
/**
* {@inheritdoc}
*/
protected function saveDisplayModeSettings($display_mode_settings) {
$bundle_settings = field_bundle_settings($this->entity_type, $this->bundle);
$bundle_settings['form_modes'] = NestedArray::mergeDeep($bundle_settings['form_modes'], $display_mode_settings);
field_bundle_settings($this->entity_type, $this->bundle, $bundle_settings);
protected function getDisplayType() {
return 'entity_form_display';
}
/**
......
......@@ -3,6 +3,7 @@ uuid: adaef6a9-8dc0-4f2e-9858-88daac440aa9
targetEntityType: taxonomy_term
bundle: forums
mode: default
status: 1
content:
description:
weight: '0'
......
......@@ -3,6 +3,7 @@ uuid: c8eab085-8fd3-4545-8600-e13b7d8bb9c4
targetEntityType: taxonomy_term
bundle: forums
mode: default
status: 1
content:
name:
weight: '-5'
......
......@@ -26,7 +26,7 @@ class FieldSqlStorageTest extends EntityUnitTestBase {
*
* @var array
*/
public static $modules = array('system', 'field', 'field_test', 'text', 'number', 'entity_test');
public static $modules = array('field', 'field_test', 'text', 'number', 'entity_test');
/**
* The name of the created field.
......@@ -67,7 +67,6 @@ public static function getInfo() {
function setUp() {
parent::setUp();
$this->installSchema('entity_test', array('entity_test_rev', 'entity_test_rev_revision'));
$this->installSchema('system', array('variable'));
$entity_type = 'entity_test_rev';
$this->field_name = strtolower($this->randomName());
......
......@@ -12,19 +12,19 @@
$value = array(
'view_modes' => array(
'teaser' => array(
'status' => 1,
'custom_settings' => 1,
),
'full' => array(
'status' => 0,
'custom_settings' => 0,
),
'rss' => array(
'status' => 0,
'custom_settings' => 0,
),
'search_index' => array(
'status' => 0,
'custom_settings' => 0,
),
'search_result' => array(
'status' => 0,
'custom_settings' => 0,
),
),
'extra_fields' => array(
......
......@@ -213,6 +213,8 @@ function testRegistrationWithUserFields() {
entity_get_form_display('user', 'user', 'default')
->setComponent('test_user_field', array('type' => 'test_field_widget'))
->save();
entity_get_form_display('user', 'user', 'register')
->save();