Issue #2095195 by yched, fago, Berdir, amateescu, swentel, pfrenssen, Xano: Remove deprecated field_attach_form_*().
parent
0b6e47e23d
commit
83b797dfce
|
|
@ -7,7 +7,8 @@
|
||||||
|
|
||||||
namespace Drupal\Core\Entity;
|
namespace Drupal\Core\Entity;
|
||||||
|
|
||||||
use Drupal\Core\Language\Language;
|
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
||||||
|
use Drupal\entity\Entity\EntityFormDisplay;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -15,7 +16,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
*
|
*
|
||||||
* @see \Drupal\Core\ContentEntityBase
|
* @see \Drupal\Core\ContentEntityBase
|
||||||
*/
|
*/
|
||||||
class ContentEntityFormController extends EntityFormController {
|
class ContentEntityFormController extends EntityFormController implements ContentEntityFormControllerInterface {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entity manager.
|
* The entity manager.
|
||||||
|
|
@ -47,16 +48,8 @@ class ContentEntityFormController extends EntityFormController {
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function form(array $form, array &$form_state) {
|
public function form(array $form, array &$form_state) {
|
||||||
$entity = $this->entity;
|
$form = parent::form($form, $form_state);
|
||||||
// @todo Exploit the Field API to generate the default widgets for the
|
$this->getFormDisplay($form_state)->buildForm($this->entity, $form, $form_state);
|
||||||
// entity fields.
|
|
||||||
if ($entity->getEntityType()->isFieldable()) {
|
|
||||||
field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a process callback so we can assign weights and hide extra fields.
|
|
||||||
$form['#process'][] = array($this, 'processForm');
|
|
||||||
|
|
||||||
return $form;
|
return $form;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,27 +59,7 @@ class ContentEntityFormController extends EntityFormController {
|
||||||
public function validate(array $form, array &$form_state) {
|
public function validate(array $form, array &$form_state) {
|
||||||
$this->updateFormLangcode($form_state);
|
$this->updateFormLangcode($form_state);
|
||||||
$entity = $this->buildEntity($form, $form_state);
|
$entity = $this->buildEntity($form, $form_state);
|
||||||
$entity_type = $entity->getEntityTypeId();
|
$this->getFormDisplay($form_state)->validateFormValues($entity, $form, $form_state);
|
||||||
$entity_langcode = $entity->language()->id;
|
|
||||||
|
|
||||||
$violations = array();
|
|
||||||
foreach ($entity as $field_name => $field) {
|
|
||||||
$field_violations = $field->validate();
|
|
||||||
if (count($field_violations)) {
|
|
||||||
$violations[$field_name] = $field_violations;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map errors back to form elements.
|
|
||||||
if ($violations) {
|
|
||||||
foreach ($violations as $field_name => $field_violations) {
|
|
||||||
$field_state = field_form_get_state($form['#parents'], $field_name, $form_state);
|
|
||||||
$field_state['constraint_violations'] = $field_violations;
|
|
||||||
field_form_set_state($form['#parents'], $field_name, $form_state, $field_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
field_invoke_method('flagErrors', _field_invoke_widget_target($form_state['form_display']), $entity, $form, $form_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
// @todo Remove this.
|
// @todo Remove this.
|
||||||
// Execute legacy global validation handlers.
|
// Execute legacy global validation handlers.
|
||||||
|
|
@ -102,6 +75,10 @@ class ContentEntityFormController extends EntityFormController {
|
||||||
// language.
|
// language.
|
||||||
$langcode = $this->getFormLangcode($form_state);
|
$langcode = $this->getFormLangcode($form_state);
|
||||||
$this->entity = $this->entity->getTranslation($langcode);
|
$this->entity = $this->entity->getTranslation($langcode);
|
||||||
|
|
||||||
|
$form_display = EntityFormDisplay::collectRenderDisplay($this->entity, $this->getOperation());
|
||||||
|
$this->setFormDisplay($form_display, $form_state);
|
||||||
|
|
||||||
parent::init($form_state);
|
parent::init($form_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,37 +105,33 @@ class ContentEntityFormController extends EntityFormController {
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function buildEntity(array $form, array &$form_state) {
|
protected function copyFormValuesToEntity(EntityInterface $entity, array $form, array &$form_state) {
|
||||||
$entity = clone $this->entity;
|
// First, extract values from widgets.
|
||||||
$entity_type_id = $entity->getEntityTypeId();
|
$extracted = $this->getFormDisplay($form_state)->extractFormValues($entity, $form, $form_state);
|
||||||
$entity_type = \Drupal::entityManager()->getDefinition($entity_type_id);
|
|
||||||
|
|
||||||
// @todo Exploit the Entity Field API to process the submitted field values.
|
// Then extract the values of fields that are not rendered through widgets,
|
||||||
// Copy top-level form values that are entity fields but not handled by
|
// by simply copying from top-level form values. This leaves the fields
|
||||||
// field API without changing existing entity fields that are not being
|
// that are not being edited within this form untouched.
|
||||||
// edited by this form. Values of fields handled by field API are copied
|
foreach ($form_state['values'] as $name => $values) {
|
||||||
// by field_attach_extract_form_values() below.
|
if ($entity->hasField($name) && !isset($extracted[$name])) {
|
||||||
$values_excluding_fields = $entity_type->isFieldable() ? array_diff_key($form_state['values'], field_info_instances($entity_type_id, $entity->bundle())) : $form_state['values'];
|
$entity->set($name, $values);
|
||||||
$definitions = $entity->getFieldDefinitions();
|
|
||||||
|
|
||||||
foreach ($values_excluding_fields as $key => $value) {
|
|
||||||
if (isset($definitions[$key])) {
|
|
||||||
$entity->$key = $value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Invoke all specified builders for copying form values to entity fields.
|
/**
|
||||||
if (isset($form['#entity_builders'])) {
|
* {@inheritdoc}
|
||||||
foreach ($form['#entity_builders'] as $function) {
|
*/
|
||||||
call_user_func_array($function, array($entity_type_id, $entity, &$form, &$form_state));
|
public function getFormDisplay(array $form_state) {
|
||||||
}
|
return isset($form_state['form_display']) ? $form_state['form_display'] : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invoke field API for copying field values.
|
/**
|
||||||
if ($entity_type->isFieldable()) {
|
* {@inheritdoc}
|
||||||
field_attach_extract_form_values($entity, $form, $form_state, array('langcode' => $this->getFormLangcode($form_state)));
|
*/
|
||||||
}
|
public function setFormDisplay(EntityFormDisplayInterface $form_display, array &$form_state) {
|
||||||
return $entity;
|
$form_state['form_display'] = $form_display;
|
||||||
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\Core\Entity\ContentEntityFormControllerInterface.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\Core\Entity;
|
||||||
|
|
||||||
|
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Defines a common interface for content entity form controller classes.
|
||||||
|
*/
|
||||||
|
interface ContentEntityFormControllerInterface extends EntityFormControllerInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the form display.
|
||||||
|
*
|
||||||
|
* @param array $form_state
|
||||||
|
* An associative array containing the current state of the form.
|
||||||
|
*
|
||||||
|
* @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface.
|
||||||
|
* The current form display.
|
||||||
|
*/
|
||||||
|
public function getFormDisplay(array $form_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the form display.
|
||||||
|
*
|
||||||
|
* Sets the form display which will be used for populating form element
|
||||||
|
* defaults.
|
||||||
|
*
|
||||||
|
* @param \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display
|
||||||
|
* The form display that the current form operates with.
|
||||||
|
* @param array $form_state
|
||||||
|
* An associative array containing the current state of the form.
|
||||||
|
*/
|
||||||
|
public function setFormDisplay(EntityFormDisplayInterface $form_display, array &$form_state);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -7,9 +7,153 @@
|
||||||
|
|
||||||
namespace Drupal\Core\Entity\Display;
|
namespace Drupal\Core\Entity\Display;
|
||||||
|
|
||||||
|
use Drupal\Core\Entity\ContentEntityInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a common interface for entity form displays.
|
* Provides a common interface for entity form displays.
|
||||||
*/
|
*/
|
||||||
interface EntityFormDisplayInterface extends EntityDisplayInterface {
|
interface EntityFormDisplayInterface extends EntityDisplayInterface {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds field widgets to an entity form.
|
||||||
|
*
|
||||||
|
* The form elements for the entity's fields are added by reference as direct
|
||||||
|
* children in the $form parameter. This parameter can be a full form
|
||||||
|
* structure (most common case for entity edit forms), or a sub-element of a
|
||||||
|
* larger form.
|
||||||
|
*
|
||||||
|
* By default, submitted field values appear at the top-level of
|
||||||
|
* $form_state['values']. A different location within $form_state['values']
|
||||||
|
* can be specified by setting the '#parents' property on the incoming $form
|
||||||
|
* parameter. Because of name clashes, two instances of the same field cannot
|
||||||
|
* appear within the same $form element, or within the same '#parents' space.
|
||||||
|
*
|
||||||
|
* Sample resulting structure in $form:
|
||||||
|
* @code
|
||||||
|
* '#parents' => The location of field values in $form_state['values'],
|
||||||
|
* '#entity_type' => The name of the entity type,
|
||||||
|
* '#bundle' => The name of the bundle,
|
||||||
|
* // One sub-array per field appearing in the entity, keyed by field name.
|
||||||
|
* // The structure of the array differs slightly depending on whether the
|
||||||
|
* // widget is 'single-value' (provides the input for one field value,
|
||||||
|
* // most common case), and will therefore be repeated as many times as
|
||||||
|
* // needed, or 'multiple-values' (one single widget allows the input of
|
||||||
|
* // several values, e.g checkboxes, select box...).
|
||||||
|
* 'field_foo' => array(
|
||||||
|
* '#access' => TRUE if the current user has 'edit' grants for the field,
|
||||||
|
* FALSE if not.
|
||||||
|
* 'widget' => array(
|
||||||
|
* '#field_name' => The name of the field,
|
||||||
|
* '#language' => $langcode,
|
||||||
|
* '#field_parents' => The 'parents' space for the field in the form,
|
||||||
|
* equal to the #parents property of the $form parameter received by
|
||||||
|
* this method,
|
||||||
|
* '#required' => Whether or not the field is required,
|
||||||
|
* '#title' => The label of the field instance,
|
||||||
|
* '#description' => The description text for the field instance,
|
||||||
|
*
|
||||||
|
* // Only for 'single' widgets:
|
||||||
|
* '#theme' => 'field_multiple_value_form',
|
||||||
|
* '#cardinality' => The field cardinality,
|
||||||
|
* '#cardinality_multiple => TRUE if the field can contain multiple
|
||||||
|
* items, FALSE otherwise.
|
||||||
|
* // One sub-array per copy of the widget, keyed by delta.
|
||||||
|
* 0 => array(
|
||||||
|
* '#entity_type' => The name of the entity type,
|
||||||
|
* '#bundle' => The name of the bundle,
|
||||||
|
* '#field_name' => The name of the field,
|
||||||
|
* '#field_parents' => The 'parents' space for the field in the form,
|
||||||
|
* equal to the #parents property of the $form parameter,
|
||||||
|
* '#title' => The title to be displayed by the widget,
|
||||||
|
* '#default_value' => The field value for delta 0,
|
||||||
|
* '#required' => Whether the widget should be marked required,
|
||||||
|
* '#delta' => 0,
|
||||||
|
* // The remaining elements in the sub-array depend on the widget.
|
||||||
|
* '#type' => The type of the widget,
|
||||||
|
* ...
|
||||||
|
* ),
|
||||||
|
* 1 => array(
|
||||||
|
* ...
|
||||||
|
* ),
|
||||||
|
*
|
||||||
|
* // Only for multiple widgets:
|
||||||
|
* '#entity_type' => The name of the entity type,
|
||||||
|
* '#bundle' => $instance['bundle'],
|
||||||
|
* // The remaining elements in the sub-array depend on the widget.
|
||||||
|
* '#type' => The type of the widget,
|
||||||
|
* ...
|
||||||
|
* ),
|
||||||
|
* ...
|
||||||
|
* ),
|
||||||
|
* )
|
||||||
|
* @endcode
|
||||||
|
*
|
||||||
|
* Additionally, some processing data is placed in $form_state, and can be
|
||||||
|
* accessed by field_form_get_state() and field_form_set_state().
|
||||||
|
*
|
||||||
|
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
||||||
|
* The entity.
|
||||||
|
* @param array $form
|
||||||
|
* The form structure to fill in. This can be a full form structure, or a
|
||||||
|
* sub-element of a larger form. The #parents property can be set to
|
||||||
|
* control the location of submitted field values within
|
||||||
|
* $form_state['values']. If not specified, $form['#parents'] is set to an
|
||||||
|
* empty array, which results in field values located at the top-level of
|
||||||
|
* $form_state['values'].
|
||||||
|
* @param array $form_state
|
||||||
|
* The form state.
|
||||||
|
*/
|
||||||
|
public function buildForm(ContentEntityInterface $entity, array &$form, array &$form_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates submitted widget values and sets the corresponding form errors.
|
||||||
|
*
|
||||||
|
* There are two levels of validation for fields in forms: widget validation
|
||||||
|
* and field validation.
|
||||||
|
* - Widget validation steps are specific to a given widget's own form
|
||||||
|
* structure and UI metaphors. They are executed during normal form
|
||||||
|
* validation, usually through Form API's #element_validate property.
|
||||||
|
* Errors reported at this level are typically those that prevent the
|
||||||
|
* extraction of proper field values from the submitted form input.
|
||||||
|
* - If no form / widget errors were reported for the field, field validation
|
||||||
|
* steps are performed according to the "constraints" specified by the
|
||||||
|
* field definition. Those are independent of the specific widget being
|
||||||
|
* used in a given form, and are also performed on REST entity submissions.
|
||||||
|
*
|
||||||
|
* This function performs field validation in the context of a form submission.
|
||||||
|
* It reports field constraint violations as form errors on the correct form
|
||||||
|
* elements.
|
||||||
|
*
|
||||||
|
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
||||||
|
* The entity.
|
||||||
|
* @param array $form
|
||||||
|
* The form structure where field elements are attached to. This might be a
|
||||||
|
* full form structure, or a sub-element of a larger form.
|
||||||
|
* @param array $form_state
|
||||||
|
* The form state.
|
||||||
|
*/
|
||||||
|
public function validateFormValues(ContentEntityInterface $entity, array &$form, array &$form_state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts field values from the submitted widget values into the entity.
|
||||||
|
*
|
||||||
|
* This accounts for drag-and-drop reordering of field values, and filtering
|
||||||
|
* of empty values.
|
||||||
|
*
|
||||||
|
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
||||||
|
* The entity.
|
||||||
|
* @param array $form
|
||||||
|
* The form structure where field elements are attached to. This might be a
|
||||||
|
* full form structure, or a sub-element of a larger form.
|
||||||
|
* @param array $form_state
|
||||||
|
* The form state.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
* An array whose keys and values are the keys of the top-level entries in
|
||||||
|
* $form_state['values'] that have been processed. The remaining entries, if
|
||||||
|
* any, do not correspond to widgets and should be extracted manually by
|
||||||
|
* the caller if needed.
|
||||||
|
*/
|
||||||
|
public function extractFormValues(ContentEntityInterface $entity, array &$form, array &$form_state);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,8 @@
|
||||||
|
|
||||||
namespace Drupal\Core\Entity;
|
namespace Drupal\Core\Entity;
|
||||||
|
|
||||||
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
|
||||||
use Drupal\Core\Form\FormBase;
|
use Drupal\Core\Form\FormBase;
|
||||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||||
use Drupal\entity\Entity\EntityFormDisplay;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for entity form controllers.
|
* Base class for entity form controllers.
|
||||||
|
|
@ -122,9 +120,6 @@ class EntityFormController extends FormBase implements EntityFormControllerInter
|
||||||
// Prepare the entity to be presented in the entity form.
|
// Prepare the entity to be presented in the entity form.
|
||||||
$this->prepareEntity();
|
$this->prepareEntity();
|
||||||
|
|
||||||
$form_display = EntityFormDisplay::collectRenderDisplay($this->entity, $this->getOperation());
|
|
||||||
$this->setFormDisplay($form_display, $form_state);
|
|
||||||
|
|
||||||
// Invoke the prepare form hooks.
|
// Invoke the prepare form hooks.
|
||||||
$this->prepareInvokeAll('entity_prepare_form', $form_state);
|
$this->prepareInvokeAll('entity_prepare_form', $form_state);
|
||||||
$this->prepareInvokeAll($this->entity->getEntityTypeId() . '_prepare_form', $form_state);
|
$this->prepareInvokeAll($this->entity->getEntityTypeId() . '_prepare_form', $form_state);
|
||||||
|
|
@ -137,13 +132,8 @@ class EntityFormController extends FormBase implements EntityFormControllerInter
|
||||||
*/
|
*/
|
||||||
public function form(array $form, array &$form_state) {
|
public function form(array $form, array &$form_state) {
|
||||||
$entity = $this->entity;
|
$entity = $this->entity;
|
||||||
// @todo Exploit the Field API to generate the default widgets for the
|
|
||||||
// entity properties.
|
|
||||||
if ($entity->getEntityType()->isFieldable()) {
|
|
||||||
field_attach_form($entity, $form, $form_state, $this->getFormLangcode($form_state));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add a process callback so we can assign weights and hide extra fields.
|
// Add a process callback.
|
||||||
$form['#process'][] = array($this, 'processForm');
|
$form['#process'][] = array($this, 'processForm');
|
||||||
|
|
||||||
if (!isset($form['langcode'])) {
|
if (!isset($form['langcode'])) {
|
||||||
|
|
@ -168,25 +158,6 @@ class EntityFormController extends FormBase implements EntityFormControllerInter
|
||||||
// to the entity object, hence we must restore it.
|
// to the entity object, hence we must restore it.
|
||||||
$this->entity = $form_state['controller']->getEntity();
|
$this->entity = $form_state['controller']->getEntity();
|
||||||
|
|
||||||
// Assign the weights configured in the form display.
|
|
||||||
foreach ($this->getFormDisplay($form_state)->getComponents() as $name => $options) {
|
|
||||||
if (isset($element[$name])) {
|
|
||||||
$element[$name]['#weight'] = $options['weight'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Hide or assign weights for extra fields.
|
|
||||||
$extra_fields = field_info_extra_fields($this->entity->getEntityTypeId(), $this->entity->bundle(), 'form');
|
|
||||||
foreach ($extra_fields as $extra_field => $info) {
|
|
||||||
$component = $this->getFormDisplay($form_state)->getComponent($extra_field);
|
|
||||||
if (!$component) {
|
|
||||||
$element[$extra_field]['#access'] = FALSE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$element[$extra_field]['#weight'] = $component['weight'];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $element;
|
return $element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,7 +330,7 @@ class EntityFormController extends FormBase implements EntityFormControllerInter
|
||||||
// controller of the current request.
|
// controller of the current request.
|
||||||
$form_state['controller'] = $this;
|
$form_state['controller'] = $this;
|
||||||
|
|
||||||
$this->copyFormValuesToEntity($entity, $form_state);
|
$this->copyFormValuesToEntity($entity, $form, $form_state);
|
||||||
|
|
||||||
// Invoke all specified builders for copying form values to entity
|
// Invoke all specified builders for copying form values to entity
|
||||||
// properties.
|
// properties.
|
||||||
|
|
@ -380,10 +351,12 @@ class EntityFormController extends FormBase implements EntityFormControllerInter
|
||||||
*
|
*
|
||||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||||
* The entity the current form should operate upon.
|
* The entity the current form should operate upon.
|
||||||
|
* @param array $form
|
||||||
|
* A nested array of form elements comprising the form.
|
||||||
* @param array $form_state
|
* @param array $form_state
|
||||||
* An associative array containing the current state of the form.
|
* An associative array containing the current state of the form.
|
||||||
*/
|
*/
|
||||||
protected function copyFormValuesToEntity(EntityInterface $entity, array $form_state) {
|
protected function copyFormValuesToEntity(EntityInterface $entity, array $form, array &$form_state) {
|
||||||
// @todo: This relies on a method that only exists for config and content
|
// @todo: This relies on a method that only exists for config and content
|
||||||
// entities, in a different way. Consider moving this logic to a config
|
// entities, in a different way. Consider moving this logic to a config
|
||||||
// entity specific implementation.
|
// entity specific implementation.
|
||||||
|
|
@ -427,27 +400,12 @@ class EntityFormController extends FormBase implements EntityFormControllerInter
|
||||||
if (function_exists($function)) {
|
if (function_exists($function)) {
|
||||||
// Ensure we pass an updated translation object and form display at
|
// Ensure we pass an updated translation object and form display at
|
||||||
// each invocation, since they depend on form state which is alterable.
|
// each invocation, since they depend on form state which is alterable.
|
||||||
$args = array($this->entity, $this->getFormDisplay($form_state), $this->operation, &$form_state);
|
$args = array($this->entity, $this->operation, &$form_state);
|
||||||
call_user_func_array($function, $args);
|
call_user_func_array($function, $args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getFormDisplay(array $form_state) {
|
|
||||||
return isset($form_state['form_display']) ? $form_state['form_display'] : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function setFormDisplay(EntityFormDisplayInterface $form_display, array &$form_state) {
|
|
||||||
$form_state['form_display'] = $form_display;
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
namespace Drupal\Core\Entity;
|
namespace Drupal\Core\Entity;
|
||||||
|
|
||||||
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
|
||||||
use Drupal\Core\Extension\ModuleHandlerInterface;
|
use Drupal\Core\Extension\ModuleHandlerInterface;
|
||||||
use Drupal\Core\Form\BaseFormIdInterface;
|
use Drupal\Core\Form\BaseFormIdInterface;
|
||||||
use Drupal\Core\StringTranslation\TranslationInterface;
|
use Drupal\Core\StringTranslation\TranslationInterface;
|
||||||
|
|
@ -57,30 +56,6 @@ interface EntityFormControllerInterface extends BaseFormIdInterface {
|
||||||
*/
|
*/
|
||||||
public function getOperation();
|
public function getOperation();
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the form display.
|
|
||||||
*
|
|
||||||
* @param array $form_state
|
|
||||||
* An associative array containing the current state of the form.
|
|
||||||
*
|
|
||||||
* @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface.
|
|
||||||
* The current form display.
|
|
||||||
*/
|
|
||||||
public function getFormDisplay(array $form_state);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the form display.
|
|
||||||
*
|
|
||||||
* Sets the form display which will be used for populating form element
|
|
||||||
* defaults.
|
|
||||||
*
|
|
||||||
* @param \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display
|
|
||||||
* The form display that the current form operates with.
|
|
||||||
* @param array $form_state
|
|
||||||
* An associative array containing the current state of the form.
|
|
||||||
*/
|
|
||||||
public function setFormDisplay(EntityFormDisplayInterface $form_display, array &$form_state);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the form entity.
|
* Returns the form entity.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -331,15 +331,9 @@ class FieldItemList extends ItemList implements FieldItemListInterface {
|
||||||
$widget->extractFormValues($this, $element, $form_state);
|
$widget->extractFormValues($this, $element, $form_state);
|
||||||
$violations = $this->validate();
|
$violations = $this->validate();
|
||||||
|
|
||||||
|
// Assign reported errors to the correct form element.
|
||||||
if (count($violations)) {
|
if (count($violations)) {
|
||||||
// Store reported errors in $form_state.
|
$widget->flagErrors($this, $violations, $element, $form_state);
|
||||||
$field_name = $this->getFieldDefinition()->getName();
|
|
||||||
$field_state = field_form_get_state($element['#parents'], $field_name, $form_state);
|
|
||||||
$field_state['constraint_violations'] = $violations;
|
|
||||||
field_form_set_state($element['#parents'], $field_name, $form_state, $field_state);
|
|
||||||
|
|
||||||
// Assign reported errors to the correct form element.
|
|
||||||
$widget->flagErrors($this, $element, $form_state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ use Drupal\Component\Utility\NestedArray;
|
||||||
use Drupal\Component\Utility\SortArray;
|
use Drupal\Component\Utility\SortArray;
|
||||||
use Drupal\Component\Utility\String;
|
use Drupal\Component\Utility\String;
|
||||||
use Symfony\Component\Validator\ConstraintViolationInterface;
|
use Symfony\Component\Validator\ConstraintViolationInterface;
|
||||||
|
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for 'Field widget' plugin implementations.
|
* Base class for 'Field widget' plugin implementations.
|
||||||
|
|
@ -61,7 +62,6 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
|
||||||
$field_state = array(
|
$field_state = array(
|
||||||
'items_count' => count($items),
|
'items_count' => count($items),
|
||||||
'array_parents' => array(),
|
'array_parents' => array(),
|
||||||
'constraint_violations' => array(),
|
|
||||||
);
|
);
|
||||||
field_form_set_state($parents, $field_name, $form_state, $field_state);
|
field_form_set_state($parents, $field_name, $form_state, $field_state);
|
||||||
}
|
}
|
||||||
|
|
@ -355,12 +355,12 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function flagErrors(FieldItemListInterface $items, array $form, array &$form_state) {
|
public function flagErrors(FieldItemListInterface $items, ConstraintViolationListInterface $violations, array $form, array &$form_state) {
|
||||||
$field_name = $this->fieldDefinition->getName();
|
$field_name = $this->fieldDefinition->getName();
|
||||||
|
|
||||||
$field_state = field_form_get_state($form['#parents'], $field_name, $form_state);
|
$field_state = field_form_get_state($form['#parents'], $field_name, $form_state);
|
||||||
|
|
||||||
if (!empty($field_state['constraint_violations'])) {
|
if ($violations->count()) {
|
||||||
$form_builder = \Drupal::formBuilder();
|
$form_builder = \Drupal::formBuilder();
|
||||||
|
|
||||||
// Locate the correct element in the the form.
|
// Locate the correct element in the the form.
|
||||||
|
|
@ -384,7 +384,7 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
|
||||||
$handles_multiple = $this->handlesMultipleValues();
|
$handles_multiple = $this->handlesMultipleValues();
|
||||||
|
|
||||||
$violations_by_delta = array();
|
$violations_by_delta = array();
|
||||||
foreach ($field_state['constraint_violations'] as $violation) {
|
foreach ($violations as $violation) {
|
||||||
// Separate violations by delta.
|
// Separate violations by delta.
|
||||||
$property_path = explode('.', $violation->getPropertyPath());
|
$property_path = explode('.', $violation->getPropertyPath());
|
||||||
$delta = array_shift($property_path);
|
$delta = array_shift($property_path);
|
||||||
|
|
@ -396,6 +396,7 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
|
||||||
$violation->arrayPropertyPath = $property_path;
|
$violation->arrayPropertyPath = $property_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @var \Symfony\Component\Validator\ConstraintViolationInterface[] $delta_violations */
|
||||||
foreach ($violations_by_delta as $delta => $delta_violations) {
|
foreach ($violations_by_delta as $delta => $delta_violations) {
|
||||||
// Pass violations to the main element:
|
// Pass violations to the main element:
|
||||||
// - if this is a multiple-value widget,
|
// - if this is a multiple-value widget,
|
||||||
|
|
@ -416,9 +417,6 @@ abstract class WidgetBase extends PluginSettingsBase implements WidgetInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Reinitialize the errors list for the next submit.
|
|
||||||
$field_state['constraint_violations'] = array();
|
|
||||||
field_form_set_state($form['#parents'], $field_name, $form_state, $field_state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@
|
||||||
|
|
||||||
namespace Drupal\Core\Field;
|
namespace Drupal\Core\Field;
|
||||||
|
|
||||||
|
use Symfony\Component\Validator\ConstraintViolationListInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base interface definition for "Field widget" plugins.
|
* Base interface definition for "Field widget" plugins.
|
||||||
*
|
*
|
||||||
|
|
@ -59,12 +61,14 @@ interface WidgetBaseInterface extends PluginSettingsInterface {
|
||||||
*
|
*
|
||||||
* @param \Drupal\Core\Field\FieldItemListInterface $items
|
* @param \Drupal\Core\Field\FieldItemListInterface $items
|
||||||
* The field values.
|
* The field values.
|
||||||
|
* @param \Symfony\Component\Validator\ConstraintViolationListInterface|\Symfony\Component\Validator\ConstraintViolationInterface[] $violations
|
||||||
|
* The constraint violations that were detected.
|
||||||
* @param array $form
|
* @param array $form
|
||||||
* The form structure where field elements are attached to. This might be a
|
* The form structure where field elements are attached to. This might be a
|
||||||
* full form structure, or a sub-element of a larger form.
|
* full form structure, or a sub-element of a larger form.
|
||||||
* @param array $form_state
|
* @param array $form_state
|
||||||
* The form state.
|
* The form state.
|
||||||
*/
|
*/
|
||||||
public function flagErrors(FieldItemListInterface $items, array $form, array &$form_state);
|
public function flagErrors(FieldItemListInterface $items, ConstraintViolationListInterface $violations, array $form, array &$form_state);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -499,7 +499,7 @@ function book_node_predelete(EntityInterface $node) {
|
||||||
/**
|
/**
|
||||||
* Implements hook_node_prepare_form().
|
* Implements hook_node_prepare_form().
|
||||||
*/
|
*/
|
||||||
function book_node_prepare_form(NodeInterface $node, $form_display, $operation, array &$form_state) {
|
function book_node_prepare_form(NodeInterface $node, $operation, array &$form_state) {
|
||||||
// Get BookManager service
|
// Get BookManager service
|
||||||
$book_manager = \Drupal::service('book.manager');
|
$book_manager = \Drupal::service('book.manager');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1002,7 +1002,7 @@ function datetime_form_node_form_alter(&$form, &$form_state, $form_id) {
|
||||||
/**
|
/**
|
||||||
* Implements hook_node_prepare_form().
|
* Implements hook_node_prepare_form().
|
||||||
*/
|
*/
|
||||||
function datetime_node_prepare_form(NodeInterface $node, $form_display, $operation, array &$form_state) {
|
function datetime_node_prepare_form(NodeInterface $node, $operation, array &$form_state) {
|
||||||
// Prepare the 'Authored on' date to use datetime.
|
// Prepare the 'Authored on' date to use datetime.
|
||||||
$node->date = DrupalDateTime::createFromTimestamp($node->getCreatedTime());
|
$node->date = DrupalDateTime::createFromTimestamp($node->getCreatedTime());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ class EditFieldForm extends FormBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the field form.
|
// Add the field form.
|
||||||
field_attach_form($form_state['entity'], $form, $form_state, $form_state['langcode'], array('field_name' => $form_state['field_name']));
|
$form_state['form_display']->buildForm($entity, $form, $form_state);
|
||||||
|
|
||||||
// Add a dummy changed timestamp field to attach form errors to.
|
// Add a dummy changed timestamp field to attach form errors to.
|
||||||
if ($entity instanceof EntityChangedInterface) {
|
if ($entity instanceof EntityChangedInterface) {
|
||||||
|
|
@ -128,9 +128,15 @@ class EditFieldForm extends FormBase {
|
||||||
$form_state['entity'] = $entity;
|
$form_state['entity'] = $entity;
|
||||||
$form_state['field_name'] = $field_name;
|
$form_state['field_name'] = $field_name;
|
||||||
|
|
||||||
// @todo Allow the usage of different form modes by exposing a hook and the
|
// Fetch the display used by the form. It is the display for the 'default'
|
||||||
// UI for them.
|
// form mode, with only the current field visible.
|
||||||
$form_state['form_display'] = EntityFormDisplay::collectRenderDisplay($entity, 'default');
|
$display = EntityFormDisplay::collectRenderDisplay($entity, 'default');
|
||||||
|
foreach ($display->getComponents() as $name => $optipns) {
|
||||||
|
if ($name != $field_name) {
|
||||||
|
$display->removeComponent($name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$form_state['form_display'] = $display;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -138,7 +144,8 @@ class EditFieldForm extends FormBase {
|
||||||
*/
|
*/
|
||||||
public function validateForm(array &$form, array &$form_state) {
|
public function validateForm(array &$form, array &$form_state) {
|
||||||
$entity = $this->buildEntity($form, $form_state);
|
$entity = $this->buildEntity($form, $form_state);
|
||||||
field_attach_form_validate($entity, $form, $form_state, array('field_name' => $form_state['field_name']));
|
|
||||||
|
$form_state['form_display']->validateFormValues($entity, $form, $form_state);
|
||||||
|
|
||||||
// Do validation on the changed field as well and assign the error to the
|
// Do validation on the changed field as well and assign the error to the
|
||||||
// dummy form element we added for this. We don't know the name of this
|
// dummy form element we added for this. We don't know the name of this
|
||||||
|
|
@ -174,7 +181,7 @@ class EditFieldForm extends FormBase {
|
||||||
$entity = clone $form_state['entity'];
|
$entity = clone $form_state['entity'];
|
||||||
$field_name = $form_state['field_name'];
|
$field_name = $form_state['field_name'];
|
||||||
|
|
||||||
field_attach_extract_form_values($entity, $form, $form_state, array('field_name' => $field_name));
|
$form_state['form_display']->extractFormValues($entity, $form, $form_state);
|
||||||
|
|
||||||
// @todo Refine automated log messages and abstract them to all entity
|
// @todo Refine automated log messages and abstract them to all entity
|
||||||
// types: http://drupal.org/node/1678002.
|
// types: http://drupal.org/node/1678002.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
namespace Drupal\entity\Entity;
|
namespace Drupal\entity\Entity;
|
||||||
|
|
||||||
|
use Drupal\Core\Entity\ContentEntityInterface;
|
||||||
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
|
||||||
use Drupal\entity\EntityDisplayBase;
|
use Drupal\entity\EntityDisplayBase;
|
||||||
|
|
||||||
|
|
@ -49,7 +50,7 @@ class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayIn
|
||||||
* party code to alter the display options held in the display before they are
|
* party code to alter the display options held in the display before they are
|
||||||
* used to generate render arrays.
|
* used to generate render arrays.
|
||||||
*
|
*
|
||||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
||||||
* The entity for which the form is being built.
|
* The entity for which the form is being built.
|
||||||
* @param string $form_mode
|
* @param string $form_mode
|
||||||
* The form mode.
|
* The form mode.
|
||||||
|
|
@ -60,7 +61,7 @@ class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayIn
|
||||||
* @see entity_get_form_display()
|
* @see entity_get_form_display()
|
||||||
* @see hook_entity_form_display_alter()
|
* @see hook_entity_form_display_alter()
|
||||||
*/
|
*/
|
||||||
public static function collectRenderDisplay($entity, $form_mode) {
|
public static function collectRenderDisplay(ContentEntityInterface $entity, $form_mode) {
|
||||||
$entity_type = $entity->getEntityTypeId();
|
$entity_type = $entity->getEntityTypeId();
|
||||||
$bundle = $entity->bundle();
|
$bundle = $entity->bundle();
|
||||||
|
|
||||||
|
|
@ -144,6 +145,83 @@ class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayIn
|
||||||
return $widget;
|
return $widget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function buildForm(ContentEntityInterface $entity, array &$form, array &$form_state) {
|
||||||
|
// Set #parents to 'top-level' by default.
|
||||||
|
$form += array('#parents' => array());
|
||||||
|
|
||||||
|
// Let each widget generate the form elements.
|
||||||
|
foreach ($entity as $name => $items) {
|
||||||
|
if ($widget = $this->getRenderer($name)) {
|
||||||
|
$items->filterEmptyItems();
|
||||||
|
$form[$name] = $widget->form($items, $form, $form_state);
|
||||||
|
|
||||||
|
// Assign the correct weight. This duplicates the reordering done in
|
||||||
|
// processForm(), but is needed for other forms calling this method
|
||||||
|
// directly.
|
||||||
|
$form[$name]['#weight'] = $this->getComponent($name)['weight'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a process callback so we can assign weights and hide extra fields.
|
||||||
|
$form['#process'][] = array($this, 'processForm');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Process callback: assigns weights and hides extra fields.
|
||||||
|
*
|
||||||
|
* @see \Drupal\entity\Entity\EntityFormDisplay::buildForm()
|
||||||
|
*/
|
||||||
|
public function processForm($element, $form_state, $form) {
|
||||||
|
// Assign the weights configured in the form display.
|
||||||
|
foreach ($this->getComponents() as $name => $options) {
|
||||||
|
if (isset($element[$name])) {
|
||||||
|
$element[$name]['#weight'] = $options['weight'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide extra fields.
|
||||||
|
$extra_fields = field_info_extra_fields($this->targetEntityType, $this->bundle, 'form');
|
||||||
|
foreach ($extra_fields as $extra_field => $info) {
|
||||||
|
if (!$this->getComponent($extra_field)) {
|
||||||
|
$element[$extra_field]['#access'] = FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function extractFormValues(ContentEntityInterface $entity, array &$form, array &$form_state) {
|
||||||
|
$extracted = array();
|
||||||
|
foreach ($entity as $name => $items) {
|
||||||
|
if ($widget = $this->getRenderer($name)) {
|
||||||
|
$widget->extractFormValues($items, $form, $form_state);
|
||||||
|
$extracted[$name] = $name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $extracted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function validateFormValues(ContentEntityInterface $entity, array &$form, array &$form_state) {
|
||||||
|
foreach ($entity as $field_name => $items) {
|
||||||
|
// Only validate the fields that actually appear in the form, and let the
|
||||||
|
// widget assign the violations to the right form elements.
|
||||||
|
if ($widget = $this->getRenderer($field_name)) {
|
||||||
|
$violations = $items->validate();
|
||||||
|
if (count($violations)) {
|
||||||
|
$widget->flagErrors($items, $violations, $form, $form_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -11,15 +11,16 @@ use Drupal\field\FieldConfigUpdateForbiddenException;
|
||||||
/**
|
/**
|
||||||
* Exposes "pseudo-field" components on fieldable entities.
|
* Exposes "pseudo-field" components on fieldable entities.
|
||||||
*
|
*
|
||||||
* Field UI's "Manage fields" and "Manage display" pages let users re-order
|
* Field UI's "Manage display" and "Manage form display" pages let users
|
||||||
* fields, but also non-field components. For nodes, these include the title
|
* re-order fields rendered through the regular widget/formatter pipeline, but
|
||||||
* and other elements exposed by modules through hook_form_alter().
|
* also other components: entity fields that are rendered through custom code,
|
||||||
|
* or other arbitrary components added through hook_form_alter() or
|
||||||
|
* hook_entity_view().
|
||||||
*
|
*
|
||||||
* Fieldable entities or modules that want to have their components supported
|
* Fieldable entities or modules that want to have their components supported
|
||||||
* should expose them using this hook. The user-defined settings (weight,
|
* should expose them using this hook. The user-defined settings (weight,
|
||||||
* visible) are automatically applied on rendered forms and displayed entities
|
* visible) are automatically applied on rendered forms and displayed entities
|
||||||
* in a #pre_render callback added by field_attach_form() and
|
* by ContentEntityFormController::form() and EntityViewBuilder::viewMultiple().
|
||||||
* EntityViewBuilder::viewMultiple().
|
|
||||||
*
|
*
|
||||||
* @see hook_field_extra_fields_alter()
|
* @see hook_field_extra_fields_alter()
|
||||||
*
|
*
|
||||||
|
|
@ -162,8 +163,8 @@ function hook_field_info_alter(&$info) {
|
||||||
*
|
*
|
||||||
* Widgets are @link forms_api_reference.html Form API @endlink
|
* Widgets are @link forms_api_reference.html Form API @endlink
|
||||||
* elements with additional processing capabilities. The methods of the
|
* elements with additional processing capabilities. The methods of the
|
||||||
* WidgetInterface object are typically called by the Field Attach API during
|
* WidgetInterface object are typically called by respective methods in the
|
||||||
* the creation of the field form structure with field_attach_form().
|
* \Drupal\entity\Entity\EntityFormDisplay class.
|
||||||
*
|
*
|
||||||
* @see field
|
* @see field
|
||||||
* @see field_types
|
* @see field_types
|
||||||
|
|
@ -291,78 +292,6 @@ function hook_field_formatter_info_alter(array &$info) {
|
||||||
* @} End of "defgroup field_formatter".
|
* @} End of "defgroup field_formatter".
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
|
||||||
* @addtogroup field_attach
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Act on field_attach_form().
|
|
||||||
*
|
|
||||||
* This hook is invoked after the field module has performed the operation.
|
|
||||||
* Implementing modules should alter the $form or $form_state parameters.
|
|
||||||
*
|
|
||||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
|
||||||
* The entity for which an edit form is being built.
|
|
||||||
* @param $form
|
|
||||||
* The form structure field elements are attached to. This might be a full
|
|
||||||
* form structure, or a sub-element of a larger form. The $form['#parents']
|
|
||||||
* property can be used to identify the corresponding part of
|
|
||||||
* $form_state['values']. Hook implementations that need to act on the
|
|
||||||
* top-level properties of the global form (like #submit, #validate...) can
|
|
||||||
* add a #process callback to the array received in the $form parameter, and
|
|
||||||
* act on the $complete_form parameter in the process callback.
|
|
||||||
* @param $form_state
|
|
||||||
* An associative array containing the current state of the form.
|
|
||||||
* @param $langcode
|
|
||||||
* The language the field values are going to be entered in. If no language is
|
|
||||||
* provided the default site language will be used.
|
|
||||||
*
|
|
||||||
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
|
|
||||||
* Use the entity system instead, see https://drupal.org/developing/api/entity
|
|
||||||
*/
|
|
||||||
function hook_field_attach_form(\Drupal\Core\Entity\EntityInterface $entity, &$form, &$form_state, $langcode) {
|
|
||||||
// Add a checkbox allowing a given field to be emptied.
|
|
||||||
// See hook_field_attach_extract_form_values() for the corresponding
|
|
||||||
// processing code.
|
|
||||||
$form['empty_field_foo'] = array(
|
|
||||||
'#type' => 'checkbox',
|
|
||||||
'#title' => t("Empty the 'field_foo' field"),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Act on field_attach_extract_form_values().
|
|
||||||
*
|
|
||||||
* This hook is invoked after the field module has performed the operation.
|
|
||||||
*
|
|
||||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
|
||||||
* The entity for which an edit form is being submitted. The incoming form
|
|
||||||
* values have been extracted as field values of the $entity object.
|
|
||||||
* @param $form
|
|
||||||
* The form structure field elements are attached to. This might be a full
|
|
||||||
* form structure, or a sub-part of a larger form. The $form['#parents']
|
|
||||||
* property can be used to identify the corresponding part of
|
|
||||||
* $form_state['values'].
|
|
||||||
* @param $form_state
|
|
||||||
* An associative array containing the current state of the form.
|
|
||||||
*
|
|
||||||
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
|
|
||||||
* Use the entity system instead, see https://drupal.org/developing/api/entity
|
|
||||||
*/
|
|
||||||
function hook_field_attach_extract_form_values(\Drupal\Core\Entity\EntityInterface $entity, $form, &$form_state) {
|
|
||||||
// Sample case of an 'Empty the field' checkbox added on the form, allowing
|
|
||||||
// a given field to be emptied.
|
|
||||||
$values = NestedArray::getValue($form_state['values'], $form['#parents']);
|
|
||||||
if (!empty($values['empty_field_foo'])) {
|
|
||||||
unset($entity->field_foo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @} End of "addtogroup field_attach".
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the maximum weight for the entity components handled by the module.
|
* Returns the maximum weight for the entity components handled by the module.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -1,153 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Field attach API, allowing entities (nodes, users, ...) to be 'fieldable'.
|
|
||||||
*/
|
|
||||||
|
|
||||||
use Drupal\Core\Entity\EntityInterface;
|
|
||||||
use Drupal\Core\Field\FieldDefinitionInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @defgroup field_attach Field Attach API
|
|
||||||
* @{
|
|
||||||
* Operates on Field API data attached to Drupal entities.
|
|
||||||
*
|
|
||||||
* Field Attach API functions load, store, display, generate Field API
|
|
||||||
* structures, and perform a variety of other functions for field data attached
|
|
||||||
* to individual entities.
|
|
||||||
*
|
|
||||||
* Field Attach API functions generally take $entity_type and $entity arguments
|
|
||||||
* along with additional function-specific arguments. $entity_type is the type
|
|
||||||
* of the fieldable entity, such as 'node' or 'user', and $entity is the entity
|
|
||||||
* itself.
|
|
||||||
*
|
|
||||||
* An entity plugin's annotation is how entity types define if and how
|
|
||||||
* Field API should operate on their entity objects. Notably, the 'fieldable'
|
|
||||||
* property needs to be set to TRUE.
|
|
||||||
*
|
|
||||||
* The Field Attach API uses the concept of bundles: the set of fields for a
|
|
||||||
* given entity is defined on a per-bundle basis. The collection of bundles for
|
|
||||||
* an entity type is added to the entity definition with
|
|
||||||
* hook_entity_type_alter(). For instance, node_entity_type_alter() exposes
|
|
||||||
* each node type as its own bundle. This means that the set of fields of a
|
|
||||||
* node is determined by the node type.
|
|
||||||
*
|
|
||||||
* The Field API reads the bundle name for a given entity from a particular
|
|
||||||
* property of the entity object, and hook_entity_type_alter() defines which
|
|
||||||
* property to use. For instance, \Drupal\node\Entity\Node specifies:
|
|
||||||
* @code
|
|
||||||
* entity_keys = {
|
|
||||||
* "bundle" = "type"
|
|
||||||
* }
|
|
||||||
* @endcode
|
|
||||||
* This indicates that for a particular node object, the bundle name can be
|
|
||||||
* found in $node->type. This property can be omitted if the entity type only
|
|
||||||
* exposes a single bundle (all entities of this type have the same collection
|
|
||||||
* of fields). This is the case for the 'user' entity type.
|
|
||||||
*
|
|
||||||
* @link field_language Field language API @endlink provides information about
|
|
||||||
* the structure of field objects.
|
|
||||||
*
|
|
||||||
* See @link field Field API @endlink for information about the other parts of
|
|
||||||
* the Field API.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invokes a method on all the fields of a given entity.
|
|
||||||
*
|
|
||||||
* @param string $method
|
|
||||||
* The name of the method to invoke.
|
|
||||||
* @param callable $target_function
|
|
||||||
* A function that receives a FieldDefinitionInterface object and returns the
|
|
||||||
* object on which the method should be invoked.
|
|
||||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
|
||||||
* The fully formed $entity_type entity.
|
|
||||||
* @param mixed $a
|
|
||||||
* (optional) A parameter for the invoked method. Defaults to NULL.
|
|
||||||
* @param mixed $b
|
|
||||||
* (optional) A parameter for the invoked method. Defaults to NULL.
|
|
||||||
* @param array $options
|
|
||||||
* (optional) An associative array of additional options, with the following
|
|
||||||
* keys:
|
|
||||||
* - field_name: The name of the field whose operation should be invoked. By
|
|
||||||
* default, the operation is invoked on all the fields in the entity's
|
|
||||||
* bundle.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
* An array of returned values.
|
|
||||||
*/
|
|
||||||
function field_invoke_method($method, $target_function, EntityInterface $entity, &$a = NULL, &$b = NULL, array $options = array()) {
|
|
||||||
$entity_type = $entity->getEntityTypeId();
|
|
||||||
|
|
||||||
// Determine the list of fields to iterate on.
|
|
||||||
$field_definitions = _field_invoke_get_field_definitions($entity_type, $entity->bundle(), $options);
|
|
||||||
|
|
||||||
// Iterate through the fields and collect results.
|
|
||||||
$return = array();
|
|
||||||
foreach ($field_definitions as $field_definition) {
|
|
||||||
// Let the function determine the target object on which the method should be
|
|
||||||
// called.
|
|
||||||
$target = call_user_func($target_function, $field_definition);
|
|
||||||
|
|
||||||
if (method_exists($target, $method)) {
|
|
||||||
$field_name = $field_definition->getName();
|
|
||||||
$items = $entity->get($field_name);
|
|
||||||
$items->filterEmptyItems();
|
|
||||||
|
|
||||||
$result = $target->$method($items, $a, $b);
|
|
||||||
if (isset($result)) {
|
|
||||||
$return[$field_name] = $result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieves a list of field definitions to operate on.
|
|
||||||
*
|
|
||||||
* Helper for field_invoke_method().
|
|
||||||
*
|
|
||||||
* @param $entity_type
|
|
||||||
* The entity type.
|
|
||||||
* @param $bundle
|
|
||||||
* The bundle name.
|
|
||||||
* @param $options
|
|
||||||
* An associative array of options, as provided to field_invoke_method(). Only
|
|
||||||
* the following keys are considered:
|
|
||||||
* - field_name
|
|
||||||
* See field_invoke_method() for details.
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* The array of selected field definitions.
|
|
||||||
*/
|
|
||||||
function _field_invoke_get_field_definitions($entity_type, $bundle, $options) {
|
|
||||||
$definitions = \Drupal::entityManager()->getFieldDefinitions($entity_type, $bundle);
|
|
||||||
if (isset($options['field_name'])) {
|
|
||||||
$definitions = array_intersect_key($definitions, array($options['field_name'] => TRUE));
|
|
||||||
}
|
|
||||||
return $definitions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines a 'target function' for field_invoke_method().
|
|
||||||
*
|
|
||||||
* Used to invoke methods on a field's widget.
|
|
||||||
*
|
|
||||||
* @param \Drupal\entity\Entity\EntityFormDisplay $form_display
|
|
||||||
* An EntityFormDisplay object.
|
|
||||||
*
|
|
||||||
* @return callable $target_function
|
|
||||||
* A 'target function' for field_invoke_method().
|
|
||||||
*/
|
|
||||||
function _field_invoke_widget_target($form_display) {
|
|
||||||
return function (FieldDefinitionInterface $field_definition) use ($form_display) {
|
|
||||||
return $form_display->getRenderer($field_definition->getName());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @} End of "defgroup field_attach".
|
|
||||||
*/
|
|
||||||
|
|
@ -174,218 +174,3 @@ function field_info_instances($entity_type = NULL, $bundle_name = NULL) {
|
||||||
function field_info_instance($entity_type, $field_name, $bundle_name) {
|
function field_info_instance($entity_type, $field_name, $bundle_name) {
|
||||||
return Field::fieldInfo()->getInstance($entity_type, $bundle_name, $field_name);
|
return Field::fieldInfo()->getInstance($entity_type, $bundle_name, $field_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds form elements for all fields for an entity to a form structure.
|
|
||||||
*
|
|
||||||
* The form elements for the entity's fields are added by reference as direct
|
|
||||||
* children in the $form parameter. This parameter can be a full form structure
|
|
||||||
* (most common case for entity edit forms), or a sub-element of a larger form.
|
|
||||||
*
|
|
||||||
* By default, submitted field values appear at the top-level of
|
|
||||||
* $form_state['values']. A different location within $form_state['values'] can
|
|
||||||
* be specified by setting the '#parents' property on the incoming $form
|
|
||||||
* parameter. Because of name clashes, two instances of the same field cannot
|
|
||||||
* appear within the same $form element, or within the same '#parents' space.
|
|
||||||
*
|
|
||||||
* For each call to field_attach_form(), field values are processed by calling
|
|
||||||
* field_attach_extract_form_values() on the same $form element.
|
|
||||||
*
|
|
||||||
* Sample resulting structure in $form:
|
|
||||||
* @code
|
|
||||||
* '#parents' => The location of field values in $form_state['values'],
|
|
||||||
* '#entity_type' => The name of the entity type,
|
|
||||||
* '#bundle' => The name of the bundle,
|
|
||||||
* // One sub-array per field appearing in the entity, keyed by field name.
|
|
||||||
* // The structure of the array differs slightly depending on whether the
|
|
||||||
* // widget is 'single-value' (provides the input for one field value,
|
|
||||||
* // most common case), and will therefore be repeated as many times as
|
|
||||||
* // needed, or 'multiple-values' (one single widget allows the input of
|
|
||||||
* // several values, e.g checkboxes, select box...).
|
|
||||||
* 'field_foo' => array(
|
|
||||||
* '#access' => TRUE if the current user has 'edit' grants for the field,
|
|
||||||
* FALSE if not.
|
|
||||||
* 'widget' => array(
|
|
||||||
* '#field_name' => The name of the field,
|
|
||||||
* '#language' => $langcode,
|
|
||||||
* '#field_parents' => The 'parents' space for the field in the form,
|
|
||||||
* equal to the #parents property of the $form parameter received by
|
|
||||||
* field_attach_form(),
|
|
||||||
* '#required' => Whether or not the field is required,
|
|
||||||
* '#title' => The label of the field instance,
|
|
||||||
* '#description' => The description text for the field instance,
|
|
||||||
*
|
|
||||||
* // Only for 'single' widgets:
|
|
||||||
* '#theme' => 'field_multiple_value_form',
|
|
||||||
* '#cardinality' => The field cardinality,
|
|
||||||
* '#cardinality_multiple => TRUE if the field can contain multiple items,
|
|
||||||
* FALSE otherwise.
|
|
||||||
* // One sub-array per copy of the widget, keyed by delta.
|
|
||||||
* 0 => array(
|
|
||||||
* '#entity_type' => The name of the entity type,
|
|
||||||
* '#bundle' => The name of the bundle,
|
|
||||||
* '#field_name' => The name of the field,
|
|
||||||
* '#field_parents' => The 'parents' space for the field in the form,
|
|
||||||
* equal to the #parents property of the $form parameter received by
|
|
||||||
* field_attach_form(),
|
|
||||||
* '#title' => The title to be displayed by the widget,
|
|
||||||
* '#default_value' => The field value for delta 0,
|
|
||||||
* '#required' => Whether the widget should be marked required,
|
|
||||||
* '#delta' => 0,
|
|
||||||
* // The remaining elements in the sub-array depend on the widget.
|
|
||||||
* '#type' => The type of the widget,
|
|
||||||
* ...
|
|
||||||
* ),
|
|
||||||
* 1 => array(
|
|
||||||
* ...
|
|
||||||
* ),
|
|
||||||
*
|
|
||||||
* // Only for multiple widgets:
|
|
||||||
* '#entity_type' => The name of the entity type,
|
|
||||||
* '#bundle' => $instance['bundle'],
|
|
||||||
* // The remaining elements in the sub-array depend on the widget.
|
|
||||||
* '#type' => The type of the widget,
|
|
||||||
* ...
|
|
||||||
* ),
|
|
||||||
* ...
|
|
||||||
* ),
|
|
||||||
* )
|
|
||||||
* @endcode
|
|
||||||
*
|
|
||||||
* Additionally, some processing data is placed in $form_state, and can be
|
|
||||||
* accessed by field_form_get_state() and field_form_set_state().
|
|
||||||
*
|
|
||||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
|
||||||
* The entity for which to load form elements, used to initialize
|
|
||||||
* default form values.
|
|
||||||
* @param $form
|
|
||||||
* The form structure to fill in. This can be a full form structure, or a
|
|
||||||
* sub-element of a larger form. The #parents property can be set to control
|
|
||||||
* the location of submitted field values within $form_state['values']. If
|
|
||||||
* not specified, $form['#parents'] is set to an empty array, placing field
|
|
||||||
* values at the top-level of $form_state['values'].
|
|
||||||
* @param $form_state
|
|
||||||
* An associative array containing the current state of the form.
|
|
||||||
* @param $langcode
|
|
||||||
* The language the field values are going to be entered, if no language
|
|
||||||
* is provided the default site language will be used.
|
|
||||||
* @param array $options
|
|
||||||
* An associative array of additional options. See field_invoke_method() for
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
|
|
||||||
* Use the entity system instead, see https://drupal.org/developing/api/entity
|
|
||||||
*
|
|
||||||
* @see field_form_get_state()
|
|
||||||
* @see field_form_set_state()
|
|
||||||
*/
|
|
||||||
function field_attach_form(EntityInterface $entity, &$form, &$form_state, $langcode = NULL, array $options = array()) {
|
|
||||||
// Set #parents to 'top-level' by default.
|
|
||||||
$form += array('#parents' => array());
|
|
||||||
|
|
||||||
// Get the entity_form_display object for this form.
|
|
||||||
$form_display = $form_state['form_display'];
|
|
||||||
|
|
||||||
$form += (array) field_invoke_method('form', _field_invoke_widget_target($form_display), $entity, $form, $form_state, $options);
|
|
||||||
|
|
||||||
$form['#entity_type'] = $entity->getEntityTypeId();
|
|
||||||
$form['#bundle'] = $entity->bundle();
|
|
||||||
|
|
||||||
// Let other modules make changes to the form.
|
|
||||||
// Avoid \Drupal::moduleHandler()->invokeAll()
|
|
||||||
// to let parameters be taken by reference.
|
|
||||||
foreach (\Drupal::moduleHandler()->getImplementations('field_attach_form') as $module) {
|
|
||||||
$function = $module . '_field_attach_form';
|
|
||||||
$function($entity, $form, $form_state, $langcode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs field validation against form-submitted field values.
|
|
||||||
*
|
|
||||||
* There are two levels of validation for fields in forms: widget validation and
|
|
||||||
* and field validation.
|
|
||||||
* - Widget validation steps are specific to a given widget's own form structure
|
|
||||||
* and UI metaphors. They are executed through FAPI's #element_validate
|
|
||||||
* property during normal form validation.
|
|
||||||
* - Field validation steps are common to a given field type, independently of
|
|
||||||
* the specific widget being used in a given form. They are defined in the
|
|
||||||
* field type's implementation of hook_field_validate().
|
|
||||||
*
|
|
||||||
* This function performs field validation in the context of a form submission.
|
|
||||||
* It converts field validation errors into form errors on the correct form
|
|
||||||
* elements. Fieldable entity types should call this function during their own
|
|
||||||
* form validation function.
|
|
||||||
*
|
|
||||||
* @param \Drupal\Core\Entity\ContentEntityInterface $entity
|
|
||||||
* The entity being submitted. The actual field values will be read
|
|
||||||
* from $form_state['values'].
|
|
||||||
* @param $form
|
|
||||||
* The form structure where field elements are attached to. This might be a
|
|
||||||
* full form structure, or a sub-element of a larger form.
|
|
||||||
* @param $form_state
|
|
||||||
* An associative array containing the current state of the form.
|
|
||||||
* @param array $options
|
|
||||||
* An associative array of additional options. See field_invoke_method() for
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
|
|
||||||
* Use the entity system instead, see https://drupal.org/developing/api/entity
|
|
||||||
*/
|
|
||||||
function field_attach_form_validate(ContentEntityInterface $entity, $form, &$form_state, array $options = array()) {
|
|
||||||
$has_violations = FALSE;
|
|
||||||
foreach ($entity as $field_name => $field) {
|
|
||||||
if (empty($options['field_name']) || $options['field_name'] == $field_name) {
|
|
||||||
$field_violations = $field->validate();
|
|
||||||
if (count($field_violations)) {
|
|
||||||
$has_violations = TRUE;
|
|
||||||
|
|
||||||
// Place violations in $form_state.
|
|
||||||
$field_state = field_form_get_state($form['#parents'], $field_name, $form_state);
|
|
||||||
$field_state['constraint_violations'] = $field_violations;
|
|
||||||
field_form_set_state($form['#parents'], $field_name, $form_state, $field_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($has_violations) {
|
|
||||||
// Map errors back to form elements.
|
|
||||||
$form_display = $form_state['form_display'];
|
|
||||||
field_invoke_method('flagErrors', _field_invoke_widget_target($form_display), $entity, $form, $form_state, $options);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates an entity object with values from a form submission.
|
|
||||||
*
|
|
||||||
* Currently, this accounts for drag-and-drop reordering of field values, and
|
|
||||||
* filtering of empty values.
|
|
||||||
*
|
|
||||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
|
||||||
* The entity being submitted. The actual field values will be read
|
|
||||||
* from $form_state['values'].
|
|
||||||
* @param $form
|
|
||||||
* The form structure where field elements are attached to. This might be a
|
|
||||||
* full form structure, or a sub-element of a larger form.
|
|
||||||
* @param $form_state
|
|
||||||
* An associative array containing the current state of the form.
|
|
||||||
* @param array $options
|
|
||||||
* An associative array of additional options. See field_invoke_method() for
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
|
|
||||||
* Use the entity system instead, see https://drupal.org/developing/api/entity
|
|
||||||
*/
|
|
||||||
function field_attach_extract_form_values(EntityInterface $entity, $form, &$form_state, array $options = array()) {
|
|
||||||
// Extract field values from submitted values.
|
|
||||||
$form_display = $form_state['form_display'];
|
|
||||||
field_invoke_method('extractFormValues', _field_invoke_widget_target($form_display), $entity, $form, $form_state, $options);
|
|
||||||
|
|
||||||
// Let other modules act on submitting the entity.
|
|
||||||
// Avoid \Drupal::moduleHandler()->invokeAll()
|
|
||||||
// to let $form_state be taken by reference.
|
|
||||||
foreach (\Drupal::moduleHandler()->getImplementations('field_attach_extract_form_values') as $module) {
|
|
||||||
$function = $module . 'field_attach_extract_form_values';
|
|
||||||
$function($entity, $form, $form_state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ use Drupal\field\Field;
|
||||||
* every page request.
|
* every page request.
|
||||||
*/
|
*/
|
||||||
require_once __DIR__ . '/field.info.inc';
|
require_once __DIR__ . '/field.info.inc';
|
||||||
require_once __DIR__ . '/field.attach.inc';
|
|
||||||
require_once __DIR__ . '/field.form.inc';
|
require_once __DIR__ . '/field.form.inc';
|
||||||
require_once __DIR__ . '/field.purge.inc';
|
require_once __DIR__ . '/field.purge.inc';
|
||||||
require_once __DIR__ . '/field.deprecated.inc';
|
require_once __DIR__ . '/field.deprecated.inc';
|
||||||
|
|
|
||||||
|
|
@ -262,22 +262,22 @@ class FieldAttachOtherTest extends FieldUnitTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test field_attach_form().
|
* Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::buildForm().
|
||||||
*
|
*
|
||||||
* This could be much more thorough, but it does verify that the correct
|
* This could be much more thorough, but it does verify that the correct
|
||||||
* widgets show up.
|
* widgets show up.
|
||||||
*/
|
*/
|
||||||
function testFieldAttachForm() {
|
function testEntityFormDisplayBuildForm() {
|
||||||
$this->createFieldWithInstance('_2');
|
$this->createFieldWithInstance('_2');
|
||||||
|
|
||||||
$entity_type = 'entity_test';
|
$entity_type = 'entity_test';
|
||||||
$entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));
|
$entity = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));
|
||||||
|
|
||||||
// When generating form for all fields.
|
// Test generating widgets for all fields.
|
||||||
|
$display = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
|
||||||
$form = array();
|
$form = array();
|
||||||
$form_state = form_state_defaults();
|
$form_state = form_state_defaults();
|
||||||
$form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
|
$display->buildForm($entity, $form, $form_state);
|
||||||
field_attach_form($entity, $form, $form_state);
|
|
||||||
|
|
||||||
$this->assertEqual($form[$this->field_name]['widget']['#title'], $this->instance->getLabel(), "First field's form title is {$this->instance->getLabel()}");
|
$this->assertEqual($form[$this->field_name]['widget']['#title'], $this->instance->getLabel(), "First field's form title is {$this->instance->getLabel()}");
|
||||||
$this->assertEqual($form[$this->field_name_2]['widget']['#title'], $this->instance_2->getLabel(), "Second field's form title is {$this->instance_2->getLabel()}");
|
$this->assertEqual($form[$this->field_name_2]['widget']['#title'], $this->instance_2->getLabel(), "Second field's form title is {$this->instance_2->getLabel()}");
|
||||||
|
|
@ -290,12 +290,16 @@ class FieldAttachOtherTest extends FieldUnitTestBase {
|
||||||
$this->assertEqual($form[$this->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
|
$this->assertEqual($form[$this->field_name_2]['widget'][$delta]['value']['#type'], 'textfield', "Second field's form delta $delta widget is textfield");
|
||||||
}
|
}
|
||||||
|
|
||||||
// When generating form for a single field (the second field).
|
// Test generating widgets for all fields.
|
||||||
$options = array('field_name' => $this->field_name_2);
|
$display = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
|
||||||
|
foreach ($display->getComponents() as $name => $options) {
|
||||||
|
if ($name != $this->field_name_2) {
|
||||||
|
$display->removeComponent($name);
|
||||||
|
}
|
||||||
|
}
|
||||||
$form = array();
|
$form = array();
|
||||||
$form_state = form_state_defaults();
|
$form_state = form_state_defaults();
|
||||||
$form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
|
$display->buildForm($entity, $form, $form_state);
|
||||||
field_attach_form($entity, $form, $form_state, NULL, $options);
|
|
||||||
|
|
||||||
$this->assertFalse(isset($form[$this->field_name]), 'The first field does not exist in the form');
|
$this->assertFalse(isset($form[$this->field_name]), 'The first field does not exist in the form');
|
||||||
$this->assertEqual($form[$this->field_name_2]['widget']['#title'], $this->instance_2->getLabel(), "Second field's form title is {$this->instance_2->getLabel()}");
|
$this->assertEqual($form[$this->field_name_2]['widget']['#title'], $this->instance_2->getLabel(), "Second field's form title is {$this->instance_2->getLabel()}");
|
||||||
|
|
@ -306,19 +310,19 @@ class FieldAttachOtherTest extends FieldUnitTestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test field_attach_extract_form_values().
|
* Tests \Drupal\Core\Entity\Display\EntityFormDisplayInterface::extractFormValues().
|
||||||
*/
|
*/
|
||||||
function testFieldAttachExtractFormValues() {
|
function testEntityFormDisplayExtractFormValues() {
|
||||||
$this->createFieldWithInstance('_2');
|
$this->createFieldWithInstance('_2');
|
||||||
|
|
||||||
$entity_type = 'entity_test';
|
$entity_type = 'entity_test';
|
||||||
$entity_init = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));
|
$entity_init = entity_create($entity_type, array('id' => 1, 'revision_id' => 1, 'type' => $this->instance->bundle));
|
||||||
|
|
||||||
// Build the form for all fields.
|
// Build the form for all fields.
|
||||||
|
$display = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
|
||||||
$form = array();
|
$form = array();
|
||||||
$form_state = form_state_defaults();
|
$form_state = form_state_defaults();
|
||||||
$form_state['form_display'] = entity_get_form_display($entity_type, $this->instance->bundle, 'default');
|
$display->buildForm($entity_init, $form, $form_state);
|
||||||
field_attach_form($entity_init, $form, $form_state);
|
|
||||||
|
|
||||||
// Simulate incoming values.
|
// Simulate incoming values.
|
||||||
// First field.
|
// First field.
|
||||||
|
|
@ -356,9 +360,9 @@ class FieldAttachOtherTest extends FieldUnitTestBase {
|
||||||
$form_state['values'][$this->field_name] = $values;
|
$form_state['values'][$this->field_name] = $values;
|
||||||
$form_state['values'][$this->field_name_2] = $values_2;
|
$form_state['values'][$this->field_name_2] = $values_2;
|
||||||
|
|
||||||
// Call field_attach_extract_form_values() for all fields.
|
// Extract values for all fields.
|
||||||
$entity = clone($entity_init);
|
$entity = clone($entity_init);
|
||||||
field_attach_extract_form_values($entity, $form, $form_state);
|
$display->extractFormValues($entity, $form, $form_state);
|
||||||
|
|
||||||
asort($weights);
|
asort($weights);
|
||||||
asort($weights_2);
|
asort($weights_2);
|
||||||
|
|
@ -378,16 +382,20 @@ class FieldAttachOtherTest extends FieldUnitTestBase {
|
||||||
$this->assertIdentical($entity->{$this->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
|
$this->assertIdentical($entity->{$this->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
|
||||||
|
|
||||||
// Call field_attach_extract_form_values() for a single field (the second field).
|
// Call field_attach_extract_form_values() for a single field (the second field).
|
||||||
$options = array('field_name' => $this->field_name_2);
|
foreach ($display->getComponents() as $name => $options) {
|
||||||
|
if ($name != $this->field_name_2) {
|
||||||
|
$display->removeComponent($name);
|
||||||
|
}
|
||||||
|
}
|
||||||
$entity = clone($entity_init);
|
$entity = clone($entity_init);
|
||||||
field_attach_extract_form_values($entity, $form, $form_state, $options);
|
$display->extractFormValues($entity, $form, $form_state);
|
||||||
$expected_values_2 = array();
|
$expected_values_2 = array();
|
||||||
foreach ($weights_2 as $key => $value) {
|
foreach ($weights_2 as $key => $value) {
|
||||||
if ($key != 1) {
|
if ($key != 1) {
|
||||||
$expected_values_2[] = array('value' => $values_2[$key]['value']);
|
$expected_values_2[] = array('value' => $values_2[$key]['value']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->assertTrue($entity->{$this->field_name}->isEmpty(), 'The first field does is empty in the entity object');
|
$this->assertTrue($entity->{$this->field_name}->isEmpty(), 'The first field is empty in the entity object');
|
||||||
$this->assertIdentical($entity->{$this->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
|
$this->assertIdentical($entity->{$this->field_name_2}->getValue(), $expected_values_2, 'Submit filters empty values');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -531,10 +531,10 @@ class FormTest extends FieldTestBase {
|
||||||
// apart from #access.
|
// apart from #access.
|
||||||
$entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0));
|
$entity = entity_create($entity_type, array('id' => 0, 'revision_id' => 0));
|
||||||
|
|
||||||
|
$display = entity_get_form_display($entity_type, $entity_type, 'default');
|
||||||
$form = array();
|
$form = array();
|
||||||
$form_state = form_state_defaults();
|
$form_state = form_state_defaults();
|
||||||
$form_state['form_display'] = entity_get_form_display($entity_type, $entity_type, 'default');
|
$display->buildForm($entity, $form, $form_state);
|
||||||
field_attach_form($entity, $form, $form_state);
|
|
||||||
|
|
||||||
$this->assertEqual($form[$field_name_no_access]['widget'][0]['value']['#entity_type'], $entity_type, 'The correct entity type is set in the field structure.');
|
$this->assertEqual($form[$field_name_no_access]['widget'][0]['value']['#entity_type'], $entity_type, 'The correct entity type is set in the field structure.');
|
||||||
$this->assertFalse($form[$field_name_no_access]['#access'], 'Field #access is FALSE for the field without edit access.');
|
$this->assertFalse($form[$field_name_no_access]['#access'], 'Field #access is FALSE for the field without edit access.');
|
||||||
|
|
|
||||||
|
|
@ -39,86 +39,3 @@ function field_test_entity_info_translatable($entity_type = NULL, $translatable
|
||||||
}
|
}
|
||||||
return $stored_value;
|
return $stored_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Form combining two separate entities.
|
|
||||||
*
|
|
||||||
* @deprecated Use \Drupal\field_test\Form\FieldTestForm::testEntityNestedForm()
|
|
||||||
*/
|
|
||||||
function field_test_entity_nested_form($form, &$form_state, EntityInterface $entity_1, EntityInterface $entity_2) {
|
|
||||||
// First entity.
|
|
||||||
foreach (array('id', 'type') as $key) {
|
|
||||||
$form[$key] = array(
|
|
||||||
'#type' => 'value',
|
|
||||||
'#value' => $entity_1->$key->value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$form_state['form_display'] = entity_get_form_display($entity_1->getEntityTypeId(), $entity_1->bundle(), 'default');
|
|
||||||
field_attach_form($entity_1, $form, $form_state);
|
|
||||||
|
|
||||||
// Second entity.
|
|
||||||
$form['entity_2'] = array(
|
|
||||||
'#type' => 'details',
|
|
||||||
'#title' => t('Second entity'),
|
|
||||||
'#open' => TRUE,
|
|
||||||
'#tree' => TRUE,
|
|
||||||
'#parents' => array('entity_2'),
|
|
||||||
'#weight' => 50,
|
|
||||||
);
|
|
||||||
foreach (array('id', 'type') as $key) {
|
|
||||||
$form['entity_2'][$key] = array(
|
|
||||||
'#type' => 'value',
|
|
||||||
'#value' => $entity_2->$key->value,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
$form_state['form_display'] = entity_get_form_display($entity_1->getEntityTypeId(), $entity_1->bundle(), 'default');
|
|
||||||
field_attach_form($entity_2, $form['entity_2'], $form_state);
|
|
||||||
|
|
||||||
$form['save'] = array(
|
|
||||||
'#type' => 'submit',
|
|
||||||
'#value' => t('Save'),
|
|
||||||
'#weight' => 100,
|
|
||||||
);
|
|
||||||
|
|
||||||
return $form;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate handler for field_test_entity_nested_form().
|
|
||||||
*/
|
|
||||||
function field_test_entity_nested_form_validate($form, &$form_state) {
|
|
||||||
$entity_1 = entity_create('entity_test', array(
|
|
||||||
'id' => $form_state['values']['id'],
|
|
||||||
'type' => $form_state['values']['type'],
|
|
||||||
));
|
|
||||||
field_attach_extract_form_values($entity_1, $form, $form_state);
|
|
||||||
field_attach_form_validate($entity_1, $form, $form_state);
|
|
||||||
|
|
||||||
$entity_2 = entity_create('entity_test', array(
|
|
||||||
'id' => $form_state['values']['entity_2']['id'],
|
|
||||||
'type' => $form_state['values']['entity_2']['type'],
|
|
||||||
));
|
|
||||||
field_attach_extract_form_values($entity_2, $form['entity_2'], $form_state);
|
|
||||||
field_attach_form_validate($entity_2, $form['entity_2'], $form_state);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit handler for field_test_entity_nested_form().
|
|
||||||
*/
|
|
||||||
function field_test_entity_nested_form_submit($form, &$form_state) {
|
|
||||||
$entity_1 = entity_create('entity_test', array(
|
|
||||||
'id' => $form_state['values']['id'],
|
|
||||||
'type' => $form_state['values']['type'],
|
|
||||||
));
|
|
||||||
field_attach_extract_form_values($entity_1, $form, $form_state);
|
|
||||||
$entity_1->save();
|
|
||||||
|
|
||||||
$entity_2 = entity_create('entity_test', array(
|
|
||||||
'id' => $form_state['values']['entity_2']['id'],
|
|
||||||
'type' => $form_state['values']['entity_2']['type'],
|
|
||||||
));
|
|
||||||
field_attach_extract_form_values($entity_2, $form['entity_2'], $form_state);
|
|
||||||
$entity_2->save();
|
|
||||||
|
|
||||||
drupal_set_message(t('test_entities @id_1 and @id_2 have been updated.', array('@id_1' => $entity_1->id(), '@id_2' => $entity_2->id())));
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ field_test.entity_nested_form:
|
||||||
path: '/test-entity/nested/{entity_1}/{entity_2}'
|
path: '/test-entity/nested/{entity_1}/{entity_2}'
|
||||||
defaults:
|
defaults:
|
||||||
_title: 'Nested entity form'
|
_title: 'Nested entity form'
|
||||||
_content: '\Drupal\field_test\Form\FieldTestForm::testEntityNestedForm'
|
_form: '\Drupal\field_test\Form\NestedEntityTestForm'
|
||||||
options:
|
options:
|
||||||
parameters:
|
parameters:
|
||||||
entity_1:
|
entity_1:
|
||||||
|
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
* Contains \Drupal\field_test\Form\FieldTestForm.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Drupal\field_test\Form;
|
|
||||||
|
|
||||||
use Drupal\Core\Entity\EntityInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides a form for field_test routes.
|
|
||||||
*/
|
|
||||||
class FieldTestForm {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @todo Remove field_test_entity_nested_form().
|
|
||||||
*/
|
|
||||||
public function testEntityNestedForm(EntityInterface $entity_1, EntityInterface $entity_2) {
|
|
||||||
module_load_include('entity.inc', 'field_test');
|
|
||||||
return drupal_get_form('field_test_entity_nested_form', $entity_1, $entity_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* Contains \Drupal\field_test\Form\NestedEntityTestForm.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Drupal\field_test\Form;
|
||||||
|
|
||||||
|
use Drupal\Core\Entity\EntityInterface;
|
||||||
|
use Drupal\Core\Form\FormBase;
|
||||||
|
use Drupal\entity\Entity\EntityFormDisplay;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a form for field_test routes.
|
||||||
|
*/
|
||||||
|
class NestedEntityTestForm extends FormBase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc]
|
||||||
|
*/
|
||||||
|
public function getFormId() {
|
||||||
|
return 'field_test_entity_nested_form';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc]
|
||||||
|
*/
|
||||||
|
public function buildForm(array $form, array &$form_state, EntityInterface $entity_1 = NULL, EntityInterface $entity_2 = NULL) {
|
||||||
|
// First entity.
|
||||||
|
$form_state['entity_1'] = $entity_1;
|
||||||
|
$form_state['form_display_1'] = EntityFormDisplay::collectRenderDisplay($entity_1, 'default');
|
||||||
|
$form_state['form_display_1']->buildForm($entity_1, $form, $form_state);
|
||||||
|
|
||||||
|
// Second entity.
|
||||||
|
$form_state['entity_2'] = $entity_2;
|
||||||
|
$form_state['form_display_2'] = EntityFormDisplay::collectRenderDisplay($entity_2, 'default');
|
||||||
|
$form['entity_2'] = array(
|
||||||
|
'#type' => 'details',
|
||||||
|
'#title' => t('Second entity'),
|
||||||
|
'#tree' => TRUE,
|
||||||
|
'#parents' => array('entity_2'),
|
||||||
|
'#weight' => 50,
|
||||||
|
);
|
||||||
|
|
||||||
|
$form_state['form_display_2']->buildForm($entity_2, $form['entity_2'], $form_state);
|
||||||
|
|
||||||
|
$form['save'] = array(
|
||||||
|
'#type' => 'submit',
|
||||||
|
'#value' => t('Save'),
|
||||||
|
'#weight' => 100,
|
||||||
|
);
|
||||||
|
|
||||||
|
return $form;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc]
|
||||||
|
*/
|
||||||
|
public function validateForm(array &$form, array &$form_state) {
|
||||||
|
$entity_1 = $form_state['entity_1'];
|
||||||
|
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display_1 */
|
||||||
|
$form_display_1 = $form_state['form_display_1'];
|
||||||
|
$form_display_1->extractFormValues($entity_1, $form, $form_state);
|
||||||
|
$form_display_1->validateFormValues($entity_1, $form, $form_state);
|
||||||
|
|
||||||
|
$entity_2 = $form_state['entity_2'];
|
||||||
|
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display_2 */
|
||||||
|
$form_display_2 = $form_state['form_display_2'];
|
||||||
|
$form_display_2->extractFormValues($entity_2, $form['entity_2'], $form_state);
|
||||||
|
$form_display_2->validateFormValues($entity_2, $form['entity_2'], $form_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc]
|
||||||
|
*/
|
||||||
|
public function submitForm(array &$form, array &$form_state) {
|
||||||
|
/** @var \Drupal\Core\Entity\EntityInterface $entity_1 */
|
||||||
|
$entity_1 = $form_state['entity_1'];
|
||||||
|
$entity_1->save();
|
||||||
|
|
||||||
|
/** @var \Drupal\Core\Entity\EntityInterface $entity_2 */
|
||||||
|
$entity_2 = $form_state['entity_2'];
|
||||||
|
$entity_2->save();
|
||||||
|
|
||||||
|
drupal_set_message($this->t('test_entities @id_1 and @id_2 have been updated.', array('@id_1' => $entity_1->id(), '@id_2' => $entity_2->id())));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -252,7 +252,7 @@ class ImageStyleEditForm extends ImageStyleFormBase {
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
protected function copyFormValuesToEntity(EntityInterface $entity, array $form_state) {
|
protected function copyFormValuesToEntity(EntityInterface $entity, array $form, array &$form_state) {
|
||||||
foreach ($form_state['values'] as $key => $value) {
|
foreach ($form_state['values'] as $key => $value) {
|
||||||
// Do not copy effects here, see self::updateEffectWeights().
|
// Do not copy effects here, see self::updateEffectWeights().
|
||||||
if ($key != 'effects') {
|
if ($key != 'effects') {
|
||||||
|
|
|
||||||
|
|
@ -390,7 +390,7 @@ function menu_node_predelete(EntityInterface $node) {
|
||||||
/**
|
/**
|
||||||
* Implements hook_node_prepare_form().
|
* Implements hook_node_prepare_form().
|
||||||
*/
|
*/
|
||||||
function menu_node_prepare_form(NodeInterface $node, $form_display, $operation, array &$form_state) {
|
function menu_node_prepare_form(NodeInterface $node, $operation, array &$form_state) {
|
||||||
if (empty($node->menu)) {
|
if (empty($node->menu)) {
|
||||||
// Prepare the node for the edit form so that $node->menu always exists.
|
// Prepare the node for the edit form so that $node->menu always exists.
|
||||||
$node_type_config = \Drupal::config('menu.entity.node.' . $node->getType());
|
$node_type_config = \Drupal::config('menu.entity.node.' . $node->getType());
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,12 @@ use Drupal\Component\Utility\Xss;
|
||||||
* - Entity hooks: Generic hooks for "entity" operations. These are always
|
* - Entity hooks: Generic hooks for "entity" operations. These are always
|
||||||
* invoked on all modules.
|
* invoked on all modules.
|
||||||
*
|
*
|
||||||
* Here is a list of the node and entity hooks that are invoked, field
|
* Here is a list of the node and entity hooks that are invoked, and other
|
||||||
* operations, and other steps that take place during node operations:
|
* steps that take place during node operations:
|
||||||
* - Instantiating a new node:
|
* - Instantiating a new node:
|
||||||
* - hook_node_create() (all)
|
* - hook_node_create() (all)
|
||||||
* - hook_entity_create() (all)
|
* - hook_entity_create() (all)
|
||||||
* - Creating a new node (calling $node->save() on a new node):
|
* - Creating a new node (calling $node->save() on a new node):
|
||||||
* - field_attach_presave()
|
|
||||||
* - hook_node_presave() (all)
|
* - hook_node_presave() (all)
|
||||||
* - hook_entity_presave() (all)
|
* - hook_entity_presave() (all)
|
||||||
* - Node and revision records are written to the database
|
* - Node and revision records are written to the database
|
||||||
|
|
@ -46,7 +45,6 @@ use Drupal\Component\Utility\Xss;
|
||||||
* - hook_node_access_records() (all)
|
* - hook_node_access_records() (all)
|
||||||
* - hook_node_access_records_alter() (all)
|
* - hook_node_access_records_alter() (all)
|
||||||
* - Updating an existing node (calling $node->save() on an existing node):
|
* - Updating an existing node (calling $node->save() on an existing node):
|
||||||
* - field_attach_presave()
|
|
||||||
* - hook_node_presave() (all)
|
* - hook_node_presave() (all)
|
||||||
* - hook_entity_presave() (all)
|
* - hook_entity_presave() (all)
|
||||||
* - Node and revision records are written to the database
|
* - Node and revision records are written to the database
|
||||||
|
|
@ -91,7 +89,7 @@ use Drupal\Component\Utility\Xss;
|
||||||
* existing node, it will already be loaded; see the Loading section above):
|
* existing node, it will already be loaded; see the Loading section above):
|
||||||
* - hook_node_prepare_form() (all)
|
* - hook_node_prepare_form() (all)
|
||||||
* - hook_entity_prepare_form() (all)
|
* - hook_entity_prepare_form() (all)
|
||||||
* - field_attach_form()
|
* - @todo hook for EntityFormDisplay::buildForm()
|
||||||
* - Validating a node during editing form submit (calling
|
* - Validating a node during editing form submit (calling
|
||||||
* node_form_validate()):
|
* node_form_validate()):
|
||||||
* - hook_node_validate() (all)
|
* - hook_node_validate() (all)
|
||||||
|
|
@ -598,8 +596,6 @@ function hook_node_access(\Drupal\node\NodeInterface $node, $op, $account, $lang
|
||||||
*
|
*
|
||||||
* @param \Drupal\node\NodeInterface $node
|
* @param \Drupal\node\NodeInterface $node
|
||||||
* The node that is about to be shown on the form.
|
* The node that is about to be shown on the form.
|
||||||
* @param $form_display
|
|
||||||
* The current form display.
|
|
||||||
* @param $operation
|
* @param $operation
|
||||||
* The current operation.
|
* The current operation.
|
||||||
* @param array $form_state
|
* @param array $form_state
|
||||||
|
|
@ -607,7 +603,7 @@ function hook_node_access(\Drupal\node\NodeInterface $node, $op, $account, $lang
|
||||||
*
|
*
|
||||||
* @ingroup node_api_hooks
|
* @ingroup node_api_hooks
|
||||||
*/
|
*/
|
||||||
function hook_node_prepare_form(\Drupal\node\NodeInterface $node, $form_display, $operation, array &$form_state) {
|
function hook_node_prepare_form(\Drupal\node\NodeInterface $node, $operation, array &$form_state) {
|
||||||
if (!isset($node->my_rating)) {
|
if (!isset($node->my_rating)) {
|
||||||
$node->my_rating = \Drupal::config("my_rating_{$node->bundle()}")->get('enabled');
|
$node->my_rating = \Drupal::config("my_rating_{$node->bundle()}")->get('enabled');
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -620,8 +620,6 @@ function hook_entity_display_build_alter(&$build, $context) {
|
||||||
*
|
*
|
||||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||||
* The entity that is about to be shown on the form.
|
* The entity that is about to be shown on the form.
|
||||||
* @param $form_display
|
|
||||||
* The current form display.
|
|
||||||
* @param $operation
|
* @param $operation
|
||||||
* The current operation.
|
* The current operation.
|
||||||
* @param array $form_state
|
* @param array $form_state
|
||||||
|
|
@ -629,7 +627,7 @@ function hook_entity_display_build_alter(&$build, $context) {
|
||||||
*
|
*
|
||||||
* @see \Drupal\Core\Entity\EntityFormController::prepareEntity()
|
* @see \Drupal\Core\Entity\EntityFormController::prepareEntity()
|
||||||
*/
|
*/
|
||||||
function hook_entity_prepare_form(\Drupal\Core\Entity\EntityInterface $entity, $form_display, $operation, array &$form_state) {
|
function hook_entity_prepare_form(\Drupal\Core\Entity\EntityInterface $entity, $operation, array &$form_state) {
|
||||||
if ($operation == 'edit') {
|
if ($operation == 'edit') {
|
||||||
$entity->label->value = 'Altered label';
|
$entity->label->value = 'Altered label';
|
||||||
$form_state['mymodule']['label_altered'] = TRUE;
|
$form_state['mymodule']['label_altered'] = TRUE;
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ class ArbitraryRebuildTest extends WebTestBase {
|
||||||
'name' => 'foo',
|
'name' => 'foo',
|
||||||
'mail' => 'bar@example.com',
|
'mail' => 'bar@example.com',
|
||||||
);
|
);
|
||||||
$this->drupalPostForm('user/register', $edit, t('Add another item'), array('query' => array('field' => TRUE)));
|
$this->drupalPostForm('user/register', $edit, t('Add another item'));
|
||||||
$this->assertText('Test a multiple valued field', 'Form has been rebuilt.');
|
$this->assertText('Test a multiple valued field', 'Form has been rebuilt.');
|
||||||
$this->assertFieldByName('name', 'foo', 'Entered user name has been kept.');
|
$this->assertFieldByName('name', 'foo', 'Entered user name has been kept.');
|
||||||
$this->assertFieldByName('mail', 'bar@example.com', 'Entered mail address has been kept.');
|
$this->assertFieldByName('mail', 'bar@example.com', 'Entered mail address has been kept.');
|
||||||
|
|
|
||||||
|
|
@ -1942,13 +1942,6 @@ function form_test_form_user_register_form_alter(&$form, &$form_state) {
|
||||||
'#value' => t('Rebuild'),
|
'#value' => t('Rebuild'),
|
||||||
'#submit' => array('form_test_user_register_form_rebuild'),
|
'#submit' => array('form_test_user_register_form_rebuild'),
|
||||||
);
|
);
|
||||||
// If requested, add the test field by attaching the node page form.
|
|
||||||
if (\Drupal::request()->request->has('field')) {
|
|
||||||
$node = entity_create('node', array(
|
|
||||||
'type' => 'page',
|
|
||||||
));
|
|
||||||
field_attach_form($node, $form, $form_state);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -50,9 +50,6 @@ class RegisterFormController extends AccountFormController {
|
||||||
// Start with the default user account fields.
|
// Start with the default user account fields.
|
||||||
$form = parent::form($form, $form_state, $account);
|
$form = parent::form($form, $form_state, $account);
|
||||||
|
|
||||||
// Attach field widgets.
|
|
||||||
field_attach_form($account, $form, $form_state);
|
|
||||||
|
|
||||||
if ($admin) {
|
if ($admin) {
|
||||||
// Redirect back to page which initiated the create request; usually
|
// Redirect back to page which initiated the create request; usually
|
||||||
// admin/people/create.
|
// admin/people/create.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue