block_generation-8.x-1.x-dev/block_generation.module

block_generation.module
<?php

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\views\ViewExecutable;
/**
 * @file
 * Provides Block improvements.
 */

use Drupal\block_content\Entity\BlockContent;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Template\Attribute;

/**
 * Implements hook_ENTITY_TYPE_view_alter().
 *
 * @param array $build
 * @param \Drupal\Core\Entity\EntityInterface $entity
 * @param \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display
 */
function block_generation_block_content_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
  $block_generation_bundles = _block_generation_bundles();
  if ($entity instanceof BlockContent && array_key_exists($entity->bundle(), $block_generation_bundles)) {
    /** @var \Drupal\Core\Utility\ThemeRegistry $theme_registry */
    $theme_registry = \Drupal::service('theme.registry')->getRuntime();

    // Generalize the entity-type-specific defaults for easier default theming.
    if ($theme_registry->has('block__block_generation__' . $entity->bundle())) {
      $build['#theme'] = 'block__block_generation__' . $entity->bundle();
    }

    // Update the theme for specific fields.
    if (isset($build['title']['#object']) && $theme_registry->has('field__block_generation__title')) {
      $build['title']['#theme'] = 'field__block_generation__title';
    }
    if (isset($build['link']['#object']) && $theme_registry->has('field__block_generation__link')) {
      $build['link']['#theme'] = 'field__block_generation__link';
    }
  }
}

/**
 * Suggests block templates depending on "machine_name" field of the block.
 * Implements hook_theme_suggestions_HOOK_alter().
 *
 * @param array $suggestions
 * @param array $variables
 */
function block_generation_theme_suggestions_block_alter(array &$suggestions, array $variables) {
  if (isset($variables['elements']['content']['#block_content']) && $variables['elements']['content']['#block_content']->hasField('machine_name')) {
    $block_machine_name = $variables['elements']['content']['#block_content']->get('machine_name')->value;
    $suggestions[] = 'block__block_content__' . $block_machine_name;
  };
}

/**
 * Adds classes to content blocks.
 * Implements hook_preprocess_HOOK() for block templates.
 *
 * @param $variables
 */
function block_generation_preprocess_block(&$variables) {
  if ($variables['base_plugin_id'] == 'block_content' && $variables['content']['#block_content']->hasField('machine_name')) {
    $variables['attributes']['class'][] = 'block--' . strtr($variables['content']['#block_content']->get('machine_name')->value, '_', '-');
  }
}

/**
 * Helper function returns all block content bundles what are introduced in block_generation.
 */
function _block_generation_bundles() {
  $block_generation_bundles = &drupal_static(__FUNCTION__, []);
  if (!$block_generation_bundles) {
    $cid = 'block_generation:bundles';
    if ($cache = \Drupal::cache()->get($cid)) {
      $block_generation_bundles = $cache->data;
    }
    else {
      $block_generation_bundles = \Drupal::entityTypeManager()
        ->getStorage('block_content_type')
        ->loadMultiple();
      foreach ($block_generation_bundles as $block_generation_bundle) {
        if (strpos($block_generation_bundle->id(), 'block_generation_') === false) {
          unset($block_generation_bundles[$block_generation_bundle->id()]);
        }
      }
      \Drupal::cache()
        ->set($cid, $block_generation_bundles, Cache::PERMANENT, [
          'block_generation',
          'block_generation_bundles',
        ]);
    }
  }

  return $block_generation_bundles;
}

/**
 * Alter the theme registry to add templates for existing bundles of custom blocks.
 * Implements hook_theme_registry_alter().
 *
 * @param $theme_registry
 *
 * @see \Drupal\Core\Theme\Registry::processExtension()
 * @see hook_theme()
 */
