io-8.x-1.x-dev/modules/io_browser/templates/io_browser.theme.inc

modules/io_browser/templates/io_browser.theme.inc
<?php

/**
 * @file
 * Hooks and preprocess functions for the IO Browser module.
 */

use Drupal\Core\Render\Element;
use Drupal\Core\StringTranslation\ByteSizeMarkup;
use Drupal\Component\Utility\DeprecationHelper;
use Drupal\io_browser\IoBrowserDefault as Defaults;
use Drupal\io_browser\IoBrowserUtil;

/**
 * Prepares variables for io-browser.html.twig templates.
 *
 * @todo Core image, Focal Point, Crop integration outside EB.
 */
function template_preprocess_io_browser(&$variables) {
  $element = $variables['element'];

  // Pre 2.10 only used variables were added, now many in case needed.
  foreach (Defaults::themeProperties() as $key => $default) {
    $k = $key == 'items' ? 'items' : "#$key";
    $variables[$key] = $element[$k] ?? $default;
  }

  $widgets   = $build = $draggables = $thumbs = [];
  $content   = &$variables['content'];
  $settings  = &$variables['settings'];
  $settings += Defaults::htmlSettings();
  $formatter = io_browser()->formatter();
  $blazies   = $formatter->verifySafely($settings);
  $ib        = $settings['iobrowsers'];

  // Get our list of widgets in order (needed when the form comes back after
  // preview or failed validation).
  // Image is stored as indexed children, media as items.
  $items = empty($variables['items']) ? $element : $variables['items'];
  foreach (Element::children($items) as $key) {
    $widgets[] = &$items[$key];
  }

  // Sort the items if required.
  if ($ib->get('widget.plugin_id') != 'entity_browser_entity_reference') {
    usort($widgets, '_field_multiple_value_form_sort_helper');
  }

  // Provides basic settings.
  $count = count($widgets);
  $uploading = isset($element['#file_upload_delta']);
  $element_id = $element['#id'];

  $settings['count'] = $count;
  $blazies->set('count', $count)
    ->set('css.element_id', $element_id);

  $ib->set('is.uploading', $uploading);

  // Massage settings.
  _io_browser_massage_settings($variables, $settings);

  foreach ($widgets as $delta => &$widget) {
    $sets = $settings;
    $sets['delta'] = $delta;

    // EB uses 'display' while core Image 'preview', get them consistent here.
    if (isset($widget['display'])) {
      $widget['preview'] = $widget['display'];
      unset($widget['display']);
    }

    if ($blazies->is('eb')) {
      $widget_classes = $widget['#attributes']['class'] ?? [];
      if ($widget_classes and is_array($widget_classes)) {
        $classes = ['item-container', 'draggable'];
        $widget['#attributes']['class'] = array_diff($widget_classes, $classes);
      }
    }
    else {
      // Save the uploading row for last, for image widget, not entity browser.
      if (isset($widget['#files']) && empty($widget['#files'])) {
        if ($title = ($element['#file_upload_title'] ?? NULL)) {
          $widget['#title'] = $title;
          $desc = $element['#file_upload_description'];

          // @todo use directly renderInIsolation() post blazy:2.28|3.0.6.
          if (method_exists($formatter, 'renderInIsolation')) {
            $widget['#description'] = $formatter->renderInIsolation($desc);
          }
          else {
            /* @phpstan-ignore-next-line */
            $widget['#description'] = $formatter->renderer()->renderPlain($desc);
          }
        }

        foreach (Element::children($widget) as $sub_key) {
          if (!in_array($sub_key, ['display', 'fids', 'upload', 'upload_button'])) {
            unset($widget[$sub_key]);
          }
        }

        continue;
      }
    }

    // Masages widgets.
    _io_browser_prepare_widget_item($widget, $sets, $delta);
    _io_browser_build_widget_item($widget, $sets, $delta);

    // Build the widget slides.
    $build['items'][] = $widget;

    // We don't do early rendering, hide em all now.
    foreach (Element::children($widget) as $sub_key) {
      hide($widget[$sub_key]);
    }

    // Place _weight and thumb into sortable element.
    if ($ib->is('sortable')) {
      $draggables[] = _io_browser_get_draggable($widget, $sets);
    }
  }

  // Pass variables to template.
  $content['header'] = $content['main'] = [];

  // Build buttons.
  $buttons = _io_browser_get_buttons($settings);

  // Build draggable.
  $content['draggable'] = _io_browser_build_draggables($buttons, $draggables);

  $build['#settings'] = $settings;

  if ($items = ($build['items'] ?? [])) {
    // Provide Blazy attributes for the containing element.
    $first = $items[0]['preview'] ?? [];
    if ($_uri = ($first['#uri'] ?? NULL)) {
      $blazies->set('first.uri', $_uri);
    }

    $variables['attributes']['data-blazy'] = '';

    $style = $settings['style'] ?? '';
    if ($style) {
      $attrs['class'][] = 'ib__grid';
      $item_attrs['class'][] = 'ib__sortitem';
      $item_attrs['class'][] = 'grid--ib';

      if ($style != 'single') {
        $attrs['class'][] = 'ib__sortable';
      }

      $blazies->set('grid.attributes', $attrs);
      $blazies->set('grid.item_attributes', $item_attrs);
    }

    $content['main'] = $formatter->build($build);
    $content['header'] = _io_browser_build_buttons($buttons);
  }

  unset($element['#theme_wrappers']);

  $variables['blazies'] = $settings['blazies']->storage();
  $variables['ib']      = $settings['iobrowsers']->storage();
}

