FacetListBuilder.php 11.6 KB
Newer Older
Nick_vh's avatar
Nick_vh committed
1 2
<?php

3
namespace Drupal\facets;
Nick_vh's avatar
Nick_vh committed
4

5
use Drupal\Core\Config\Entity\DraggableListBuilder;
Nick_vh's avatar
Nick_vh committed
6
use Drupal\Core\Entity\EntityInterface;
7
use Drupal\Core\Form\FormStateInterface;
8
use Drupal\Core\Link;
9
use Drupal\Component\Utility\Html;
10 11
use Drupal\facets_summary\Entity\FacetsSummary;
use Drupal\facets_summary\FacetsSummaryInterface;
Nick_vh's avatar
Nick_vh committed
12 13

/**
14
 * Builds a listing of facet entities.
Nick_vh's avatar
Nick_vh committed
15
 */
16 17
class FacetListBuilder extends DraggableListBuilder {

Nick_vh's avatar
Nick_vh committed
18 19 20
  /**
   * {@inheritdoc}
   */
21 22
  public function getFormId() {
    return 'facets_overview';
Nick_vh's avatar
Nick_vh committed
23 24 25 26 27 28
  }

  /**
   * {@inheritdoc}
   */
  public function getDefaultOperations(EntityInterface $entity) {
29
    $operations = parent::getDefaultOperations($entity);
Nick_vh's avatar
Nick_vh committed
30 31

    if ($entity instanceof FacetInterface) {
Nick_vh's avatar
Nick_vh committed
32

Nick_vh's avatar
Nick_vh committed
33
      if ($entity->access('update') && $entity->hasLinkTemplate('edit-form')) {
34
        $operations['edit'] = [
Nick_vh's avatar
Nick_vh committed
35 36
          'title' => $this->t('Edit'),
          'weight' => 10,
37
          'url' => $entity->toUrl('edit-form'),
38
        ];
Nick_vh's avatar
Nick_vh committed
39
      }
40
      if ($entity->access('update') && $entity->hasLinkTemplate('settings-form')) {
41
        $operations['settings'] = [
42
          'title' => $this->t('Facet settings'),
43
          'weight' => 20,
44
          'url' => $entity->toUrl('settings-form'),
45
        ];
46
      }
47
      if ($entity->access('update') && $entity->hasLinkTemplate('clone-form')) {
48
        $operations['clone'] = [
49 50 51
          'title' => $this->t('Clone facet'),
          'weight' => 90,
          'url' => $entity->toUrl('clone-form'),
52
        ];
53
      }
Nick_vh's avatar
Nick_vh committed
54
      if ($entity->access('delete') && $entity->hasLinkTemplate('delete-form')) {
55
        $operations['delete'] = [
Nick_vh's avatar
Nick_vh committed
56 57
          'title' => $this->t('Delete'),
          'weight' => 100,
58
          'url' => $entity->toUrl('delete-form'),
59
        ];
Nick_vh's avatar
Nick_vh committed
60
      }
61 62
    }
    elseif ($entity instanceof FacetsSummaryInterface) {
63
      $operations['edit'] = [
64 65 66
        'title' => $this->t('Edit'),
        'weight' => 10,
        'url' => $entity->toUrl('edit-form'),
67
      ];
68
      if ($entity->access('update') && $entity->hasLinkTemplate('settings-form')) {
69
        $operations['settings'] = [
70 71 72
          'title' => $this->t('Facet Summary settings'),
          'weight' => 20,
          'url' => $entity->toUrl('settings-form'),
73
        ];
74 75
      }
      if ($entity->access('delete') && $entity->hasLinkTemplate('delete-form')) {
76
        $operations['delete'] = [
77 78 79
          'title' => $this->t('Delete'),
          'weight' => 100,
          'url' => $entity->toUrl('delete-form'),
80
        ];
81
      }
Nick_vh's avatar
Nick_vh committed
82 83 84 85 86 87 88 89 90
    }

    return $operations;
  }

  /**
   * {@inheritdoc}
   */
  public function buildHeader() {
91
    $header = [
92 93 94
      'type' => $this->t('Type'),
      'title' => [
        'data' => $this->t('Title'),
95
      ],
96 97
    ];
    return $header + parent::buildHeader();
Nick_vh's avatar
Nick_vh committed
98 99 100 101 102 103
  }

  /**
   * {@inheritdoc}
   */
  public function buildRow(EntityInterface $entity) {
104
    /** @var \Drupal\facets\FacetInterface $entity */
105
    $facet = $entity;
106 107 108 109 110 111 112
    $row = [
      'type' => [
        '#theme_wrappers' => [
          'container' => [
            '#attributes' => ['class' => 'facets-type'],
          ],
        ],
113 114
        '#type' => 'markup',
        '#markup' => 'Facet',
115 116
      ],
      'title' => [
117 118 119
        '#type' => 'link',
        '#title' => $facet->label(),
        '#suffix' => '<div>' . $entity->getFieldAlias() . ' - ' . $facet->getWidget()['type'] . '</div>',
120 121 122 123 124 125 126
        '#attributes' => [
          'class' => ['search-api-title'],
        ],
      ] + $facet->toUrl('edit-form')->toRenderArray(),
      '#attributes' => [
        'title' => $this->t('ID: @name', ['@name' => $facet->id()]),
        'class' => [
127
          'facet',
128 129 130
        ],
      ],
    ];
131 132 133 134 135 136 137
    return array_merge_recursive($row, parent::buildRow($entity));
  }