function block_generation_theme_registry_alter(&$theme_registry) {
  $block_generation_theme_registry = &drupal_static(__FUNCTION__, []);

  if (!$block_generation_theme_registry) {
    $cid = 'block_generation:theme_registry';
    $block_generation_theme_registry = [];

    if ($cache = \Drupal::cache()->get($cid)) {
      $block_generation_theme_registry = $cache->data;
    }
    else {
      $module_handler = \Drupal::moduleHandler();
      $app_root = \Drupal::getContainer()->getParameter('app.root');

      // Make theme registry changes for every bundle of block content introduced in block_generation.
      foreach (_block_generation_bundles() as $bundle => $definition) {
        // Possible modules name what can contain templates and preprocess
        // functions for different bundle definitions of block_content.
        // So we're going through the modules from main to specific.
        $block_generation_modules = ['block_generation', $bundle];

        foreach ($block_generation_modules as $block_generation_module) {
          // Make theme registry changes if the module enabled.
          if ($module_handler->moduleExists($block_generation_module)) {

            // Possible file path of the template name containing the bundle name.
            $template_name = 'block--block-generation--' . strtr($bundle, '_', '-');
            $file_path = $app_root . '/' . \Drupal::service('extension.list.module')->getPath($block_generation_module) . '/templates/' . $template_name . '.html.twig';
            // If file exists then make registry changes.
            if (file_exists($file_path)) {
              // Add possible preprocesses, template with template path.
              $block_generation_theme_registry['block__block_generation__' . $bundle] = [
                'path' => \Drupal::service('extension.list.module')->getPath($block_generation_module) . '/templates',
                'preprocess functions' => [
                  'template_preprocess',
                  'template_preprocess_block__block_generation',
                  'template_preprocess_block__block_generation__' . $bundle,
                ],
                'render element' => 'elements',
                'template' => $template_name,
                'theme path' => \Drupal::service('extension.list.module')->getPath($block_generation_module),
                'type' => 'module',
              ];
            }

            // Make theme registry changes for every view mode of block_content.
            $view_modes = \Drupal::service('entity_display.repository')->getViewModeOptions('block_content');
            foreach ($view_modes as $view_mode_name => $view_mode_definition) {
              // Possible file path of the template name containing the bundle name and view mode name.
              $template_name = 'block--block-generation--' . strtr($bundle, '_', '-') . '--' . strtr($view_mode_name, '_', '-');
              $file_path = $app_root . '/' . \Drupal::service('extension.list.module')->getPath($block_generation_module) . '/templates/' . $template_name . '.html.twig';
              // If file exists then make registry changes.
              if (file_exists($file_path)) {
                // Add possible preprocesses, template with template path.
                $block_generation_theme_registry['block__block_generation__' . $bundle . '__' . $view_mode_name] = [
                  'path' => \Drupal::service('extension.list.module')->getPath($block_generation_module) . '/templates',
                  'preprocess functions' => [
                    'template_preprocess',
                    'template_preprocess_block__block_generation',
                    'template_preprocess_block__block_generation__' . $bundle,
                    'template_preprocess_block__block_generation__' . $bundle . '__' . $view_mode_name,
                  ],
                  'render element' => 'elements',
                  'template' => $template_name,
                  'theme path' => \Drupal::service('extension.list.module')->getPath($block_generation_module),
                  'type' => 'module',
                ];
              }
            }

            // Make theme registry changes for every field of block content.
            $fields = \Drupal::service('entity_field.manager')->getFieldStorageDefinitions('block_content');
            foreach ($fields as $fieldName => $fieldDefinition) {
              // Possible file path of the template name containing the field name.
              $template_name = 'field--block-generation--' . strtr($fieldName, '_', '-');
              $file_path = $app_root . '/' . \Drupal::service('extension.list.module')->getPath($block_generation_module) . '/templates/' . $template_name . '.html.twig';
              // If file exists then make registry changes.
              if (file_exists($file_path)) {
                // Add possible preprocesses, template with template path.
                $block_generation_theme_registry['field__block_generation__' . $fieldName] = [
                  'path' => \Drupal::service('extension.list.module')->getPath($block_generation_module) . '/templates',
                  'preprocess functions' => [
                    'template_preprocess',
                    'template_preprocess_field',
                    'template_preprocess_field__block_generation',
                    'template_preprocess_field__block_generation__' . $fieldName,
                  ],
                  'render element' => 'element',
                  'template' => $template_name,
                  'theme path' => \Drupal::service('extension.list.module')->getPath($block_generation_module),
                  'type' => 'module',
                ];
              }

              // Possible file path of the template name containing the field name.
              $template_name = 'field--block-generation--' . strtr($bundle, '_', '-') . '--' . strtr($fieldName, '_', '-');
              $file_path = $app_root . '/' . \Drupal::service('extension.list.module')->getPath($block_generation_module) . '/templates/' . $template_name . '.html.twig';
              // If file exists then make registry changes.
              if (file_exists($file_path)) {
                // Add possible preprocesses, template with template path.
                $block_generation_theme_registry['field__block_generation__' . $bundle . '__' . $fieldName] = [
                  'path' => \Drupal::service('extension.list.module')->getPath($block_generation_module) . '/templates',
                  'preprocess functions' => [
                    'template_preprocess',
                    'template_preprocess_field',
                    'template_preprocess_field__block_generation',
                    'template_preprocess_field__block_generation__' . $bundle,
                    'template_preprocess_field__block_generation__' . $bundle . '__' . $fieldName,
                  ],
                  'render element' => 'element',
                  'template' => $template_name,
                  'theme path' => \Drupal::service('extension.list.module')->getPath($block_generation_module),
                  'type' => 'module',
                ];
              }

            }

          }
        }

      }

      // Set the cache for block_generation_theme_registry.
      \Drupal::cache()
        ->set($cid, $block_generation_theme_registry, Cache::PERMANENT, [
          'block_generation',
          'block_generation_theme_registry',
        ]);
    }
  }

  $theme_registry += $block_generation_theme_registry;
}