/**
 * Massages settings.
 */
function _io_browser_massage_settings(array &$variables, array &$settings) {
  $blazies = $settings['blazies'];
  $ib = $settings['iobrowsers'];

  // This is because empty file upload is counted one.
  $count = $blazies->get('count') ?: 0;
  $cardinality = $blazies->get('field.cardinality') ?: 0;
  $field_name = $blazies->get('field.name');
  $multiple = $cardinality != 1;

  if ($ib->is('uploading')) {
    $count = $count > 1 ? ($count - 1) : $count;
  }
  if (!$multiple) {
    $count = 1;
  }

  $nav = !empty($settings['optionset_thumbnail']) && $count > 1 && $multiple;
  $field_name_css = str_replace('_', '-', $field_name);

  // Vanilla is on, rebuild own logic to support asnavfor as needed.
  $settings['id'] = $id = 'ib-' . $field_name_css;
  $is_text = !empty($settings['alt_field']) || !empty($settings['title_field']);
  $grids = ['column', 'grid', 'flex', 'nativegrid'];

  $blazies->set('css.id', $id)
    ->set('is.blazy', TRUE)
    ->set('is.vanilla', TRUE)
    ->set('is.grid', FALSE)
    ->set('is.noscript', FALSE)
    ->set('is.nav', $nav)
    ->set('item.id', 'ib')
    ->set('lazy.id', 'blazy')
    ->set('count', $count);

  $ib->set('is.text', $is_text)
    ->set('is.widget', TRUE);

  if (in_array($settings['style'], $grids)) {
    $blazies->set('is.grid', TRUE);

    // Provides sensible defaults for the ignorant who doesn't provide Grid as
    // otherwise confusingly invisible items.
    if (empty($settings['grid'])) {
      $settings['grid']        = 3;
      $settings['grid_medium'] = 2;
      $settings['grid_small']  = 1;
    }
  }

  // Pass the settings to template.
  $element_id = $blazies->get('css.element_id');
  $weight_class = $element_id . '-weight';
  $sortable = empty($settings['grid']) && $count > 1 && $multiple;

  $ib->set('is.sortable', $sortable);
  $ib->set('weight_class', $weight_class);

  // Update attributes.
  $ibend = $ib->is('uploading') ? ($count - 2) : ($count - 1);
  if ($count > 1) {
    $variables['attributes']['data-end'] = $ibend;
  }

  $ib->set('end', $ibend);

  // Defines ID if not provided.
  $variables['attributes']['id'] = $element_id;
  $variables['attributes']['data-drupal-selector'] = $element_id;
}

