foldershare-8.x-1.2/foldershare.theme.inc

foldershare.theme.inc
<?php
 
/**
 * @file
 * Implements theme handling for the module.
 */
 
use Drupal\Core\Render\Element;
use Drupal\Component\Utility\UrlHelper;
use Drupal\Core\Url;
 
use Drupal\Core\Datetime\Entity\DateFormat;
 
use Drupal\foldershare\Constants;
use Drupal\foldershare\Utilities\FormatUtilities;
use Drupal\foldershare\Entity\FolderShare;
 
/**
 * Implements hook_theme().
 *
 * This module defines templates:
 *
 * - 'foldershare' is used to show an entity and its contents.
 */
function foldershare_theme() {
  return [
    // Show a portion of a page showing a view of a FolderShare entity.
    'foldershare' => [
      'render element' => 'elements',
    ],
 
    // Show a page containing embedded view that lists root folder
    // FolderShare entities.
    'foldershare_view' => [
      'render element' => 'elements',
    ],
 
    // Show a table of search results listing FolderShare entities.
    // The variables defined here match those for a standard 'table',
    // even though we are using an 'item_list' template.
    'item_list__search_results__foldershare_search' => [
      'variables' => [
        // Provided by SearchController
        // ----------------------------
        // The raw list of row values generated by the search plugin.
        'items'      => [],
 
        // The context for creating the search results. The 'plugin' key
        // of the value is the ID of the search plugin used.
        'context'    => [],
 
        // The list type (ignored).
        'list_type'  => 'ol',
 
        // The text to display if the table is empty.
        'empty'      => NULL,
 
        // Added/used by table template
        // ----------------------------
        // The table title.
        'caption'    => NULL,
 
        // The table header.
        'header'     => NULL,
 
        // The table footer.
        'footer'     => NULL,
 
        // The table rows.
        'rows'       => NULL,
 
        // The column groups.
        'colgroups'  => NULL,
 
        // HTML table attributes.
        'attributes' => [],
 
        // Whether the table's header is sticky.
        'sticky'     => FALSE,
 
        // Whether the table's columns are responsive.
        'responsive' => TRUE,
      ],
    ],
  ];
}
 
/**
 * Prepares the 'foldershare' template.
 *
 * The template is used to show a file or folder on a page.
 *
 * The incoming variables are rendered from content created by
 * the folder's view controller and view builder, and derived
 * from a FolderShare entity.
 *
 * The following variables are set up for the template:
 * - 'view_mode' = the viewing mode.
 * - 'item' = the raw item.
 * - 'url' = the page's URL.
 * - 'page' = TRUE if a page is being shown.
 * - 'content' = an array of specific content values.
 *
 * The ARIA role is set to 'directory'.
 *
 * @param array $variables
 *   An input array, extended by this function, that contains a list
 *   of named variables and their values.
 */
function template_preprocess_foldershare(array &$variables) {
  //
  // Rendering adds items into the 'elements' variable array.
  //
  // Get folder or file
  // ------------------
  // Get the folder or file being processed.
  $item = $variables['elements']['#foldershare'];
 
  //
  // Expose
  // ------
  // Pull out selected values for optional access by a theme.
  $variables['view_mode'] = $variables['elements']['#view_mode'];
  $variables['item']      = $item;
  $variables['url']       = $item->toUrl(
    'canonical',
    ['language' => $item->language()])->toString();
 
  //
  // Flags
  // -----
  // Add flags for state.
  $variables['page'] = ($variables['view_mode'] === 'full');
 
  //
  // Consolidated content
  // --------------------
  // The default template adds all the content at once.
  $variables['content'] = [];
  foreach (Element::children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }
 
  // Add ARIA role.
  $variables['attributes']['role'] = 'directory';
}
 
/**
 * Prepares for the 'foldershare_view' template.
 *
 * The template is used to present a FolderShare entity.
 *
 * The incoming variables are rendered from content created by
 * the folder's view controller and view builder, and derived
 * from a FolderShare entity.
 *
 * The following variables are set up for the template:
 * - 'content' = an array of specific content values.
 *
 * The ARIA role is set to 'directory'.
 *
 * @param array $variables
 *   An input array, extended by this function, that contains a list
 *   of named variables and their values.
 */