  /**
   * Builds an array of facet summary for display in the overview.
   */
  public function buildFacetSummaryRow(FacetsSummaryInterface $entity) {
138
    /** @var \Drupal\facets\FacetInterface $entity */
139 140
    $facet = $entity;
    $row = parent::buildRow($entity);
141 142 143 144 145 146 147
    return [
      'type' => [
        '#theme_wrappers' => [
          'container' => [
            '#attributes' => ['class' => 'facets-summary-type'],
          ],
        ],
148 149
        '#type' => 'markup',
        '#markup' => 'Facets Summary',
150 151
      ],
      'title' => [
152 153 154
        '#theme_wrappers' => [
          'container' => [
            '#attributes' => ['class' => 'facets-title'],
155
          ],
156 157 158 159 160 161 162 163 164 165 166
        ],
        '#type' => 'link',
        '#title' => $facet->label(),
        '#attributes' => [
          'class' => ['search-api-title'],
        ],
        '#wrapper_attributes' => [
          'colspan' => 2,
        ],
      ] + $facet->toUrl('edit-form')->toRenderArray(),
      'operations' => $row['operations'],
167 168 169
      '#attributes' => [
        'title' => $this->t('ID: @name', ['@name' => $facet->id()]),
        'class' => [
170
          'facet',
171 172 173
        ],
      ],
    ];
174 175 176
  }

  /**
177
   * Builds an array of facet sources for display in the overview.
178
   */
179
  public function buildFacetSourceRow(array $facet_source = []) {
180 181 182 183 184 185 186
    return [
      'type' => [
        '#theme_wrappers' => [
          'container' => [
            '#attributes' => ['class' => 'facets-type'],
          ],
        ],
187 188
        '#type' => 'markup',
        '#markup' => 'Facet source',
189 190 191 192 193
      ],
      'title' => [
        '#theme_wrappers' => [
          'container' => [
            '#attributes' => ['class' => 'facets-title'],
194
          ],
195
        ],
196 197
        '#type' => 'markup',
        '#markup' => $facet_source['id'],
198
        '#wrapper_attributes' => [
199
          'colspan' => 2,
200 201 202
        ],
      ],
      'operations' => [
203 204 205 206 207
        'data' => Link::createFromRoute(
          $this->t('Configure'),
          'entity.facets_facet_source.edit_form',
          ['facets_facet_source' => $facet_source['id']]
        )->toRenderable(),
208 209 210
      ],
      '#attributes' => [
        'class' => ['facet-source', 'facet-source-' . $facet_source['id']],
211
        'no_striping' => TRUE,
212 213
      ],
    ];
Nick_vh's avatar
Nick_vh committed
214 215 216 217 218
  }