/**
 * Process block content settings.
 * Implements hook_preprocess_HOOK().
 *
 * @param array $variables
 */
function template_preprocess_block__block_generation(array &$variables) {
  if (isset($variables['elements']['#block_content']) && $variables['elements']['#block_content'] instanceof BlockContent) {
    // Block content object.
    /** @var \Drupal\block_content\Entity\BlockContent $block */
    $block = $variables['elements']['#block_content'];

    $wrappers = [
      'wrapper_external',
      'wrapper_main',
      'wrapper_internal',
      'wrapper_inner',
    ];

    foreach ($wrappers as $wrapper) {
      _block_generation_process_wrapper($wrapper, $block, $variables);
      // _block_generation_process_effects($wrapper, $block, $variables);
    }

    if (isset($variables['settings']['wrapper_main']['attributes']) && $variables['settings']['wrapper_main']['attributes']) {
      $variables['attributes'] = $variables['settings']['wrapper_main']['attributes']->toArray() + $variables['attributes'];
    }

  }
}

/**
 * Wrap the value with a tag and set the attributes to the fields.
 * Implements hook_preprocess_HOOK().
 *
 * @param array $variables
 */
function template_preprocess_field__block_generation(array &$variables) {
  if (isset($variables['element']['#object']) && $variables['element']['#object'] instanceof BlockContent) {
    // BlockContent object.
    /** @var \Drupal\block_content\Entity\BlockContent $block */
    $block = $variables['element']['#object'];

    $wrappers = [
      'wrapper_' . $variables['field_name'],
      $variables['field_name'],
    ];
    foreach ($wrappers as $wrapper) {
      _block_generation_process_wrapper($wrapper, $block, $variables);
    }

    // Process contexts.
    $block_context = _block_generation_get_contexts($variables['element']['#object']);

    // Replaces tokens with appropriate values.
    if (is_array($variables['items']) && is_array($block_context) && $block_context) {
      foreach ($variables['items'] as &$item) {
        $item['content']['#context']['value'] = \Drupal::token()->replace($item['content']['#context']['value'], $block_context);
      }
    }
  }

}

/**
 * Prepares variables for views fields templates.
 *
 * Default template: views-view-fields.html.twig.
 *
 * @param array $variables
 *   An associative array containing:
 *   - view: The view object.
 *   - options: An array of options. Each option contains:
 *     - inline: An array that contains the fields that are to be
 *       displayed inline.
 *     - default_field_elements: If default field wrapper
 *       elements are to be provided.
 *     - hide_empty: Whether the field is to be hidden if empty.
 *     - element_default_classes: If the default classes are to be added.
 *     - separator: A string to be placed between inline fields to keep them
 *       visually distinct.
 *    - row: An array containing information about the current row.
 */
function template_preprocess_block_generation_views_view_fields(&$variables) {
  template_preprocess_views_view_fields($variables);

  $wrappers = [
    'field_wrapper_external',
    'field_wrapper_main',
    'field_wrapper_internal',
    'field_wrapper_inner',
  ];

  foreach ($wrappers as $wrapper) {
    _block_generation_process_wrapper($wrapper, $variables["row"]->_entity, $variables);
    _block_generation_process_effects($wrapper, $variables["row"]->_entity, $variables);
  }
}

/**
 * Helper function for skin processing.
 *
 * @param $skin_wrapper
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 * @param array $variables
 * @param bool $inner
 */
