bootstrap_five_layouts-1.0.x-dev/modules/bootstrap_five_layouts_css_loader/bootstrap_five_layouts_css_loader.module

modules/bootstrap_five_layouts_css_loader/bootstrap_five_layouts_css_loader.module
<?php

/**
 * @file
 * Bootstrap Five Layout CSS Loader module.
 *
 * Provides automatic loading of Bootstrap 5 grid and utilities CSS.
 */

/**
 * Implements hook_help().
 */
function bootstrap_five_layouts_css_loader_help($route_name, $route_match) {
  switch ($route_name) {
    case 'help.page.bootstrap_five_layouts_css_loader':
      $output = '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Bootstrap Five Layouts CSS Loader module provides automatic loading of Bootstrap 5 grid and utilities CSS. It offers flexible loading methods and exposes Bootstrap grid classes for programmatic use.') . '</p>';

      $output .= '<h3>' . t('Features') . '</h3>';
      $output .= '<ul>';
      $output .= '<li>' . t('Automatic loading of Bootstrap 5 CSS libraries') . '</li>';
      $output .= '<li>' . t('Multiple loading methods: page attachments, preprocess_page, and preprocess_html') . '</li>';
      $output .= '<li>' . t('Access to Bootstrap grid classes via API functions') . '</li>';
      $output .= '<li>' . t('Over 300+ Bootstrap grid classes available programmatically') . '</li>';
      $output .= '</ul>';

      $output .= '<h3>' . t('Usage') . '</h3>';
      $output .= '<p>' . t('Once enabled, the module will automatically load Bootstrap 5 CSS according to your configuration. You can also use the provided API functions to access Bootstrap grid class information programmatically:') . '</p>';

      $output .= _bootstrap_five_layouts_css_loader_overview_table();

      return $output;

    default:
      return '';
  }
}


function _bootstrap_five_layouts_css_loader_overview_table() {
      $output = '<section id="classlist-helper">';

      $output .= '<h1 id="classlist-tabs-header">' . t('BS5 Layouts CSS Loader » Class List Filter') . '</h1>';

      $yaml_files = [
        'bootstrap-grid-classes',
        'bootstrap-utilities-classes',
      ];
      $yaml_data = [];
      foreach ($yaml_files as $yaml_file) {
        $yaml_data[$yaml_file] = _bootstrap_five_layouts_css_loader_read_yaml($yaml_file);
      }
      $output .= '<ul id="panel-tab">';
      foreach ($yaml_files as $yaml_file) {
        $yaml_info = $yaml_data[$yaml_file];
        if (!empty($yaml_info['data'])) {
          $output .= '<li><a href="#' . $yaml_file . '" data-panel="'.$yaml_file.'-panel">' . $yaml_info['metadata']['title'] . ' <small>(<span class="count">'.$yaml_info['metadata']['total_classes'] . '</span>)</small></a></li>';
        }
      }
      $output .= '</ul>';

      foreach ($yaml_files as $yaml_file) {
        $yaml_info = $yaml_data[$yaml_file];

        // Only display if we have data
        if (!empty($yaml_info['data'])) {
          $output .= '<div id="'.$yaml_file.'-panel" class="panel"><h2 id="'.$yaml_file.'">' . $yaml_info['metadata']['title'] . '</h2>';
          $output .= '<table class="table">';

          $output .= '<thead><tr>';
          foreach ($yaml_info['headers'] as $header) {
            $output .= '<th>' . $header . '</th>';
          }
          $output .= '</tr></thead>';

          $output .= '<tbody>';
          foreach ($yaml_info['data'] as $class_info) {
            $output .= '<tr>';
            foreach ($class_info as $col=>$content) {
              $output .= '<td>' . $content. '</td>';
            }
            $output .= '</tr>';
          }
          $output .= '</tbody>';

          $output .= '</table>';
          $output .= '<a href="#classlist-tabs-header">' . t('Back to top of Class Lists') . '</a>';
          $output .= '</div>';
        }
      }
      $output .= '</section>';
  return $output;
}

/**
 * Gets the configured Bootstrap library to load.
 *
 * @return string|null
 *   The library name to load, or NULL if disabled.
 */
function _bootstrap_five_layouts_css_loader_get_library() {
  return 'bootstrap_five_layouts_css_loader/toolkit';
}

/**
 * Gets the configured loading method.
 *
 * @return string
 *   The loading method.
 */
function _bootstrap_five_layouts_css_loader_get_method() {
  $config = \Drupal::config('bootstrap_five_layouts_css_loader.settings');
  return $config->get('load_method') ?: 'page_attachments';
}

/**
 * Implements hook_preprocess_page().
 *
 * Attaches Bootstrap 5 CSS libraries to all pages when configured to do so.
 */
