blazy-8.x-2.x-dev/modules/blazy_layout/blazy_layout.module
modules/blazy_layout/blazy_layout.module
<?php
/**
* @file
* Provides a single layout with dynamic regions for Layout Builder.
*/
use Drupal\Core\Render\Element;
use Drupal\Core\Template\Attribute;
use Drupal\blazy_layout\BlazyLayoutDefault;
use Drupal\blazy_layout\BlazyLayoutManager;
/**
* Provides a convenient shortcut for procedural hooks.
*
* @return \Drupal\blazy_layout\BlazyLayoutManager
* The BlazyLayoutManager manager class instance.
*/
// @codingStandardsIgnoreStart
function blazy_layout(): BlazyLayoutManager {
static $manager;
if (!isset($manager)) {
$manager = \Drupal::service('blazy_layout');
}
return $manager;
}
// @codingStandardsIgnoreEnd
/**
* Implements hook_theme().
*/
function blazy_layout_theme() {
return [
'block__blazy' => [
'base hook' => 'block',
],
'field__blazy' => [
'base hook' => 'field',
],
'layout__blazy' => [
'base hook' => 'layout',
],
];
}
/**
* Overrides variables for layout.html.twig templates.
*/
function blazy_layout_preprocess_layout(array &$variables) {
$settings = &$variables['settings'];
$namespace = $variables['content']['#namespace'] ?? 'x';
if ($namespace != 'blazy') {
return;
}
$blazies = $settings['blazies'];
$wrappers = $variables['content']['#wrapper_attributes'] ?? [];
$variables['wrapper_attributes'] = new Attribute($wrappers);
$in_preview = $variables['in_preview'];
$count = $settings['count'] = (int) $settings['count'];
$settings['background'] = $background = $in_preview ||
!empty($settings['background']) ||
!empty($variables['content']['bg']);
$style = $settings['style'] ?? '';
_blazy_layout_region_attributes($variables, 'bg');
if ($theme = \Drupal::theme()->getActiveTheme()->getName()) {
$variables['attributes']['class'][] = 'b-theme-' . str_replace('_', '-', $theme);
}
if ($in_preview) {
$variables['attributes']['class'][] = 'b-layout--preview';
$variables['region_attributes']['bg']['title'] = t('Background');
$variables['region_attributes']['bg']['data-b-h'] = 'xs';
}
if ($background) {
$variables['region_attributes']['bg']['data-b-w'] = $style == 'nativegrid' ? 12 : 100;
}
// Cleanup unused regions.
_blazy_layout_cleanup_regions($variables, $count);
// Create an attributes variable for each region.
$region_settings = $settings['regions'];
if ($regions = $blazies->get('grid.items', [])) {
foreach (range(1, $count) as $delta => $value) {
$name = BlazyLayoutDefault::regionId($delta);
// Cleanup unwanted block attributes from builtin Media background.
_blazy_layout_cleanup_block_attributes($variables, $name);
// Core region attributes depend on content[region], hence enforced.
_blazy_layout_region_attributes($variables, $name);
// Add browser title tooltip over regions.
if ($in_preview && $region = $region_settings[$name] ?? []) {
$label = $region['label'] ?? '';
$variables['region_attributes'][$name]['title'] = $label;
}
// Merge attributes taken from regions generated by Grid class.
if ($region = $regions[$name] ?? []) {
if ($attrs = $region['#attributes'] ?? []) {
if (isset($variables['region_attributes'][$name])) {
$variables['region_attributes'][$name]->merge(new Attribute($attrs));
}
}
if ($cattrs = $region['#content_attributes'] ?? []) {
if (isset($variables['region_content_attributes'][$name])) {
$variables['region_content_attributes'][$name]->merge(new Attribute($cattrs));
}
}
}
}
$regions = array_diff(array_keys($settings['regions']), ['bg']);
$variables['regions'] = $regions;
}
}
/**
* Cleanup unused regions.
*/
function _blazy_layout_cleanup_regions(array &$variables, $count) {
$bg = $variables['content']['bg'] ?? [];
unset($variables['content']['bg']);
foreach (Element::children($variables['content']) as $delta => $name) {
if ($delta >= $count) {
unset($variables['content'][$name]);
}
}
$variables['content']['bg'] = $bg;
}
/**
* Cleanup unwanted block attributes from builtin Media background.
*/
function _blazy_layout_cleanup_block_attributes(array &$variables, $name) {
$contents = &$variables['content'];
if (isset($contents[$name])) {
$subcontents = &$contents[$name];
foreach ($subcontents as $uuid => &$content) {
if (strpos($uuid, '-media') !== FALSE) {
unset(
$content['#attributes']['data-layout-block-uuid'],
$content['#attributes']['data-layout-builder-highlight-id']
);
if ($classes = $content['#attributes']['class'] ?? []) {
$classes = array_diff($classes, [
'js-layout-builder-block',
'layout-builder-block',
]);
$content['#attributes']['class'] = $classes;
}
break;
}
}
}
}
/**
* Provides regions attributes.
*/
function _blazy_layout_region_attributes(array &$variables, $name) {
foreach (['attributes', 'content_attributes'] as $key) {
if (!isset($variables["region_$key"][$name])) {
if (!isset($variables['content'][$name]["#$key"])) {
$variables['content'][$name]["#$key"] = [];
}
$variables["region_$key"][$name] = new Attribute($variables['content'][$name]["#$key"]);
}
}
}
/**
* Overrides variables for block.html.twig templates.
*/
function blazy_layout_preprocess_block(array &$variables) {
if ($settings = $variables['elements']['#blazy'] ?? []) {
$variables['blazies'] = $settings['blazies']->storage();
}
}
/**
* Overrides variables for field.html.twig templates.
*/
function blazy_layout_preprocess_field(array &$variables) {
$element = &$variables['element'];
$formatter = $element['#formatter'] ?? 'null';
$blazy = strpos($formatter, 'blazy') !== FALSE;
if ($blazy || isset($element['#blazy'])
|| !empty($element['#third_party_settings']['blazy']['blazy'])) {
if ($settings = $element['#blazy'] ?? []) {
$blazies = $settings['blazies'];
// @fixme might be 0 even has one if embedded inside LB blocks.
if ($blazies->total() == 0) {
$items = $variables['items'] ?? [];
if ($items && !empty($items[0]['content'])) {
$count = count($items);
$settings['count'] = $count;
$blazies->set('count', $count)
->set('total', $count);
}
}
$variables['blazies'] = $blazies->storage();
// Make Blazy background have less divities if just a single image.
// Basically reverting to stable9 logic with minimal divities.
if ($blazies->get('count') == 1) {
$variables['multiple'] = FALSE;
if (!empty($settings['background'])) {
$variables['label_hidden'] = TRUE;
}
}
}
}
}
/**
* Implements hook_layout_alter().
*/
function blazy_layout_layout_alter(array &$definitions) {
if ($layout = $definitions['blazy_layout'] ?? NULL) {
if ($regions = $layout->getRegions()) {
$count = count($regions);
if ($count < 10) {
$max = (int) blazy()->config('max_region_count');
if ($max < 10) {
$max = 20;
}
foreach (range(9, $max) as $delta) {
$regions['blzyr_' . $delta] = [
'label' => t('Region @delta', ['@delta' => $delta]),
];
}
}
// Append the BG region into the defined regions.
$regions['bg'] = [
'label' => t('Background'),
];
$layout->setRegions($regions);
}
}
}
/**
* Implements hook_theme_suggestions_alter().
*/
function blazy_layout_theme_suggestions_alter(array &$suggestions, array $variables, $hook) {
if ($hook == 'layout') {
$settings = $variables['content']['#settings'] ?? [];
if (!empty($settings['blazy_layout'])) {
$suggestions[] = 'layout__blazy';
}
}
else {
// Make Blazy background less troublesome if just a single image.
// Basically reverting to stable9 logic with minimal divities.
$settings = [];
if ($hook == 'field') {
$settings = $variables['element']['#blazy'] ?? [];
if (!empty($settings['use_theme_field'])) {
$settings = [];
}
}
elseif ($hook == 'block') {
$settings = $variables['elements']['content'][0]['#blazy'] ?? [];
}
if ($settings) {
if (!empty($settings['use_lb'])
&& $blazies = $settings['blazies'] ?? NULL) {
if ($blazies->use('bg') || $blazies->count() == 1) {
$suggestions[] = $hook . '__blazy';
}
}
}
}
}
/**
* Implements hook_help().
*/
function blazy_layout_help($route_name) {
if ($route_name == 'help.page.blazy_layout') {
$output = file_get_contents(dirname(__FILE__) . '/README.md');
return blazy()->markdown($output);
}
return '';
}