function template_preprocess_foldershare_view(array &$variables) {
  //
  // Rendering adds items into the 'elements' variable array.
  //
  //
  // Consolidated content
  // --------------------
  // The default template adds all the content at once.
  $variables['content'] = [];
  foreach (Element::children($variables['elements']) as $key) {
    $variables['content'][$key] = $variables['elements'][$key];
  }
 
  // Add ARIA role.
  $variables['attributes']['role'] = 'directory';
}
 
/**
 * Prepares the 'item-list--search-results--foldershare-search' template.
 *
 * The template presents a table of search results.
 *
 * While the template's name is for an "item list", this implementation
 * instead creates a table. The template itself is based upon the standard
 * "table.html.twig" in Drupal core and the variables set up here are for
 * a table presentation, not a list.
 *
 * This switch from list to table is done here because:
 *
 * - We want to present search results in a table similar to the tabular view
 *   used for root folders and folder children tables.
 *
 * - The Search module's SearchController hard-codes use of an item list-based
 *   theme and provides no hooks to override it.
 *
 * - Replacing the Search module's SearchController is probably possible by
 *   replacing the route to it with one to a custom controller, but that
 *   custom controller would invoke SearchController for most of the work,
 *   and then swap out the theme name. And that would *still* leave the issue
 *   of mapping variable names from those intended for an item list to those
 *   needed for a table. We would still need this function.
 *
 * Without an override hook or replacing the SearchController, the next best
 * thing is to define our own template named the way SearchController intends
 * it to be (i.e. "item_list__search_results__*"), but swapped for a table
 * template. This preprocessor method then remaps the incoming variables
 * intended for an item list into table variables for the table template.
 *
 * The following list variables are assumed to be incoming:
 *
 * - 'items' = an array with one entry per search result. Each entry is an
 *   associative array with keys and values set by the search plugin. See
 *   this module's FolderShareSearch plugin.
 *
 * - 'empty' = a message to use if the search has no results.
 *
 * - 'list_type' = the style of list. SearchController sets this to 'ol',
 *   but this preprocessor and template ignore it.
 *
 * - 'context' = the way the search results were generated. The value is an
 *   associative array with the 'plugin' key set to the name of the search
 *   plugin used.
 *
 * The following table variables are created by this preprocessor, or by
 * the standard table preprocessor that this method invokes:
 *
 * - 'caption' = the caption for the table. This preprocessor sets this
 *   to NULL (which disables it).
 *
 * - 'colgroups' = an array of table column groups. This preprocessor sets
 *   this to an empty array (which disables it).
 *
 * - 'header' = an array of table column names. This preprocessor sets
 *   column names and responsive class names (see below).
 *
 * - 'rows' = an array of table rows. Each row is an associative array with
 *   column name keys and cell values (see below).
 *
 * - 'footer' = an array of table column values for the footer. This
 *   preprocessor sets this to an empty array (which disables it).
 *
 * - 'header_columns' = the number of table columns. This preprocessor
 *   always produces a fixed table (see below).
 *
 * - 'sticky' = a TRUE/FALSE flag indicating if the header is 'sticky' (it
 *   stays visible even when scrolling long tables). This preprocessor
 *   leaves this at its default FALSE.
 *
 * - 'no_striping' = a TRUE/FALSE flag indicating if even/odd row stripe
 *   styles should be used. This preprocessor leaves this at its default TRUE.
 *
 * The table produced always has the following columns:
 *
 * - 'Name' = the name of the file or folder, displayed as a link. For
 *   responsiveness, the column has high priority.
 *
 * - 'Modified' = the modification date of the file or folder. For
 *   responsiveness, the column has low priority.
 *
 * - 'Owner' = the owner of the file or folder, displayed as a link. For
 *   responsiveness, the column has medium priority.
 *
 * - 'Size' = the size of the file or folder, in bytes. For
 *   responsiveness, the column has low priority.
 *
 * Because search results are always specifically sorted from best to worst,
 * the table produced here does not support column sorting.
 *
 * @param array $variables
 *   An input array, extended by this function, that contains a list
 *   of named variables and their values.
 *
 * @see template_preprocess_table()
 */