function bootstrap_five_layouts_css_loader_preprocess_page(&$variables) {
  $method = _bootstrap_five_layouts_css_loader_get_method();
  $library = _bootstrap_five_layouts_css_loader_get_library();

  if ($method === 'preprocess_page' && $library) {
    $variables['#attached']['library'][] = $library;
  }
}

/**
 * Implements hook_preprocess_html().
 *
 * Ensures Bootstrap CSS is loaded early in the HTML head when configured to do so.
 */
function bootstrap_five_layouts_css_loader_preprocess_html(&$variables) {
  $method = _bootstrap_five_layouts_css_loader_get_method();
  $library = _bootstrap_five_layouts_css_loader_get_library();

  if ($method === 'preprocess_html' && $library) {
    $variables['#attached']['library'][] = $library;
  }
}

/**
 * Implements hook_page_attachments().
 *
 * Default method to attach libraries globally.
 */
function bootstrap_five_layouts_css_loader_page_attachments(array &$attachments) {
  $method = _bootstrap_five_layouts_css_loader_get_method();
  $library = _bootstrap_five_layouts_css_loader_get_library();

  if ($method === 'page_attachments' && $library) {
    $attachments['#attached']['library'][] = $library;
  }

  // Attach class-helper library only on the help page
  $route_match = \Drupal::routeMatch();

  if ($route_match->getParameters()->get('name') === 'bootstrap_five_layouts_css_loader') {
    $attachments['#attached']['library'][] = 'bootstrap_five_layouts_css_loader/class-helper';
  }
}

/**
 * Reads and parses the Bootstrap YAML files using Drupal's Config system.
 *
 * @param string $file
 *   The YAML file name (without extension).
 *
 * @return array
 *   An array with 'data', 'title', 'headers', and 'metadata' keys.
 */
function _bootstrap_five_layouts_css_loader_read_yaml($file = 'bootstrap-grid-classes') {
  static $cached_files = [];

  if (!isset($cached_files[$file])) {
    $cached_files[$file] = ['data' => [], 'title' => '', 'headers' => [], 'metadata' => []];

    // Use Drupal's Config system to load the YAML file
    $config = \Drupal::config("bootstrap_five_layouts_css_loader.$file");
    // Check if config has data
    if ($config instanceof \Drupal\Core\Config\ImmutableConfig && $config->get()) {
      // Extract metadata if available
      $metadata = $config->get('metadata');
      if ($metadata) {
        $cached_files[$file]['metadata'] = $metadata;
        // Get title from metadata, fallback to generated title
        $cached_files[$file]['title'] = $metadata['title'];
      }

      // Process the data structure based on file type
      if ($file === 'bootstrap-grid-classes') {
        $processed = _bootstrap_five_layouts_css_loader_process_grid_yaml($config);
        $cached_files[$file]['data'] = $processed['data'];
        $cached_files[$file]['headers'] = $processed['headers'];
      } else {
        $processed = _bootstrap_five_layouts_css_loader_process_utilities_yaml($config);
        $cached_files[$file]['data'] = $processed['data'];
        $cached_files[$file]['headers'] = $processed['headers'];
      }
    }
  }

  return $cached_files[$file];
}

/**
 * Processes a section of grid YAML data into a flat array for display.
 *
 * @param array $section_data
 *   The section data to process.
 * @param array &$classes
 *   Reference to the classes array to populate.
 * @param string $default_breakpoint
 *   The default breakpoint to use.
 */
function _bootstrap_five_layouts_css_loader_process_grid_section($section_data, &$classes, $default_breakpoint = 'XS/All') {
  if (!$section_data) {
    return;
  }

  // Check if this is a direct array (like containers, rows)
  if (isset($section_data[0]) && isset($section_data[0]['class_name'])) {
    // Direct array structure: [...]
    foreach ($section_data as $item) {
      if (isset($item['class_name'])) {
        $classes[] = [
          'class_name' => $item['class_name'],
          'category' => $item['category'],
          'breakpoint' => isset($item['breakpoint']) ? $item['breakpoint'] : $default_breakpoint,
          'description' => $item['description'],
          'width_spacing' => $item['width'],
        ];
      }
    }
  } else {
    // Object structure: {breakpoint: [...]} or {breakpoint: {breakpoint: "name", classes: [...]}}
    foreach ($section_data as $breakpoint => $items) {
      if (is_array($items)) {
        $items_to_process = [];
        $breakpoint_name = $default_breakpoint;

        if (isset($items['classes']) && is_array($items['classes'])) {
          // Structure: {breakpoint: {breakpoint: "name", classes: [...]}}
          $items_to_process = $items['classes'];
          $breakpoint_name = isset($items['breakpoint']) ? $items['breakpoint'] : $default_breakpoint;
        } else {
          // Structure: {breakpoint: [...]} - direct array
          $items_to_process = $items;
          $breakpoint_name = $default_breakpoint;
        }

        foreach ($items_to_process as $item) {
          if (isset($item['class_name'])) {
            $classes[] = [
              'class_name' => $item['class_name'],
              'category' => $item['category'],
              'breakpoint' => isset($item['breakpoint']) ? $item['breakpoint'] : $breakpoint_name,
              'description' => $item['description'],
              'width_spacing' => $item['width'],
            ];
          }
        }
      }
    }
  }
}