  /**
   * {@inheritdoc}
   */
219
  public function buildForm(array $form, FormStateInterface $form_state) {
220
    $groups = $this->loadGroups();
221

222
    $form['facets'] = [
223 224 225
      '#type' => 'table',
      '#header' => $this->buildHeader(),
      '#empty' => $groups['lone_facets'] ? '' : $this->t('There are no facet sources or facets defined.'),
226 227
      '#attributes' => [
        'class' => [
228
          'facets-groups-list',
229 230 231
        ],
      ],
    ];
232

233 234 235 236 237 238 239
    // When no facet sources are found, we should show a message that you can't
    // add facets yet.
    if (empty($groups['facet_source_groups'])) {
      return [
        '#markup' => $this->t(
          'You currently have no facet sources defined. You should start by adding a facet source before creating facets.<br />
           An example of a facet source is a view based on Search API or a Search API page.
240
           Other modules can also implement a facet source by providing a plugin that implements the FacetSourcePluginInterface.'
borisson_'s avatar
borisson_ committed
241
        ),
242 243 244
      ];
    }

245
    $form['#attached']['library'][] = 'facets/drupal.facets.admin_css';
246 247

    foreach ($groups['facet_source_groups'] as $facet_source_group) {
248 249 250
      $subgroup_class = Html::cleanCssIdentifier('facets-weight-' . $facet_source_group['facet_source']['id']);
      $delta = round(count($facet_source_group['facets']) / 2);

251
      $form['facets']['#tabledrag'][] = [
252 253 254 255
        'action' => 'order',
        'relationship' => 'sibling',
        'group' => 'weight',
        'subgroup' => $subgroup_class,
256
      ];
257
      $form['facets'][$facet_source_group['facet_source']['id']] = $this->buildFacetSourceRow($facet_source_group['facet_source']);
258
      foreach ($facet_source_group['facets'] as $i => $facet) {
259 260 261 262 263
        if ($facet instanceof FacetInterface) {
          $form['facets'][$facet->id()] = $this->buildRow($facet);
          $form['facets'][$facet->id()]['weight']['#attributes']['class'][] = $subgroup_class;
          $form['facets'][$facet->id()]['weight']['#delta'] = $delta;
        }
264
        elseif ($facet instanceof FacetsSummaryInterface) {
265 266
          $form['facets'][$facet->id()] = $this->buildFacetSummaryRow($facet);
        }
267 268 269 270 271
      }
    }

    // Output the list of facets without a facet source separately.
    if (!empty($groups['lone_facets'])) {
272
      $subgroup_class = 'facets-weight-lone-facets';
273
      $form['facets']['#tabledrag'][] = [
274 275 276 277
        'action' => 'order',
        'relationship' => 'sibling',
        'group' => 'weight',
        'subgroup' => $subgroup_class,
278 279 280 281 282 283 284 285
      ];
      $form['facets']['lone_facets'] = [
        'type' => [
          '#theme_wrappers' => [
            'container' => [
              '#attributes' => ['class' => 'facets-type'],
            ],
          ],
286 287
          '#type' => 'markup',
          '#markup' => '<h3>' . $this->t('Facets not currently associated with any facet source') . '</h3>',
288 289
        ],
        '#wrapper_attributes' => [
290
          'colspan' => 4,
291 292
        ],
      ];
293 294 295
      foreach ($facet_source_group['facets'] as $i => $facet) {
        $form['facets'][$facet->id()] = $this->buildRow($facet);
        $form['facets'][$facet->id()]['weight']['#attributes']['class'][] = $subgroup_class;
296 297
      }
    }
298

299
    $form['actions']['#type'] = 'actions';
300
    $form['actions']['submit'] = [
301 302 303
      '#type' => 'submit',
      '#value' => t('Save'),
      '#button_type' => 'primary',
304
    ];
305 306 307 308 309 310 311 312 313 314 315

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    $entities = $this->storage->loadMultiple(array_keys($form_state->getValue('facets')));
    /** @var \Drupal\block\BlockInterface[] $entities */
    foreach ($entities as $entity_id => $entity) {
316
      $entity_values = $form_state->getValue(['facets', $entity_id]);
317 318 319 320
      $entity->setWeight($entity_values['weight']);
      $entity->save();
    }
    drupal_set_message(t('The facets have been updated.'));
Nick_vh's avatar
Nick_vh committed
321 322
  }

323 324 325 326 327 328 329 330 331 332
  /**
   * Loads facet sources and facets, grouped by facet sources.
   *
   * @return \Drupal\Core\Config\Entity\ConfigEntityInterface[][]
   *   An associative array with two keys:
   *   - facet sources: All available facet sources, each followed by all facets
   *     attached to it.
   *   - lone_facets: All facets that aren't attached to any facet source.
   */
  public function loadGroups() {
333
    $facet_source_plugin_manager = \Drupal::service('plugin.manager.facets.facet_source');
334
    $facets = $this->load();
335 336 337 338
    $facets_summaries = [];
    if (\Drupal::moduleHandler()->moduleExists('facets_summary')) {
      $facets_summaries = FacetsSummary::loadMultiple();
    }
339 340
    $facet_sources = $facet_source_plugin_manager->getDefinitions();

341
    $facet_source_groups = [];
342 343 344
    foreach ($facet_sources as $facet_source) {
      $facet_source_groups[$facet_source['id']] = [
        'facet_source' => $facet_source,
borisson_'s avatar
borisson_ committed
345
        'facets' => [],
346 347 348
      ];

      foreach ($facets as $facet) {
349
        /** @var \Drupal\facets\FacetInterface $facet */
350
        if ($facet->getFacetSourceId() == $facet_source['id']) {
351 352 353 354 355 356
          $facet_source_groups[$facet_source['id']]['facets'][$facet->id()] = $facet;
          // Remove this facet from $facet so it will finally only contain those
          // facets not belonging to any facet_source.
          unset($facets[$facet->id()]);
        }
      }
357 358 359 360 361 362 363 364 365 366

      foreach ($facets_summaries as $summary) {
        /** @var \Drupal\facets_summary\FacetsSummaryInterface $summary */
        if ($summary->getFacetSourceId() == $facet_source['id']) {
          $facet_source_groups[$facet_source['id']]['facets'][$summary->id()] = $summary;
          // Remove this facet from $facet so it will finally only contain those
          // facets not belonging to any facet_source.
          unset($facets_summaries[$summary->id()]);
        }
      }
367 368
    }

369
    return [
370 371
      'facet_source_groups' => $facet_source_groups,
      'lone_facets' => $facets,
372
    ];
373
  }
374

Nick_vh's avatar
Nick_vh committed
375
}