function _block_generation_process_skin($skin_wrapper, ContentEntityInterface $entity, array &$variables, $inner = FALSE) {
  if ($entity->hasField($skin_wrapper) && $entity->get($skin_wrapper) && $entity->get($skin_wrapper)->value) {
    $variables['settings'][$skin_wrapper]['attributes'] = new Attribute();
    $variables['settings'][$skin_wrapper]['tag'] = 'div';
    $variables['settings'][$skin_wrapper]['value'] = $entity->get($skin_wrapper)->value;
    $skin_classes = [];
    if ($inner) {
      $skin_classes[] = 'page-skin--inner';
    }
    $skin_classes[] = 'page-skin--' . $entity->get($skin_wrapper)->value;
    $variables['settings'][$skin_wrapper]['attributes']->addClass($skin_classes);

    if (isset($variables['view']) && $variables['view'] instanceof ViewExecutable && isset($variables['fields'][$skin_wrapper])) {
      unset($variables['fields'][$skin_wrapper]);
    }
  }
}

/**
 * Helper function for wrapper processing.
 *
 * @param $wrapper
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 * @param array $variables
 */
function _block_generation_process_wrapper($wrapper, ContentEntityInterface $entity, array &$variables) {
  // Define if the wrapper should be processed.
  if ($entity->hasField($wrapper) && $entity->getFieldDefinition($wrapper)->getType() == 'boolean') {
    if ($entity->get($wrapper) && $entity->get($wrapper)->value) {
      $processing = TRUE;
    }
    else {
      $processing = FALSE;
    }
  }
  elseif (
    ($entity->hasField($wrapper) && $entity->get($wrapper) && $entity->get($wrapper)->value)
    || ($entity->hasField($wrapper . '_tag') && $entity->get($wrapper . '_tag') && $entity->get($wrapper . '_tag')->value)
    || ($entity->hasField($wrapper . '_attr') && $entity->get($wrapper . '_attr') && $entity->get($wrapper . '_attr')->value)
    || ($entity->hasField($wrapper . '_effects') && $entity->get($wrapper . '_effects') && $entity->get($wrapper . '_effects')->value)
  ) {
    $processing = TRUE;
  }
  else {
    $processing = FALSE;
  }

  // Process wrapper.
  if ($processing) {
    // The tag of the wrapper.
    _block_generation_process_wrapper_tag($wrapper, $entity, $variables);
    // The attributes of the wrapper.
    _block_generation_process_attributes($wrapper, $entity, $variables);
    // The effects of the wrapper.
    _block_generation_process_effects($wrapper, $entity, $variables);
  }
}

/**
 * Helper function for wrapper's tag processing.
 *
 * @param $wrapper
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 * @param array $variables
 */
function _block_generation_process_wrapper_tag($wrapper, ContentEntityInterface $entity, array &$variables) {
  if ($entity->hasField($wrapper . '_tag')) {
    $variables['settings'][$wrapper]['tag'] = ($entity->get($wrapper . '_tag') && $entity->get($wrapper . '_tag')->value) ? $entity->get($wrapper . '_tag')->value : 'div';
  }
  else {
    $variables['settings'][$wrapper]['tag'] = 'div';
  }
}

/**
 * Helper function for attributes processing of the block.
 *
 * @param $element
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 * @param array $variables
 * @param string $destination
 */
function _block_generation_process_attributes($element, ContentEntityInterface $entity, array &$variables) {
  // Attributes for wrapper.
  if (!isset($variables['settings'][$element]['attributes']) || !$variables['settings'][$element]['attributes'] instanceof Attribute) {
    $variables['settings'][$element]['attributes'] = new Attribute();
  }

  if ($entity->hasField($element . '_attr')) {
    if ($entity->get($element . '_attr') && $entity->get($element . '_attr')->getValue()) {
      foreach ($entity->get($element . '_attr')->getValue() as $attribute_delta => $attribute) {
        $attribute_id = $attribute['first'];
        $attribute_value = $attribute['second'];
        if ($attribute_id === 'class') {
          $classes = explode(' ', $attribute_value);
          foreach ($classes as $class) {
            if (!$variables['settings'][$element]['attributes']->hasClass($class)) {
              $variables['settings'][$element]['attributes']->addClass($class);
            }
          }
        }
        elseif ($attribute_id === 'style') {
          $styles = explode(';', $attribute_value);
          foreach ($styles as $style_delta => &$style) {
            $style = trim($style);
            if ($style === '') {
              unset($styles[$style_delta]);
            }
          }
          $variables['settings'][$element]['attributes']->setAttribute('style', implode('; ', $styles) . ';');
        }
        else {
          $variables['settings'][$element]['attributes']->setAttribute($attribute_id, $attribute_value);
        }
      }
    }
  }
}

