Commit 6ed57d39 authored by alexpott's avatar alexpott

Issue #1946404 by tim.plunkett, amateescu, swentel: Convert forms in...

Issue #1946404 by tim.plunkett, amateescu, swentel: Convert forms in field_ui().admin.inc to the new form interface.
parent 47308d21
......@@ -97,16 +97,8 @@ function hook_entity_view_mode_info_alter(&$view_modes) {
* - admin: An array of information that allows Field UI pages to attach
* themselves to the existing administration pages for the bundle.
* Elements:
* - path: the path of the bundle's main administration page, as defined
* in hook_menu(). If the path includes a placeholder for the bundle,
* the 'bundle argument', 'bundle helper' and 'real path' keys below
* are required.
* - bundle argument: The position of the placeholder in 'path', if any.
* - real path: The actual path (no placeholder) of the bundle's main
* administration page. This will be used to generate links.
* - access callback: As in hook_menu(). 'user_access' will be assumed if
* no value is provided.
* - access arguments: As in hook_menu().
* - translatable: (optional) A boolean value specifying whether this bundle
* has translation support enabled. Defaults to FALSE.
*
......
......@@ -193,6 +193,27 @@ class EntityType extends Plugin {
*/
public $bundle_keys;
/**
* The base router path for the entity type's field administration page.
*
* If the entity type has a bundle, include {bundle} in the path.
*
* For example, the node entity type specifies
* "admin/structure/types/manage/{bundle}" as its base field admin path.
*
* @var string (optional)
*/
public $route_base_path;
/**
* The prefix for the bundles of this entity type.
*
* For example, the comment bundle is prefixed with 'comment_node_'.
*
* @var string (optional)
*/
public $bundle_prefix;
/**
* The base menu router path to which the entity admin user interface responds.
*
......
......@@ -187,9 +187,7 @@ function custom_block_entity_bundle_info() {
$bundles['custom_block'][$config->get('id')] = array(
'label' => $config->get('label'),
'admin' => array(
'path' => 'admin/structure/custom-blocks/manage/%',
'real path' => 'admin/structure/custom-blocks/manage/' . $config->get('id'),
'bundle argument' => 4,
),
);
}
......
......@@ -31,6 +31,7 @@
* },
* base_table = "custom_block",
* revision_table = "custom_block_revision",
* route_base_path = "admin/structure/custom-blocks/manage/{bundle}",
* menu_base_path = "block/%custom_block",
* fieldable = TRUE,
* translatable = TRUE,
......
......@@ -99,7 +99,7 @@ public function testCustomBlockTypeEditing() {
$this->assertEqual(url('block/add/basic', array('absolute' => TRUE)), $this->getUrl(), 'Original machine name was used in URL.');
// Remove the body field.
$this->drupalPost('admin/structure/custom-blocks/manage/basic/fields/block_body/delete', array(), t('Delete'));
$this->drupalPost('admin/structure/custom-blocks/manage/basic/fields/custom_block.basic.block_body/delete', array(), t('Delete'));
// Resave the settings for this type.
$this->drupalPost('admin/structure/custom-blocks/manage/basic', array(), t('Save'));
// Check that the body field doesn't exist.
......
......@@ -119,14 +119,6 @@ function comment_entity_bundle_info() {
// have to be extracted manually from the bundle name.
'node bundle' => $type,
'admin' => array(
// Place the Field UI paths for comments one level below the
// corresponding paths for nodes, so that they appear in the same set
// of local tasks. Note that the paths use a different placeholder name
// and thus a different menu loader callback, so that Field UI page
// callbacks get a comment bundle name from the node type in the URL.
// See comment_node_type_load() and comment_menu_alter().
'path' => 'admin/structure/types/manage/%comment_node_type/comment',
'bundle argument' => 4,
'real path' => 'admin/structure/types/manage/' . $type . '/comment',
),
);
......@@ -301,10 +293,10 @@ function comment_menu_alter(&$items) {
// Adjust the Field UI tabs on admin/structure/types/manage/[node-type].
// See comment_entity_bundle_info().
$items['admin/structure/types/manage/%comment_node_type/comment/fields']['title'] = 'Comment fields';
$items['admin/structure/types/manage/%comment_node_type/comment/fields']['weight'] = 3;
$items['admin/structure/types/manage/%comment_node_type/comment/display']['title'] = 'Comment display';
$items['admin/structure/types/manage/%comment_node_type/comment/display']['weight'] = 4;
$items['admin/structure/types/manage/%/comment/fields']['title'] = 'Comment fields';
$items['admin/structure/types/manage/%/comment/fields']['weight'] = 3;
$items['admin/structure/types/manage/%/comment/display']['title'] = 'Comment display';
$items['admin/structure/types/manage/%/comment/display']['weight'] = 4;
}
/**
......
......@@ -34,6 +34,8 @@
* fieldable = TRUE,
* translatable = TRUE,
* static_cache = FALSE,
* route_base_path = "admin/structure/types/manage/{bundle}/comment",
* bundle_prefix = "comment_node_",
* entity_keys = {
* "id" = "cid",
* "bundle" = "node_type",
......
......@@ -107,7 +107,7 @@ function testCommentFormat() {
// Disable text processing for comments.
$this->drupalLogin($this->admin_user);
$edit = array('instance[settings][text_processing]' => 0);
$this->drupalPost('admin/structure/types/manage/article/comment/fields/comment_body', $edit, t('Save settings'));
$this->drupalPost('admin/structure/types/manage/article/comment/fields/comment.comment_node_article.comment_body', $edit, t('Save settings'));
// Post a comment without an explicit subject.
$this->drupalLogin($this->web_user);
......
......@@ -179,9 +179,7 @@ function contact_entity_bundle_info() {
$bundles['contact_message'][$config->get('id')] = array(
'label' => $config->get('label'),
'admin' => array(
'path' => 'admin/structure/contact/manage/%contact_category',
'real path' => 'admin/structure/contact/manage/' . $config->get('id'),
'bundle argument' => 4,
'access arguments' => array('administer contact forms'),
),
);
......
This diff is collapsed.
This diff is collapsed.
services:
field_ui.subscriber:
class: Drupal\field_ui\Routing\RouteSubscriber
arguments: ['@plugin.manager.entity']
tags:
- { name: event_subscriber }
access_check.field_ui.view_mode:
class: Drupal\field_ui\Access\ViewModeAccessCheck
tags:
- { name: access_check }
<?php
/**
* @file
* Contains \Drupal\field_ui\Access\ViewModeAccessCheck.
*/
namespace Drupal\field_ui\Access;
use Drupal\Core\Access\AccessCheckInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\HttpFoundation\Request;
/**
* Allows access to routes to be controlled by an '_access' boolean parameter.
*/
class ViewModeAccessCheck implements AccessCheckInterface {
/**
* {@inheritdoc}
*/
public function applies(Route $route) {
return array_key_exists('_field_ui_view_mode_access', $route->getRequirements());
}
/**
* {@inheritdoc}
*/
public function access(Route $route, Request $request) {
if ($entity_type = $request->attributes->get('entity_type')) {
$bundle = $request->attributes->get('bundle');
$view_mode = $request->attributes->get('view_mode');
$view_mode_settings = field_view_mode_settings($entity_type, $bundle);
$visibility = ($view_mode == 'default') || !empty($view_mode_settings[$view_mode]['custom_settings']);
if ($visibility) {
$permission = $route->getRequirement('_field_ui_view_mode_access');
return user_access($permission);
}
}
}
}
......@@ -41,7 +41,10 @@ public function getFormID() {
/**
* Implements \Drupal\Core\Form\FormInterface::buildForm().
*/
public function buildForm(array $form, array &$form_state) {
public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL, $view_mode = NULL) {
parent::buildForm($form, $form_state, $entity_type, $bundle);
$this->view_mode = (isset($view_mode) ? $view_mode : 'default');
// Gather type information.
$instances = field_info_instances($this->entity_type, $this->bundle);
$field_types = field_info_field_types();
......
......@@ -14,16 +14,6 @@
*/
class FieldOverview extends OverviewBase {
/**
* Overrides Drupal\field_ui\OverviewBase::__construct().
*/
public function __construct($entity_type, $bundle, $view_mode = NULL) {
$this->entity_type = $entity_type;
$this->bundle = $bundle;
$this->view_mode = 'form';
$this->adminPath = field_ui_bundle_admin_path($this->entity_type, $this->bundle);
}
/**
* Implements Drupal\field_ui\OverviewBase::getRegions().
*/
......@@ -52,7 +42,10 @@ public function getFormID() {
/**
* Implements \Drupal\Core\Form\FormInterface::buildForm().
*/
public function buildForm(array $form, array &$form_state) {
public function buildForm(array $form, array &$form_state, $entity_type = NULL, $bundle = NULL) {
parent::buildForm($form, $form_state, $entity_type, $bundle);
$this->view_mode = 'form';
// When displaying the form, make sure the list of fields is up-to-date.
if (empty($form_state['post'])) {
field_info_cache_clear();
......@@ -94,7 +87,7 @@ public function buildForm(array $form, array &$form_state) {
// Fields.
foreach ($instances as $name => $instance) {
$field = field_info_field($instance['field_name']);
$admin_field_path = $this->adminPath . '/fields/' . $instance['field_name'];
$admin_field_path = $this->adminPath . '/fields/' . $instance->id();
$table[$name] = array(
'#attributes' => array('class' => array('draggable', 'tabledrag-leaf')),
'#row_type' => 'field',
......@@ -570,8 +563,9 @@ public function submitForm(array &$form, array &$form_state) {
// Create the field and instance.
try {
field_create_field($field);
field_create_instance($instance);
$this->entityManager->getStorageController('field_entity')->create($field)->save();
$new_instance = $this->entityManager->getStorageController('field_instance')->create($instance);
$new_instance->save();
// Make sure the field is displayed in the 'default' view mode (using
// default formatter and settings). It stays hidden for other view
......@@ -582,8 +576,8 @@ public function submitForm(array &$form, array &$form_state) {
// 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';
$destinations[] = $this->adminPath . '/fields/' . $field['field_name'];
$destinations[] = $this->adminPath. '/fields/' . $new_instance->id() . '/field-settings';
$destinations[] = $this->adminPath . '/fields/' . $new_instance->id();
// Store new field information for any additional submit handlers.
$form_state['fields_added']['_add_new_field'] = $field['field_name'];
......@@ -613,7 +607,8 @@ public function submitForm(array &$form, array &$form_state) {
);
try {
field_create_instance($instance);
$new_instance = $this->entityManager->getStorageController('field_instance')->create($instance);
$new_instance->save();
// Make sure the field is displayed in the 'default' view mode (using
// default formatter and settings). It stays hidden for other view
......@@ -622,7 +617,7 @@ public function submitForm(array &$form, array &$form_state) {
->setComponent($field['field_name'])
->save();
$destinations[] = $this->adminPath . '/fields/' . $instance['field_name'];
$destinations[] = $this->adminPath . '/fields/' . $new_instance->id();
// Store new field information for any additional submit handlers.
$form_state['fields_added']['_add_existing_field'] = $instance['field_name'];
}
......
<?php
/**
* @file
* Contains \Drupal\field_ui\Form\FieldDeleteForm.
*/
namespace Drupal\field_ui\Form;
use Drupal\Core\Form\ConfirmFormBase;
use Drupal\field\Plugin\Core\Entity\FieldInstance;
/**
* Provides a form for removing a field instance from a bundle.
*/
class FieldDeleteForm extends ConfirmFormBase {
/**
* The field instance being deleted.
*
* @var \Drupal\field\Plugin\Core\Entity\FieldInstance
*/
protected $instance;
/**
* {@inheritdoc}
*/
public function getFormID() {
return 'field_ui_field_delete_form';
}
/**
* {@inheritdoc}
*/
protected function getQuestion() {
return t('Are you sure you want to delete the field %field?', array('%field' => $this->instance->label()));
}
/**
* {@inheritdoc}
*/
protected function getConfirmText() {
return t('Delete');
}
/**
* {@inheritdoc}
*/
protected function getCancelPath() {
return field_ui_bundle_admin_path($this->instance->entity_type, $this->instance->bundle) . '/fields';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state, FieldInstance $field_instance = NULL) {
$this->instance = $form_state['instance'] = $field_instance;
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
form_load_include($form_state, 'inc', 'field_ui', 'field_ui.admin');
$field = $this->instance->getField();
$bundles = entity_get_bundles();
$bundle_label = $bundles[$this->instance->entity_type][$this->instance->bundle]['label'];
if ($field && !$field['locked']) {
$this->instance->delete();
drupal_set_message(t('The field %field has been deleted from the %type content type.', array('%field' => $this->instance->label(), '%type' => $bundle_label)));
}
else {
drupal_set_message(t('There was a problem removing the %field from the %type content type.', array('%field' => $this->instance->label(), '%type' => $bundle_label)), 'error');
}
$admin_path = field_ui_bundle_admin_path($this->instance->entity_type, $this->instance->bundle);
$form_state['redirect'] = field_ui_get_destinations(array($admin_path . '/fields'));
// Fields are purged on cron. However field module prevents disabling modules
// when field types they provided are used in a field until it is fully
// purged. In the case that a field has minimal or no content, a single call
// to field_purge_batch() will remove it from the system. Call this with a
// low batch limit to avoid administrators having to wait for cron runs when
// removing instances that meet this criteria.
field_purge_batch(10);
}
}
<?php
/**
* @file
* Contains \Drupal\field_ui\Form\FieldSettingsForm.
*/
namespace Drupal\field_ui\Form;
use Drupal\Core\Form\FormInterface;
use Drupal\field\Plugin\Core\Entity\FieldInstance;
use Drupal\field\Field;
/**
* Provides a form for the field settings edit page.
*/
class FieldSettingsForm implements FormInterface {
/**
* The field instance being edited.
*
* @var \Drupal\field\Plugin\Core\Entity\FieldInstance
*/
protected $instance;
/**
* {@inheritdoc}
*/
public function getFormID() {
return 'field_ui_field_settings_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state, FieldInstance $field_instance = NULL) {
$this->instance = $form_state['instance'] = $field_instance;
$field = $this->instance->getField();
$form['#field'] = $field;
drupal_set_title($this->instance->label());
$description = '<p>' . t('These settings apply to the %field field everywhere it is used. These settings impact the way that data is stored in the database and cannot be changed once data has been created.', array('%field' => $this->instance->label())) . '</p>';
// Create a form structure for the field values.
$form['field'] = array(
'#prefix' => $description,
'#tree' => TRUE,
);
// See if data already exists for this field.
// If so, prevent changes to the field settings.
$has_data = field_has_data($field);
if ($has_data) {
$form['field']['#prefix'] = '<div class="messages error">' . t('There is data for this field in the database. The field settings can no longer be changed.') . '</div>' . $form['field']['#prefix'];
}
// Build the configurable field values.
$cardinality = $field['cardinality'];
$form['field']['container'] = array(
// We can't use the container element because it doesn't support the title
// or description properties.
'#type' => 'item',
'#field_prefix' => '<div class="container-inline">',
'#field_suffix' => '</div>',
'#title' => t('Maximum number of values users can enter'),
);
$form['field']['container']['cardinality'] = array(
'#type' => 'select',
'#options' => drupal_map_assoc(range(1, 5)) + array(FIELD_CARDINALITY_UNLIMITED => t('Unlimited')) + array('other' => t('More')),
'#default_value' => ($cardinality < 6) ? $cardinality : 'other',
);
// @todo Convert when http://drupal.org/node/1207060 gets in.
$form['field']['container']['cardinality_other'] = array(
'#type' => 'number',
'#default_value' => $cardinality > 5 ? $cardinality : 6,
'#min' => 1,
'#title' => t('Custom value'),
'#title_display' => 'invisible',
'#states' => array(
'visible' => array(
':input[name="field[container][cardinality]"]' => array('value' => 'other'),
),
),
);
if (field_behaviors_widget('multiple values', $this->instance) == FIELD_BEHAVIOR_DEFAULT) {
$form['field']['container']['#description'] = t('%unlimited will provide an %add-more button so users can add as many values as they like.', array(
'%unlimited' => t('Unlimited'),
'%add-more' => t('Add another item'),
));
}
// Build the non-configurable field values.
$form['field']['field_name'] = array('#type' => 'value', '#value' => $field['field_name']);
$form['field']['type'] = array('#type' => 'value', '#value' => $field['type']);
$form['field']['module'] = array('#type' => 'value', '#value' => $field['module']);
$form['field']['active'] = array('#type' => 'value', '#value' => $field['active']);
// Add settings provided by the field module. The field module is
// responsible for not returning settings that cannot be changed if
// the field already has data.
$form['field']['settings'] = array(
'#weight' => 10,
);
$additions = \Drupal::moduleHandler()->invoke($field['module'], 'field_settings_form', array($field, $this->instance, $has_data));
if (is_array($additions)) {
$form['field']['settings'] += $additions;
}
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Save field settings'));
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, array &$form_state) {
// Validate field cardinality.
$cardinality = $form_state['values']['field']['container']['cardinality'];
$cardinality_other = $form_state['values']['field']['container']['cardinality_other'];
if ($cardinality == 'other' && empty($cardinality_other)) {
form_error($form['field']['container']['cardinality_other'], t('Number of values is required.'));
}
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
form_load_include($form_state, 'inc', 'field_ui', 'field_ui.admin');
$form_values = $form_state['values'];
$field_values = $form_values['field'];
// Save field cardinality.
$cardinality = $field_values['container']['cardinality'];
$cardinality_other = $field_values['container']['cardinality_other'];
$cardinality_other = $form_state['values']['field']['container']['cardinality_other'];
if ($cardinality == 'other') {
$cardinality = $cardinality_other;
}
$field_values['cardinality'] = $cardinality;
unset($field_values['container']);
// Merge incoming form values into the existing field.
$field = Field::fieldInfo()->getField($field_values['field_name']);
foreach ($field_values as $key => $value) {
$field[$key] = $value;
}
// Update the field.
try {
$field->save();
drupal_set_message(t('Updated field %label field settings.', array('%label' => $this->instance->label())));
$form_state['redirect'] = field_ui_next_destination($this->instance->entity_type, $this->instance->bundle);
}
catch (Exception $e) {
drupal_set_message(t('Attempt to update field %label failed: %message.', array('%label' => $this->instance->label(), '%message' => $e->getMessage())), 'error');
}
}
}
<?php
/**
* @file
* Contains \Drupal\field_ui\Form\FieldWidgetTypeForm.
*/
namespace Drupal\field_ui\Form;
use Drupal\Core\Form\FormInterface;
use Drupal\Core\ControllerInterface;
use Drupal\field\Plugin\Core\Entity\FieldInstance;
use Drupal\field\Plugin\Type\Widget\WidgetPluginManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a form for the widget selection form.
*/
class FieldWidgetTypeForm implements FormInterface, ControllerInterface {
/**
* The field instance being edited.
*
* @var \Drupal\field\Plugin\Core\Entity\FieldInstance
*/
protected $instance;
/**
* The field widget plugin manager.
*
* @var \Drupal\field\Plugin\Type\Widget\WidgetPluginManager
*/
protected $widgetManager;
/**
* Constructs a new FieldWidgetTypeForm object.
*
* @param \Drupal\field\Plugin\Type\Widget\WidgetPluginManager $widget_manager
* The field widget plugin manager.
*/
public function __construct(WidgetPluginManager $widget_manager) {
$this->widgetManager = $widget_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.field.widget')
);
}
/**
* {@inheritdoc}
*/
public function getFormID() {
return 'field_ui_widget_type_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, array &$form_state, FieldInstance $field_instance = NULL) {
$this->instance = $form_state['instance'] = $field_instance;
form_load_include($form_state, 'inc', 'field_ui', 'field_ui.admin');
drupal_set_title($this->instance['label']);
$bundle = $this->instance['bundle'];
$entity_type = $this->instance['entity_type'];
$field_name = $this->instance['field_name'];
$field = $this->instance->getField();
$bundles = entity_get_bundles();
$bundle_label = $bundles[$entity_type][$bundle]['label'];
$form = array(
'#bundle' => $bundle,
'#entity_type' => $entity_type,
'#field_name' => $field_name,
);
$form['widget_type'] = array(
'#type' => 'select',
'#title' => t('Widget type'),
'#required' => TRUE,
'#options' => field_ui_widget_type_options($field['type']),
'#default_value' => $this->instance->getWidget()->getPluginId(),
'#description' => t('The type of form element you would like to present to the user when creating this field in the %type type.', array('%type' => $bundle_label)),
);
$form['actions'] = array('#type' => 'actions');
$form['actions']['submit'] = array('#type' => 'submit', '#value' => t('Continue'));
return $form;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, array &$form_state) {
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, array &$form_state) {
$form_values = $form_state['values'];
$bundle = $form['#bundle'];
$entity_type = $form['#entity_type'];
$field_name = $form['#field_name'];
// Retrieve the stored instance settings to merge with the incoming values.
$instance = field_read_instance($entity_type, $field_name, $bundle);
// Set the right module information.
$widget_type = $this->widgetManager->getDefinition($form_values['widget_type']);
$widget_module = $widget_type['module'];
$instance['widget']['type'] = $form_values['widget_type'];
$instance['widget']['module'] = $widget_module;
try {
$instance->save();
drupal_set_message(t('Changed the widget for field %label.', array('%label' => $instance['label'])));
if ($instance['required'] && empty($instance['default_value']) && empty($instance['default_value_function']) && $instance['widget']['type'] == 'field_hidden') {
drupal_set_message(t('Field %label is required and uses the "hidden" widget. You might want to configure a default value.', array('%label' => $instance['label'])), 'warning');
}
}
catch (Exception $e) {
drupal_set_message(t('There was a problem changing the widget for field %label.', array('%label' => $instance['label'])), 'error');
}
$form_state['redirect'] = field_ui_next_destination($entity_type, $bundle);
}