GraphQLFieldRow::getFieldType()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
1
<?php
2
3
namespace Drupal\graphql_views\Plugin\views\row;
4
5
use Drupal\Core\Form\FormStateInterface;
6
use Drupal\views\ViewExecutable;
7
use Drupal\views\Plugin\views\display\DisplayPluginBase;
8
use Drupal\views\Plugin\views\row\RowPluginBase;
9
10
/**
11
 * Plugin which displays fields as raw data.
12
 *
13
 * @ViewsRow(
14
 *   id = "graphql_field",
15
 *   title = @Translation("Fields"),
16
 *   help = @Translation("Use fields as row data."),
17
 *   display_types = {"graphql"}
18
 * )
19
 */
20
class GraphQLFieldRow extends RowPluginBase {
21
22
  /**
23
   * {@inheritdoc}
24
   */
25
  protected $usesFields = TRUE;
26
27
  /**
28
   * Stores an array of prepared field aliases from options.
29
   *
30
   * @var array
31
   */
32
  protected $replacementAliases = [];
33
34
  /**
35
   * Stores an array of options to determine if the raw field output is used.
36
   *
37
   * @var array
38
   */
39
  protected $rawOutputOptions = [];
40
41
  /**
42
   * Stores an array of field GrpahQL type.
43
   *
44
   * @var array
45
   */
46
  protected $typeOptions = [];
47
48
  /**
49
   * {@inheritdoc}
50
   */
51
  public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
52
    parent::init($view, $display, $options);
53
54
    if (!empty($this->options['field_options'])) {
55
      $options = (array) $this->options['field_options'];
56
      // Prepare a trimmed version of replacement aliases.
57
      $aliases = static::extractFromOptionsArray('alias', $options);
58
      $this->replacementAliases = array_filter(array_map('trim', $aliases));
59
      // Prepare an array of raw output field options.
60
      $this->rawOutputOptions = static::extractFromOptionsArray('raw_output', $options);
61
      $this->typeOptions = static::extractFromOptionsArray('type', $options);
62
    }
63
  }
64
65
  /**
66
   * {@inheritdoc}
67
   */
68
  protected function defineOptions() {
69
    $options = parent::defineOptions();
70
    $options['field_options'] = ['default' => []];
71
72
    return $options;
73
  }
74
75
  /**
76
   * {@inheritdoc}
77
   */
78
  public function buildOptionsForm(&$form, FormStateInterface $form_state) {
79
    parent::buildOptionsForm($form, $form_state);
80
81
    $form['field_options'] = [
82
      '#type' => 'table',
83
      '#header' => [
84
        $this->t('Field'),
85
        $this->t('Alias'),
86
        $this->t('Raw output'),
87
        $this->t('Type'),
88
      ],
89
      '#empty' => $this->t('You have no fields. Add some to your view.'),
90
      '#tree' => TRUE,
91
    ];
92
93
    $options = $this->options['field_options'];
94
95
    if ($fields = $this->view->display_handler->getOption('fields')) {
96
      foreach ($fields as $id => $field) {
97
        // Don't show the field if it has been excluded.
98
        if (!empty($field['exclude'])) {
99
          continue;
100
        }
101
102
        $form['field_options'][$id]['field'] = [
103
          '#markup' => $id,
104
        ];
105
106
        $form['field_options'][$id]['alias'] = [
107
          '#title' => $this->t('Alias for @id', ['@id' => $id]),
108
          '#title_display' => 'invisible',
109
          '#type' => 'textfield',
110
          '#default_value' => isset($options[$id]['alias']) ? $options[$id]['alias'] : '',
111
          '#element_validate' => [[$this, 'validateAliasName']],
112
        ];
113
114
        $form['field_options'][$id]['raw_output'] = [
115
          '#title' => $this->t('Raw output for @id', ['@id' => $id]),
116
          '#title_display' => 'invisible',
117
          '#type' => 'checkbox',
118
          '#default_value' => isset($options[$id]['raw_output']) ? $options[$id]['raw_output'] : '',
119
        ];
120
121
        $form['field_options'][$id]['type'] = [
122
          '#type' => 'select',
123
          '#options' => [
124
            'String' => $this->t('String'),
125
            'Int' => $this->t('Int'),
126
            'Float' => $this->t('Float'),
127
            'Boolean' => $this->t('Boolean'),
128
          ],
129
          '#default_value' => isset($options[$id]['type']) ? $options[$id]['type'] : 'String',
130
        ];
131
      }
132
    }
133
  }
134
135
  /**
136
   * Form element validation handler.
137
   */
138
  public function validateAliasName($element, FormStateInterface $form_state) {
139
    if (preg_match('@[^A-Za-z0-9_-]+@', $element['#value'])) {
140
      $form_state->setError($element, $this->t('The machine-readable name must contain only letters, numbers, dashes and underscores.'));
141
    }
142
  }
143
144
  /**
145
   * {@inheritdoc}
146
   */
147
  public function validateOptionsForm(&$form, FormStateInterface $form_state) {
148
    // Collect an array of aliases to validate.
149
    $aliases = static::extractFromOptionsArray('alias', $form_state->getValue(['row_options', 'field_options']));
150
151
    // If array filter returns empty, no values have been entered. Unique keys
152
    // should only be validated if we have some.
153
    if (($filtered = array_filter($aliases)) && (array_unique($filtered) !== $filtered)) {
154
      $form_state->setErrorByName('aliases', $this->t('All field aliases must be unique'));
155
    }
156
  }
157
158
  /**
159
   * {@inheritdoc}
160
   */
161
  public function render($row) {
162
    $output = [];
163
164
    foreach ($this->view->field as $id => $field) {
165
      // If the raw output option has been set, just get the raw value.
166
      if (!empty($this->rawOutputOptions[$id])) {
167
        $value = $field->getValue($row);
168
      }
169
      // Otherwise, pass this through the field advancedRender() method.
170
      else {
171
        $value = $field->advancedRender($row);
172
      }
173
174
      // Omit excluded fields from the rendered output.
175
      if (empty($field->options['exclude'])) {
176
        $output[$this->getFieldKeyAlias($id)] = $value;
177
      }
178
    }
179
180
    return $output;
181
  }
182
183
  /**
184
   * Return an alias for a field ID, as set in the options form.
185
   *
186
   * @param string $id
187
   *   The field id to lookup an alias for.
188
   *
189
   * @return string
190
   *   The matches user entered alias, or the original ID if nothing is found.
191
   */
192
  public function getFieldKeyAlias($id) {
193
    if (isset($this->replacementAliases[$id])) {
194
      return $this->replacementAliases[$id];
195
    }
196
197
    return $id;
198
  }
199
200
  /**
201
   * Return a GraphQL field type, as set in the options form.
202
   *
203
   * @param string $id
204
   *   The field id to lookup a type for.
205
   *
206
   * @return string
207
   *   The matches user entered type, or String.
208
   */
209
  public function getFieldType($id) {
210
    if (isset($this->typeOptions[$id])) {
211
      return $this->typeOptions[$id];
212
    }
213
214
    return 'String';
215
  }
216
217
  /**
218
   * Extracts a set of option values from a nested options array.
219
   *
220
   * @param string $key
221
   *   The key to extract from each array item.
222
   * @param array $options
223
   *   The options array to return values from.
224
   *
225
   * @return array
226
   *   A regular one dimensional array of values.
227
   */
228
  protected static function extractFromOptionsArray($key, array $options) {
229
    return array_map(function($item) use ($key) {
230
      return isset($item[$key]) ? $item[$key] : NULL;
231
    }, $options);
232
  }
233
234
}
235