/**
 * Massages widget value.
 */
function _io_browser_prepare_widget_item(array &$widget, array $settings, $delta) {
  $blazies = $settings['blazies'];
  $ib = $settings['iobrowsers'];
  $target_type = $blazies->get('field.target_type');
  $attrs = &$widget['#attributes'] ?? [];

  // Self-closed elements cannot be iconized, add the wrappers.
  foreach (Defaults::widgetButtons() as $button) {
    if (isset($widget[$button])) {
      IoBrowserUtil::wrapButton($widget[$button], $button);
    }
  }

  // Delay rendering of the weight selector, so that can be rendered later.
  if (isset($widget['_weight'])) {
    if (empty($settings['grid'])) {
      hide($widget['_weight']);
    }

    $classes = [$ib->get('weight_class'), 'ib__weight'];
    $widget['_weight']['#attributes']['class'] = $classes;
    $widget['_weight']['#attributes']['data-ib-index'] = $delta;
    $widget['_weight']['#wrapper_attributes']['class'][] = 'visually-hidden';
  }

  // Arrange the row without the normal form_element wrappers.
  unset($widget['#theme'], $widget['#theme_wrappers']);

  // Makes grids draggable.
  if (!empty($settings['grid'])) {
    $attrs['class'][] = 'js-form-managed-file';
    $attrs['class'][] = 'form-managed-file';

    // If using Blazy::grid.
    if ($delta >= -1) {
      $attrs['class'][] = 'grid--' . $delta;
    }

    if ($target_type) {
      $attrs['class'][] = 'grid--' . str_replace('_', '-', $target_type);
    }
  }
}

/**
 * Prepares variables for slick-vanilla--browser.html.twig templates.
 */
function _io_browser_build_widget_item(array &$widget, array &$settings, $delta) {
  $ib = $settings['iobrowsers'];
  $group = [];

  foreach (Element::children($widget) as $child) {
    $fid = 0;
    if (in_array($child, ['upload', 'upload_button'])) {
      unset($widget[$child]);
    }
  }

  if (isset($widget['meta'])) {
    // Must not use show() to avoid dup.
    $group['meta'] = $widget['meta'];
    unset($widget['meta']);
  }

  $fid = '';
  if (isset($widget['#files'])) {
    $file = reset($widget['#files']);
    $fid = $file->id();

    if (class_exists(ByteSizeMarkup::class)) {
      $size = ByteSizeMarkup::create($file->getSize());
    }
    elseif (class_exists(DeprecationHelper::class)) {
      /* @phpstan-ignore-next-line */
      $size = DeprecationHelper::backwardsCompatibleCall(\Drupal::VERSION, '10.2.0', fn() => ByteSizeMarkup::create($file->getSize()), fn() => format_size($file->getSize()));
    }
    else {
      $size = 'N/A';
    }

    $group['meta']['file_' . $fid]['filename']['#suffix'] = '<span class="file-size"> [' . $size . ']</span> ';
  }

  $meta = [
    'fids',
    'focal_point',
    'width',
    'height',
    'alt',
    'title',
    'file_' . $fid,
    'filename',
  ];

  $label = $widget['filename'] ?? '';
  foreach ($meta as $key) {
    if ($key == 'filename') {
      unset($widget[$key]);
    }
    if (isset($widget[$key])) {
      $group['meta'][$key] = $widget[$key];
      unset($widget[$key]);
    }
  }

  if (!empty($settings['grid']) && isset($widget['_weight'])) {
    show($widget['_weight']);
    $group['action']['_weight'] = $widget['_weight'];
    unset($widget['_weight']);
  }

  foreach (Defaults::widgetButtons()
    + ['display_field'] as $key) {
    if (isset($widget[$key])) {
      $group['action'][$key] = $widget[$key];
      unset($widget[$key]);
    }
  }

  if (isset($group['meta'])) {
    $meta = $group['meta'];
    unset($group['meta']);
    $group['meta']['#theme'] = 'container';
    $group['meta']['#attributes']['class'][] = 'ib__caption';
    $group['meta']['#children'] = $meta;
  }

  if (isset($group['action'])) {
    $actions = $group['action'];
    $group['actions']['#theme'] = 'container';
    $group['actions']['#attributes']['class'] = [
      'ib__action',
      'button-group',
      'button-group--icon',
    ];
    $group['actions']['#children'] = $actions;
    unset($group['action']);
  }

  if (isset($widget['preview'])) {
    $display = $widget['preview'];
    $preview = io_browser()->toBlazy($display, $settings, $delta, $label);

    $group['preview']['#theme'] = 'container';
    $classes = &$group['preview']['#attributes'];

    $classes['class'][] = 'ib__preview';
    if ($settings['style'] == 'nativegrid') {
      $classes['class'][] = 'b-cover';
    }
    if ($ib->get('widget.plugin_id') == 'media_library_widget') {
      $classes['class'][] = 'media-library-item__preview';
      $classes['class'][] = 'js-media-library-item-preview';
    }

    $group['preview']['#children'] = $preview;
    unset($widget['preview']);
  }

  $widget['item'] = $group;
}