function template_preprocess_item_list__search_results__foldershare_search(
  array &$variables) {
  //
  // A standard 'table' template expects the $variables array to contain:
  // - 'colgroups' = an array of column groups.
  // - 'header' = an array of header rows.
  // - 'footer' = an array of footer rows.
  // - 'rows' = an array of rows.
  // - 'no_striping' = a TRUE/FALSE to indicate row striping.
  //
  // To get the same functionality of the standard 'table' template, this
  // code invokes that template's preprocessor. But to do so, the above
  // variables must be set up first.
  //
  // No caption, column groups, or footer.
  $variables['caption']   = NULL;
  $variables['colgroups'] = NULL;
  $variables['footer']    = NULL;
 
  // Strip the incoming 'empty' text of HTML tags added by SearchController
  // under the assumption that the text would be shown by itself, rather
  // than within a table.
  if (empty($variables['empty']) === FALSE &&
      empty($variables['empty']['#markup']) === FALSE) {
    $variables['empty']['#markup'] = strip_tags($variables['empty']['#markup']);
  }
 
  // Always responsive.
  $variables['responsive'] = TRUE;
  $variables['attributes']['class'][] = 'responsive-enabled';
  $variables['#attached']['library'][] = 'core/drupal.tableresponsive';
 
  // Add views classes here and below so that the table is styled the
  // same way as a view, by default.
  $variables['attributes']['class'][] = 'views-table';
  $variables['#attached']['library'][] = 'views/views.module';
 
  // Add this module's library so that default file/folder list styling is
  // done and file MIME icons are added. The appropriate file classes are
  // also needed and added below.
  $variables['#attached']['library'][] = Constants::LIBRARY_MODULE;
 
  // Get the date-time formatter.
  $dateFormatterName = 'foldershare_date_time';
  $dateFormatter = DateFormat::load($dateFormatterName);
  if ($dateFormatter === NULL) {
    $dateFormatterName = 'short';
    $dateFormatter = DateFormat::load($dateFormatterName);
    if ($dateFormatter === NULL) {
      $dateFormatterName = '';
    }
  }
 
  $dateFormatterService = \Drupal::service('date.formatter');
 
  // Header has a fixed set of well-known columns.
  //
  // Give each column the same ID and class as if the column were generated
  // by the Views module looking at the corresponding FolderShare fields.
  // This assists theme styling so that the results table is styled the same
  // as a view table showing root folders or children of a folder.
  $variables['header'] = [
    'name'     => [
      'data'   => t('Name'),
      'id'     => ['view-name-table-column'],
      'class'  => [
        'priority-high',
        'views-align-left',
        'views-field',
        'views-field-name',
      ],
    ],
    'modified' => [
      'data'   => t('Modified'),
      'id'     => ['view-changed-table-column'],
      'class'  => [
        'priority-medium',
        'views-align-left',
        'views-field',
        'views-field-changed',
      ],
    ],
    'owner'    => [
      'data'   => t('Owner'),
      'id'     => ['view-uid-table-column'],
      'class ' => [
        'priority-medium',
        'views-align-left',
        'views-field',
        'views-field-uid',
      ],
    ],
    'size'     => [
      'data'   => t('Size'),
      'id'     => ['view-size-table-column'],
      'class'  => [
        'priority-low',
        'views-align-right',
        'views-field',
        'views-field-size',
      ],
    ],
  ];
 
  // Rows have a fixed set of well-known columns as above.
  $variables['rows'] = [];
  foreach ($variables['items'] as $item) {
    $result = $item['#result'];
    if (empty($result) === TRUE) {
      continue;
    }
 
    // Validate that the row's data is usable. If anything is missing,
    // something odd is happening and we reject presenting the row.
    if (empty($result['title']) === TRUE ||
        empty($result['user']) === TRUE ||
        empty($result['date']) === TRUE ||
        empty($result['kind']) === TRUE ||
        empty($result['mime']) === TRUE) {
      continue;
    }
 
    // Use the item's kind and MIME type to decide on classes for the
    // name link. These classes style the link to include a file/folder icon.
    $kind = $result['kind'];
    $nameClasses = ['file'];
 
    if ($kind === FolderShare::FOLDER_KIND) {
      $nameClasses[] = 'file--mime-folder-directory';
      $nameClasses[] = 'file--folder';
    }
    else {
      $mime = $result['mime'];
      $fm = strtr(
        $mime,
        [
          '/' => '-',
          '.' => '-',
        ]);
      $nameClasses[] = 'file--mime-' . $fm . ' ';
      $nameClasses[] = 'file--' . file_icon_class($mime);
    }
 
    // Process the given URLs for safety.
    //
    // The search should always have provided a 'link' URL for the item.
    // But we'll be paranoid and check.
    //
    // The search may or may not provide a user URL. If the current user
    // does not have permission to view user profiles, then there won't be
    // a URL and we need a fallback.
    //
    if (empty($result['link']) === TRUE) {
      $nameData = $result['title'];
    }
    else {
      $nameUrl = UrlHelper::stripDangerousProtocols($result['link']);
      $nameData = [
        '#type'       => 'link',
        '#title'      => $result['title'],
        '#url'        => Url::fromUri($nameUrl),
        '#attributes' => [
          'class'     => $nameClasses,
        ],
      ];
    }
 
    if (empty($result['userurl']) === TRUE) {
      $userData = $result['user'];
    }
    else {
      $userUrl = UrlHelper::stripDangerousProtocols($result['userurl']);
      $userData = [
        '#type'       => 'link',
        '#title'      => $result['user'],
        '#url'        => Url::fromUri($userUrl),
      ];
    }
 
    // Format the date.
    $langcode = '';
    if (empty($result['language']) === FALSE) {
      $langcode = $result['language'];
    }
 
    if ($dateFormatterName !== '') {
      $formattedDate = $dateFormatterService->format(
        $result['date'],
        $dateFormatterName,
        '',
        NULL,
        $langcode);
    }
    else {
      // Cannot find a known formatter. Use a custom format.
      $formattedDate = $dateFormatterService->format(
        $result['date'],
        'custom',
        'M j, Y \a\t g:i A',
        NULL,
        $langcode);
    }
 
    // Add the row. The inner '#attributes' and 'class' array gives styles for
    // links to the file/folder and user. The outer 'class' array gives
    // styles to the <td> tag for the table cell.
    $variables['rows'][] = [
      'data'              => [
        'name'            => [
          'data'          => $nameData,
          'class'         => [
            'views-field',
            'views-align-left',
            'views-field-name',
            'priority-high',
          ],
        ],
 
        'modified'        => [
          'data'          => $formattedDate,
          'class'         => [
            'views-field',
            'views-align-left',
            'views-field-changed',
            'priority-medium',
          ],
        ],
 
        'owner'           => [
          'data'          => $userData,
          'class'         => [
            'views-field',
            'views-align-left',
            'views-field-uid',
            'priority-medium',
          ],
        ],
 
        'size'            => [
          'data'          => FormatUtilities::formatBytes($result['size']),
          'class'         => [
            'views-field',
            'views-align-right',
            'views-field-size',
            'priority-low',
          ],
        ],
      ],
    ];
  }
 
  // Remove irrelevant items passed in by the SearchController, thinking it
  // was invoking an item list template. This is not critical, but it cleans
  // things up a bit.
  unset($variables['list_type']);
  unset($variables['items']);
  unset($variables['context']);
  unset($variables['wrapper_attributes']);
  unset($variables['content_attributes']);
  unset($variables['title_attributes']);
  unset($variables['title_prefix']);
  unset($variables['title_suffix']);
 
  // Add ARIA role.
  $variables['attributes']['role'] = 'directory';
 
  // Let the standard 'table' preprocessor reformat the content.
  template_preprocess_table($variables);
}

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

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