ContentEntityFormController.php 5.16 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
<?php

/**
 * @file
 * Contains \Drupal\Core\Entity\ContentEntityFormController.
 */

namespace Drupal\Core\Entity;

use Drupal\Core\Language\Language;
11
use Symfony\Component\DependencyInjection\ContainerInterface;
12
13
14
15
16
17
18
19

/**
 * Entity form controller variant for content entity types.
 *
 * @see \Drupal\Core\ContentEntityBase
 */
class ContentEntityFormController extends EntityFormController {

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
  /**
   * The entity manager.
   *
   * @var \Drupal\Core\Entity\EntityManagerInterface
   */
  protected $entityManager;

  /**
   * Constructs a ContentEntityFormController object.
   *
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
   *   The entity manager.
   */
  public function __construct(EntityManagerInterface $entity_manager) {
    $this->entityManager = $entity_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity.manager')
    );
  }

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
  /**
   * {@inheritdoc}
   */
  public function form(array $form, array &$form_state) {
    $entity = $this->entity;
    // @todo Exploit the Field API to generate the default widgets for the
    // entity fields.
    $info = $entity->entityInfo();
    if (!empty($info['fieldable'])) {
      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;
  }

  /**
   * {@inheritdoc}
   */
  public function validate(array $form, array &$form_state) {
68
    $this->updateFormLangcode($form_state);
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
    $entity = $this->buildEntity($form, $form_state);
    $entity_type = $entity->entityType();
    $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.
    // Execute legacy global validation handlers.
    unset($form_state['validate_handlers']);
    form_execute_handlers('validate', $form, $form_state);
  }

  /**
   * Initialize the form state and the entity before the first form build.
   */
  protected function init(array &$form_state) {
    // Ensure we act on the translation object corresponding to the current form
    // language.
    $langcode = $this->getFormLangcode($form_state);
105
106
    $this->entity = $this->entity->getTranslation($langcode);
    parent::init($form_state);
107
108
109
110
111
  }

  /**
   * {@inheritdoc}
   */
112
113
114
115
116
117
  public function getFormLangcode(array &$form_state) {
    if (empty($form_state['langcode'])) {
      // Imply a 'view' operation to ensure users edit entities in the same
      // language they are displayed. This allows to keep contextual editing
      // working also for multilingual entities.
      $form_state['langcode'] = $this->entityManager->getTranslationFromContext($this->entity)->language()->id;
118
    }
119
    return $form_state['langcode'];
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
  }

  /**
   * {@inheritdoc}
   */
  public function isDefaultFormLangcode(array $form_state) {
    return $this->getFormLangcode($form_state) == $this->entity->getUntranslated()->language()->id;
  }

  /**
   * {@inheritdoc}
   */
  public function buildEntity(array $form, array &$form_state) {
    $entity = clone $this->entity;
    $entity_type = $entity->entityType();
    $info = entity_get_info($entity_type);

137
    // @todo Exploit the Entity Field API to process the submitted field values.
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
    // Copy top-level form values that are entity fields but not handled by
    // field API without changing existing entity fields that are not being
    // edited by this form. Values of fields handled by field API are copied
    // by field_attach_extract_form_values() below.
    $values_excluding_fields = $info['fieldable'] ? array_diff_key($form_state['values'], field_info_instances($entity_type, $entity->bundle())) : $form_state['values'];
    $definitions = $entity->getPropertyDefinitions();
    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'])) {
      foreach ($form['#entity_builders'] as $function) {
        call_user_func_array($function, array($entity_type, $entity, &$form, &$form_state));
      }
    }

    // Invoke field API for copying field values.
    if ($info['fieldable']) {
      field_attach_extract_form_values($entity, $form, $form_state, array('langcode' => $this->getFormLangcode($form_state)));
    }
    return $entity;
  }
163

164
}