/**
 * Prepares buttons if any.
 */
function _io_browser_get_buttons(array $settings) {
  $blazies = $settings['blazies'];
  $ib = $settings['iobrowsers'];

  $buttons = [];
  if (isset($settings['crop_list'])) {
    $buttons['crop'] = 'Crop';
  }

  if ($blazies->get('field.cardinality') != 1) {
    if ($ib->is('text')) {
      $buttons['caption'] = 'Text';
    }

    $buttons['removeall'] = 'Remove all';
  }

  return $buttons;
}

/**
 * Builds buttons if any.
 */
function _io_browser_build_buttons(array $buttons) {
  $actions = [];
  if ($buttons) {
    foreach ($buttons as $key => $title) {
      $actions[$key . '_button'] = [
        '#type' => 'button',
        '#value' => t('@title', ['@title' => $title]),
        '#submit' => [],
        '#attributes' => [
          'class' => ['button--ib', 'button--js', 'button--' . $key],
          'data-target' => $key,
        ],
      ];
    }
  }
  return $actions;
}

/**
 * Returns a draggable item.
 */
function _io_browser_get_draggable(array &$widget, array $settings) {
  $blazies = $settings['blazies'];

  $draggable = [];
  if (isset($widget['_weight']) && empty($settings['grid'])) {
    show($widget['_weight']);
    $draggable[] = $widget['_weight'];
    unset($widget['_weight']);
  }

  $attributes = &$widget['#attributes'] ?? [];

  if (!isset($attributes['data-row-id'])) {
    $attributes['data-row-id'] = $blazies->get('delta');
  }

  return $draggable ? [
    '#markup' => io_browser()->formatter()->renderer()->render($draggable),
    '#wrapper_attributes' => $attributes,
  ] : [];
}

/**
 * Provides draggable items if any.
 */
function _io_browser_build_draggables(array &$buttons, array $draggables = []) {
  $content = [];
  if ($draggables) {
    $content = [
      '#theme' => 'item_list',
      '#items' => $draggables,
      '#wrapper_attributes' => [
        'class' => ['ib__sortlist'],
      ],
      '#attributes' => [
        'class' => ['ib__sortable', 'clearfix'],
      ],
    ];

    $buttons += [
      'sort' => 'Sort',
      'done' => 'Done',
    ];
  }
  return $content;
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc