View source
<?php
namespace Drupal\Core\Entity\Entity;
use Drupal\Core\Entity\EntityConstraintViolationListInterface;
use Drupal\Core\Entity\EntityDisplayPluginCollection;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\EntityDisplayBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\Validator\ConstraintViolation;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\ConstraintViolationListInterface;
class EntityFormDisplay extends EntityDisplayBase implements EntityFormDisplayInterface {
protected $displayContext = 'form';
public static function collectRenderDisplay(FieldableEntityInterface $entity, $form_mode) {
$entity_type = $entity
->getEntityTypeId();
$bundle = $entity
->bundle();
if ($form_mode != 'default') {
$candidate_ids[] = $entity_type . '.' . $bundle . '.' . $form_mode;
}
$candidate_ids[] = $entity_type . '.' . $bundle . '.default';
$results = \Drupal::entityQuery('entity_form_display')
->condition('id', $candidate_ids)
->condition('status', TRUE)
->execute();
$storage = \Drupal::entityManager()
->getStorage('entity_form_display');
foreach ($candidate_ids as $candidate_id) {
if (isset($results[$candidate_id])) {
$display = $storage
->load($candidate_id);
break;
}
}
if (empty($display)) {
$display = $storage
->create(array(
'targetEntityType' => $entity_type,
'bundle' => $bundle,
'mode' => $form_mode,
'status' => TRUE,
));
}
$display->originalMode = $form_mode;
$display_context = array(
'entity_type' => $entity_type,
'bundle' => $bundle,
'form_mode' => $form_mode,
);
\Drupal::moduleHandler()
->alter('entity_form_display', $display, $display_context);
return $display;
}
public function __construct(array $values, $entity_type) {
$this->pluginManager = \Drupal::service('plugin.manager.field.widget');
parent::__construct($values, $entity_type);
}
public function getRenderer($field_name) {
if (isset($this->plugins[$field_name])) {
return $this->plugins[$field_name];
}
if (($configuration = $this
->getComponent($field_name)) && isset($configuration['type']) && ($definition = $this
->getFieldDefinition($field_name))) {
$widget = $this->pluginManager
->getInstance(array(
'field_definition' => $definition,
'form_mode' => $this->originalMode,
'prepare' => FALSE,
'configuration' => $configuration,
));
}
else {
$widget = NULL;
}
$this->plugins[$field_name] = $widget;
return $widget;
}
public function buildForm(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state) {
$form += array(
'#parents' => array(),
);
foreach ($this
->getComponents() as $name => $options) {
if ($widget = $this
->getRenderer($name)) {
$items = $entity
->get($name);
$items
->filterEmptyItems();
$form[$name] = $widget
->form($items, $form, $form_state);
$form[$name]['#access'] = $items
->access('edit');
$form[$name]['#weight'] = $options['weight'];
$field_definition = $this
->getFieldDefinition($name);
$this->renderer
->addCacheableDependency($form[$name], $field_definition);
$this->renderer
->addCacheableDependency($form[$name], $field_definition
->getFieldStorageDefinition());
}
}
$this->renderer
->addCacheableDependency($form, $this);
$form['#process'][] = array(
$this,
'processForm',
);
}
public function processForm($element, FormStateInterface $form_state, $form) {
foreach ($this
->getComponents() as $name => $options) {
if (isset($element[$name])) {
$element[$name]['#weight'] = $options['weight'];
}
}
$extra_fields = \Drupal::entityManager()
->getExtraFields($this->targetEntityType, $this->bundle);
$extra_fields = isset($extra_fields['form']) ? $extra_fields['form'] : array();
foreach ($extra_fields as $extra_field => $info) {
if (!$this
->getComponent($extra_field)) {
$element[$extra_field]['#access'] = FALSE;
}
}
return $element;
}
public function extractFormValues(FieldableEntityInterface $entity, array &$form, FormStateInterface $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;
}
public function validateFormValues(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state) {
$violations = $entity
->validate();
$violations
->filterByFieldAccess();
foreach ($violations
->getEntityViolations() as $violation) {
$form_state
->setErrorByName('', $violation
->getMessage());
}
$this
->flagWidgetsErrorsFromViolations($violations, $form, $form_state);
}
public function flagWidgetsErrorsFromViolations(EntityConstraintViolationListInterface $violations, array &$form, FormStateInterface $form_state) {
$entity = $violations
->getEntity();
foreach ($violations
->getFieldNames() as $field_name) {
if ($widget = $this
->getRenderer($field_name)) {
$field_violations = $this
->movePropertyPathViolationsRelativeToField($field_name, $violations
->getByField($field_name));
$widget
->flagErrors($entity
->get($field_name), $field_violations, $form, $form_state);
}
}
}
protected function movePropertyPathViolationsRelativeToField($field_name, ConstraintViolationListInterface $violations) {
$new_violations = new ConstraintViolationList();
foreach ($violations as $violation) {
$violation_path = $violation
->getPropertyPath();
$path_parts = explode('.', $violation_path);
if ($path_parts[0] === $field_name) {
unset($path_parts[0]);
}
$new_path = implode('.', $path_parts);
$constraint = NULL;
$cause = NULL;
$parameters = [];
$plural = NULL;
if ($violation instanceof ConstraintViolation) {
$constraint = $violation
->getConstraint();
$cause = $violation
->getCause();
$parameters = $violation
->getParameters();
$plural = $violation
->getPlural();
}
$new_violation = new ConstraintViolation($violation
->getMessage(), $violation
->getMessageTemplate(), $parameters, $violation
->getRoot(), $new_path, $violation
->getInvalidValue(), $plural, $violation
->getCode(), $constraint, $cause);
$new_violations
->add($new_violation);
}
return $new_violations;
}
public function getPluginCollections() {
$configurations = array();
foreach ($this
->getComponents() as $field_name => $configuration) {
if (!empty($configuration['type']) && ($field_definition = $this
->getFieldDefinition($field_name))) {
$configurations[$configuration['type']] = $configuration + array(
'field_definition' => $field_definition,
'form_mode' => $this->mode,
);
}
}
return array(
'widgets' => new EntityDisplayPluginCollection($this->pluginManager, $configurations),
);
}
}