/**
 * Helper function for attributes processing of the field.
 *
 * @param $element
 * @param array $variables
 */
function _block_generation_process_field_attributes($element, array &$variables) {
  if (isset($variables['element']['#object']) && $entity = $variables['element']['#object']) {
    if ($entity->hasField($element . '_attr')) {
      if ($entity->get($element . '_attr') && $entity->get($element . '_attr')->getValue()) {
        foreach ($entity->get($element . '_attr')->getValue() as $attribute_delta => $attribute) {
          $attribute_id = $attribute['first'];
          $attribute_value = $attribute['second'];
          if ($attribute_id === 'class') {
            $classes = explode(' ', $attribute_value);
            foreach ($classes as $class) {
              foreach ($variables['items'] as &$content_item) {
                if (!isset($content_item['attributes']) || !$content_item['attributes'] instanceof Attribute) {
                  $content_item['attributes'] = new Attribute();
                }
                if (!$content_item['attributes']->hasClass($class)) {
                  $content_item['attributes']->addClass($class);
                }
              }
            }
          }
          elseif ($attribute_id === 'style') {
            $styles = explode(';', $attribute_value);
            foreach ($styles as $style_delta => &$style) {
              $style = trim($style);
              if ($style === '') {
                unset($styles[$style_delta]);
              }
            }
            foreach ($variables['items'] as &$content_item) {
              if (!isset($content_item['attributes']) || !$content_item['attributes'] instanceof Attribute) {
                $content_item['attributes'] = new Attribute();
              }
              $content_item['attributes']->setAttribute('style', implode('; ', $styles) . ';');
            }
          }
          else {
            foreach ($variables['items'] as &$content_item) {
              if (!isset($content_item['attributes']) || !$content_item['attributes'] instanceof Attribute) {
                $content_item['attributes'] = new Attribute();
              }
              $content_item['attributes']->setAttribute($attribute_id, $attribute_value);
            }
          }
        }
      }
    }
  }
}

/**
 * Helper function for effects processing.
 *
 * @param $wrapper
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 * @param array $variables
 */
function _block_generation_process_effects($wrapper, ContentEntityInterface $entity, array &$variables) {
  if ($entity->hasField($wrapper . '_effects') && $entity->get($wrapper . '_effects')->getValue()) {
    if (!isset($variables['settings'][$wrapper]['attributes'])) {
      $variables['settings'][$wrapper]['attributes'] = new Attribute();
    }
    if (!isset($variables['settings'][$wrapper]['tag'])) {
      $variables['settings'][$wrapper]['tag'] = 'div';
    }
    $effects = $entity->get($wrapper . '_effects')->getValue();
    foreach ($effects as $effect) {
      $plugin = \Drupal::service('plugin.manager.block_generation_effect')->createInstance($effect['plugin_id'], $effect['plugin_configuration']);
      $plugin->applyEffect($wrapper, $variables);
    }
  }
}

/**
 * Helper function for content processing.
 *
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 * @param array $variables
 * @param array $content_composition
 */
function _block_generation_process_content(ContentEntityInterface $entity, array &$variables, array $content_composition) {
  foreach ($content_composition as $content_item) {
    if (isset($variables['elements'][$content_item])) {
      $variables['content'][$content_item] = $variables['elements'][$content_item];
    }
  }
}

/**
 * Helper function for order processing.
 *
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 * @param array $variables
 * @param array $content_composition
 */
function _block_generation_process_order(ContentEntityInterface $entity, array &$variables, array $content_composition) {
  if ($entity->hasField('order')) {
    // Prepare ordering.
    $ordering = $entity->get('order')->getValue();
    $order = [];
    foreach ($ordering as $order_key => $order_value) {
      $order[] = $order_value['value'];
    }
    foreach (Element::children($variables['elements']) as $element_id) {
      if (!in_array($element_id, $order) && $element_id[0] != '_') {
        $order[] = $element_id;
      }
    }

    // Compose ordering in settings.
    $variables['settings']['order'] = $order;
  }
}

/**
 * Get context of the entity.
 *
 * @param \Drupal\Core\Entity\ContentEntityInterface $entity
 *
 * @return array
 */
function _block_generation_get_contexts(ContentEntityInterface $entity) {
  $contexts = $entity->__get('contexts');
  $data = [];

  if ($contexts) {
    foreach ($contexts as $context_id => $context) {
      $data[$context_id] = $context->getContextValue();
    }
  }

  return $data;
}

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

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