Completed
Push — 8.x-1.x ( f23998...729d7d )
by Janez
02:46
created

EntityBrowserElement::valueCallback()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 4
eloc 7
c 1
b 0
f 0
nc 4
nop 3
dl 0
loc 12
rs 9.2
1
<?php
2
3
namespace Drupal\entity_browser\Element;
4
5
use Drupal\Component\Utility\Html;
6
use Drupal\Core\Form\FormStateInterface;
7
use Drupal\Core\Render\Element\FormElement;
8
use Drupal\entity_browser\Entity\EntityBrowser;
9
use Drupal\Core\Entity\EntityInterface;
10
11
/**
12
 * Provides an Entity Browser form element.
13
 *
14
 * Properties:
15
 * - #entity_browser: Entity browser or ID of the Entity browser to be used.
16
 * - #cardinality: (optional) Maximum number of items that are expected from
17
 *     the entity browser. Unlimited by default.
18
 * - #default_value: (optional) Array of entities that Entity browser should be
19
 *     initialized with.
20
 * - #entity_browser_validators: (optional) Array of validators that are to be
21
 *     passed to the entity browser. Array keys are plugin IDs and array values
22
 *     are plugin configuration values. Cardinality validator will be set
23
 *     automatically.
24
 *
25
 * Return value will be an array of selected entities, which will appear under
26
 * 'entities' key on the root level of the element's values in the form state.
27
 *
28
 * @FormElement("entity_browser")
29
 */
30
class EntityBrowserElement extends FormElement {
31
32
  /**
33
   * Indicating an entity browser can return an unlimited number of values.
34
   */
35
  const CARDINALITY_UNLIMITED = -1;
36
37
  /**
38
   * {@inheritdoc}
39
   */
40
  public function getInfo() {
41
    $class = get_class($this);
42
    return [
43
      '#input' => TRUE,
44
      '#tree' => TRUE,
45
      '#cardinality' => $this::CARDINALITY_UNLIMITED,
46
      '#process' => [[$class, 'processEntityBrowser']],
47
      '#default_value' => [],
48
      '#entity_browser_validators' => [],
49
      '#attached' => ['library' => ['entity_browser/common']],
50
    ];
51
  }
52
53
  /**
54
   * Render API callback: Processes the entity browser element.
55
   */
56
  public static function processEntityBrowser(&$element, FormStateInterface $form_state, &$complete_form) {
57
    /** @var \Drupal\entity_browser\EntityBrowserInterface $entity_browser */
58
    if (is_string($element['#entity_browser'])) {
59
      $entity_browser = EntityBrowser::load($element['#entity_browser']);
60
    }
61
    else {
62
      $entity_browser = $element['#entity_browser'];
63
    }
64
65
    $default_value = implode(' ', array_map(
66
      function (EntityInterface $item) {
67
        return $item->getEntityTypeId() . ':' . $item->id();
68
      },
69
      $element['#default_value']
70
    ));
71
    $validators = array_merge(
72
      $element['#entity_browser_validators'],
73
      ['cardinality' => ['cardinality' => $element['#cardinality']]]
74
    );
75
76
    $display = $entity_browser->getDisplay();
77
    $display->setUuid(sha1(implode('-', array_merge([$complete_form['#build_id']], $element['#parents']))));
78
    $element['entity_browser'] = [
79
      '#eb_parents' => array_merge($element['#parents'], ['entity_browser']),
80
    ];
81
    $element['entity_browser'] = $display->displayEntityBrowser(
82
      $element['entity_browser'],
83
      $form_state,
84
      $complete_form,
85
      ['validators' => $validators, 'selected_entities' => $element['#default_value']]
86
    );
87
88
    $hidden_id = Html::getUniqueId($element['#id'] . '-target');
89
    $element['entity_ids'] = [
90
      '#type' => 'hidden',
91
      '#id' => $hidden_id,
92
      // We need to repeat ID here as it is otherwise skipped when rendering.
93
      '#attributes' => ['id' => $hidden_id, 'class' => ['ed-target']],
94
      '#default_value' => $default_value,
95
    ];
96
97
    $element['#attached']['drupalSettings']['entity_browser'] = [
98
      $entity_browser->getDisplay()->getUuid() => [
99
        'cardinality' => $element['#cardinality'],
100
        'selector' => '#' . $hidden_id,
101
      ],
102
    ];
103
104
    return $element;
105
  }
106
107
  /**
108
   * {@inheritdoc}
109
   */
110
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
111
    if ($input === FALSE) {
112
      return $element['#default_value'] ?: [];
113
    }
114
115
    $entities = [];
116
    if ($input['entity_ids']) {
117
      $entities = static::processEntityIds($input['entity_ids']);
118
    }
119
120
    return ['entities' => $entities];
121
  }
122
123
  /**
124
   * Processes entity IDs and gets array of loaded entities.
125
   *
126
   * @param array|string $ids
127
   *   Processes entity IDs as they are returned from the entity browser. They
128
   *   are in [entity_type_id]:[entity_id] form. Array of IDs or a
129
   *   space-delimited string is supported.
130
   *
131
   * @return \Drupal\Core\Entity\EntityInterface[]
132
   *   Array of entity objects.
133
   */
134
  public static function processEntityIds($ids) {
135
    if (!is_array($ids)) {
136
      $ids = array_filter(explode(' ', $ids));
137
    }
138
139
    return array_map(
140
      function ($item) {
141
        list($entity_type, $entity_id) = explode(':', $item);
142
        return \Drupal::entityTypeManager()->getStorage($entity_type)->load($entity_id);
143
      },
144
      $ids
145
    );
146
  }
147
148
  /**
149
   * Processes entity IDs and gets array of loaded entities.
150
   *
151
   * @param string $id
152
   *   Processes entity ID as it is returned from the entity browser. ID should
153
   *   be in [entity_type_id]:[entity_id] form.
154
   *
155
   * @return \Drupal\Core\Entity\EntityInterface
156
   *   Entity object.
157
   */
158
  public static function processEntityId($id) {
159
    $return = static::processEntityIds([$id]);
160
    return current($return);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression current($return); of type Drupal\Core\Entity\EntityInterface|false adds false to the return on line 160 which is incompatible with the return type documented by Drupal\entity_browser\El...lement::processEntityId of type Drupal\Core\Entity\EntityInterface. It seems like you forgot to handle an error condition.
Loading history...
161
  }
162
163
}
164