You are here

public function TourViewBuilder::viewMultiple in Drupal 10

Same name and namespace in other branches
  1. 8 core/modules/tour/src/TourViewBuilder.php \Drupal\tour\TourViewBuilder::viewMultiple()
  2. 9 core/modules/tour/src/TourViewBuilder.php \Drupal\tour\TourViewBuilder::viewMultiple()

Builds the render array for the provided entities.

Parameters

array $entities: An array of entities implementing EntityInterface to view.

string $view_mode: (optional) The view mode that should be used to render the entity.

string $langcode: (optional) For which language the entity should be rendered, defaults to the current content language.

Return value

A render array for the entities, indexed by the same keys as the entities array passed in $entities.

Throws

\InvalidArgumentException Can be thrown when the set of parameters is inconsistent, like when trying to view Comments and passing a Node which is not the one the comments belongs to, or not passing one, and having the comments node not be available for loading.

Overrides EntityViewBuilder::viewMultiple

File

core/modules/tour/src/TourViewBuilder.php, line 17

Class

TourViewBuilder
Provides a Tour view builder.

Namespace

Drupal\tour

Code

public function viewMultiple(array $entities = [], $view_mode = 'full', $langcode = NULL) {

  /** @var \Drupal\tour\TourInterface[] $entities */
  $tour = [];
  $cache_tags = [];
  $total_tips = 0;
  foreach ($entities as $entity_id => $entity) {
    $tour[$entity_id] = $entity
      ->getTips();
    $total_tips += count($tour[$entity_id]);
    $cache_tags = Cache::mergeTags($cache_tags, $entity
      ->getCacheTags());
  }
  $items = [];
  foreach ($tour as $tour_id => $tips) {
    $tourEntity = $entities[$tour_id];
    foreach ($tips as $index => $tip) {
      $classes = [
        'tip-module-' . Html::getClass($tourEntity
          ->getModule()),
        'tip-type-' . Html::getClass($tip
          ->getPluginId()),
        'tip-' . Html::getClass($tip
          ->id()),
      ];
      $selector = $tip
        ->getSelector();
      $location = $tip
        ->getLocation();
      $body_render_array = $tip
        ->getBody();
      $body = (string) \Drupal::service('renderer')
        ->renderPlain($body_render_array);
      $output = [
        'body' => $body,
        'title' => Html::escape($tip
          ->getLabel()),
      ];
      $selector = $tip
        ->getSelector();
      if ($output) {
        $items[] = [
          'id' => $tip
            ->id(),
          'selector' => $selector,
          'module' => $tourEntity
            ->getModule(),
          'type' => $tip
            ->getPluginId(),
          'counter' => $this
            ->t('@tour_item of @total', [
            '@tour_item' => $index + 1,
            '@total' => $total_tips,
          ]),
          'attachTo' => [
            'element' => $selector,
            'on' => $location ?? 'bottom-start',
          ],
          // Shepherd expects classes to be provided as a string.
          'classes' => implode(' ', $classes),
        ] + $output;
      }
    }
  }

  // If there is at least one tour item, build the tour.
  if ($items) {
    end($items);
    $key = key($items);
    $items[$key]['cancelText'] = t('End tour');
  }
  $build = [
    '#cache' => [
      'tags' => $cache_tags,
    ],
  ];

  // If at least one tour was built, attach tips and the tour library.
  if ($items) {
    $build['#attached']['drupalSettings']['tourShepherdConfig'] = [
      'defaultStepOptions' => [
        'classes' => 'drupal-tour',
        'cancelIcon' => [
          'enabled' => TRUE,
          'label' => $this
            ->t('Close'),
        ],
        'modalOverlayOpeningPadding' => 3,
        'scrollTo' => [
          'behavior' => 'smooth',
          'block' => 'center',
        ],
        'popperOptions' => [
          'modifiers' => [
            // Prevent overlap with the element being highlighted.
            [
              'name' => 'offset',
              'options' => [
                'offset' => [
                  -10,
                  20,
                ],
              ],
            ],
            // Pad the arrows so they don't hit the edge of rounded corners.
            [
              'name' => 'arrow',
              'options' => [
                'padding' => 12,
              ],
            ],
            // Disable Shepherd's focusAfterRender modifier, which results in
            // the tour item container being focused on any scroll or resize
            // event.
            [
              'name' => 'focusAfterRender',
              'enabled' => FALSE,
            ],
          ],
        ],
      ],
      'useModalOverlay' => TRUE,
    ];

    // This property is used for storing the tour items. It may change without
    // notice and should not be extended or modified in contrib.
    // see: https://www.drupal.org/project/drupal/issues/3214593
    $build['#attached']['drupalSettings']['_tour_internal'] = $items;
    $build['#attached']['library'][] = 'tour/tour';
  }
  return $build;
}