/**
 * Processes grid YAML data into a flat array for display.
 *
 * @param \Drupal\Core\Config\Config $config
 *   The config object containing the YAML data.
 *
 * @return array
 *   An array with 'data' and 'headers' keys.
 */
function _bootstrap_five_layouts_css_loader_process_grid_yaml($config) {
  $classes = [];
  $headers = [t('Class Name'), t('Category'), t('Breakpoint'), t('Description'), t('Width/Spacing')];

  // Process containers
  $containers = $config->get('bootstrap_grid_classes.containers');
  _bootstrap_five_layouts_css_loader_process_grid_section($containers, $classes);

  // Process rows
  $rows = $config->get('bootstrap_grid_classes.rows');
  _bootstrap_five_layouts_css_loader_process_grid_section($rows, $classes);

  // Process columns
  $columns = $config->get('bootstrap_grid_classes.columns');
  _bootstrap_five_layouts_css_loader_process_grid_section($columns, $classes);

  // Process row columns
  $row_columns = $config->get('bootstrap_grid_classes.row_columns');
  _bootstrap_five_layouts_css_loader_process_grid_section($row_columns, $classes);

  // Process offsets
  $offsets = $config->get('bootstrap_grid_classes.offsets');
  _bootstrap_five_layouts_css_loader_process_grid_section($offsets, $classes);

  // Process gutters
  $gutters = $config->get('bootstrap_grid_classes.gutters');
  _bootstrap_five_layouts_css_loader_process_grid_section($gutters, $classes);

  // Process responsive variants
  $responsive_variants = $config->get('bootstrap_grid_classes.responsive_variants');
  if ($responsive_variants) {
    foreach ($responsive_variants as $variant_name => $variant_data) {
      if (isset($variant_data['classes']) && is_array($variant_data['classes'])) {
        _bootstrap_five_layouts_css_loader_process_grid_section($variant_data['classes'], $classes, $variant_data['breakpoint']);
      }
    }
  }

  return ['data' => $classes, 'headers' => $headers];
}

/**
 * Processes utilities YAML data into a flat array for display.
 *
 * @param \Drupal\Core\Config\Config $config
 *   The config object containing the YAML data.
 *
 * @return array
 *   An array with 'data' and 'headers' keys.
 */
function _bootstrap_five_layouts_css_loader_process_utilities_yaml($config) {
  $classes = [];
  $headers = [t('Class Name'), t('Category'), t('Breakpoint'), t('Description')];

  $utilities_classes = $config->get('bootstrap_utilities_classes');
  if ($utilities_classes) {
    foreach ($utilities_classes as $category => $breakpoints) {
      foreach ($breakpoints as $breakpoint => $class_list) {
        if (is_array($class_list)) {
          foreach ($class_list as $class_data) {
            // Handle both old string format and new object format
            if (is_string($class_data)) {
              // Fallback for old string format - use generic description
              $classes[] = [
                'class_name' => $class_data,
                'category' => ucfirst($category),
                'breakpoint' => _bootstrap_five_layouts_css_loader_map_breakpoint($breakpoint),
                'description' => 'Utility class',
              ];
            } else {
              $classes[] = [
                'class_name' => $class_data['class_name'],
                'category' => ucfirst($category),
                'breakpoint' => _bootstrap_five_layouts_css_loader_map_breakpoint($breakpoint),
                'description' => $class_data['description'],
              ];
            }
          }
        }
      }
    }
  }

  return ['data' => $classes, 'headers' => $headers];
}

/**
 * Maps YAML breakpoint keys to display names.
 *
 * @param string $breakpoint
 *   The breakpoint key from YAML.
 *
 * @return string
 *   The display name for the breakpoint.
 */
function _bootstrap_five_layouts_css_loader_map_breakpoint($breakpoint) {
  $breakpoint_map = [
    'xs' => 'XS',
    'sm' => 'SM (≥576px)',
    'md' => 'MD (≥768px)',
    'lg' => 'LG (≥992px)',
    'xl' => 'XL (≥1200px)',
    'xxl' => 'XXL (≥1400px)',
    'print' => t('Print'),
  ];

  return $breakpoint_map[$breakpoint] ?? ucfirst($breakpoint);
}

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

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