View source
<?php
use Drupal\bricks\BricksFieldItemInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\Component\Utility\Html;
const BRICKS_TREE_ROOT = -1;
function bricks_preprocess_field(&$variables) {
$element = $variables['element'];
if (substr($element['#formatter'], 0, 7) === 'bricks_') {
$variables['items'] = [
[
'content' => _bricks_nest_items($variables['items']),
],
];
}
}
function _bricks_nest_items($render_elements) {
$new_elements = _bricks_nested_get_new_elements($render_elements);
foreach (array_reverse(array_keys($new_elements)) as $key) {
$parent_key = $new_elements[$key]['#bricks_parent_key'];
if (!empty($new_elements[$key]['#layout']) && \Drupal::service('module_handler')
->moduleExists('layout_discovery')) {
$keep = array_intersect_key($new_elements[$key], array_flip([
'#label',
'#attributes',
'#paragraph',
]));
$new_elements[$key] = $keep + _bricks_build_layout_from_items($new_elements[$key]['#layout'], $new_elements[$key]['layout_children']);
}
if ($parent_key !== BRICKS_TREE_ROOT) {
array_unshift($new_elements[$parent_key]['layout_children'], $new_elements[$key]);
unset($new_elements[$key]);
}
}
return $new_elements;
}
function _bricks_nested_get_new_elements(array $render_elements) : array {
$parents = [
BRICKS_TREE_ROOT,
];
$previous_depth = 0;
foreach ($render_elements as $key => $render_element) {
$content = $render_element['content'] ?? [];
$field_item = _bricks_nest_get_field_item($content);
if (!$field_item) {
continue;
}
$depth = $field_item
->getDepth();
if ($depth > $previous_depth) {
array_unshift($parents, $previous_key);
}
elseif ($depth < $previous_depth) {
for ($i = 0; $i < $previous_depth - $depth; $i++) {
array_shift($parents);
}
}
$previous_depth = $depth;
$previous_key = $key;
$new_elements[$key] = _bricks_nest_get_new_element($content, $key, $field_item, $parents[0]);
}
return $new_elements ?? [];
}
function _bricks_nest_get_new_element($content, int $item_delta, BricksFieldItemInterface $field_item, $parent) : array {
$element = $content;
$entity = $field_item->entity;
$element['#label'] = $entity
->label();
$element['#bricks_parent_key'] = $parent;
$element['#attributes']['class'][] = 'brick';
$element['#attributes']['class'][] = 'brick--type--' . Html::cleanCssIdentifier($entity
->bundle());
$element['#attributes']['class'][] = 'brick--id--' . $entity
->id();
$element['layout_children'] = [];
if ($view_mode = $field_item
->getOption('view_mode')) {
$element['#view_mode'] = $view_mode;
}
if ($layout = $field_item
->getOption('layout')) {
$element['#layout'] = $layout;
}
if ($css_class = $field_item
->getOption('css_class')) {
$element['#attributes']['class'][] = $css_class;
}
return $element;
}
function _bricks_nest_get_field_item(array $content) : ?BricksFieldItemInterface {
$entity = NULL;
if ($theme = $content['#theme'] ?? '') {
$entity = $content["#{$theme}"] ?? NULL;
}
if (!$entity) {
foreach (Element::properties($content) as $property) {
if ($content[$property] instanceof EntityInterface) {
if ($entity) {
throw new \LogicException(sprintf('Unsupported render array with entity types %s %s', $entity
->getEntityTypeId(), $content[$property]
->getEntityTypeId()));
}
$entity = $content[$property];
}
}
}
return $entity ? $entity->_referringItem : NULL;
}
function _bricks_build_layout_from_items($layout, $items) {
$layoutPluginManager = \Drupal::service('plugin.manager.core.layout');
if (!$layoutPluginManager
->hasDefinition($layout)) {
\Drupal::messenger()
->addWarning(t('Layout `%layout_id` is unknown.', [
'%layout_id' => $layout,
]));
return [];
}
$layoutInstance = $layoutPluginManager
->createInstance($layout);
$regionNames = $layoutInstance
->getPluginDefinition()
->getRegionNames();
$defaultRegion = $layoutInstance
->getPluginDefinition()
->getDefaultRegion();
$use_default_region = count($regionNames) == 1 && !empty($defaultRegion);
$regions = [];
if ($use_default_region) {
$regions[$defaultRegion] = $items;
}
else {
$count = min(count($regionNames), count($items));
$regionNamesSlice = array_slice($regionNames, 0, $count);
$items = array_slice($items, 0, $count);
$regions = array_combine($regionNamesSlice, $items);
}
return $layoutInstance
->build($regions);
}
function bricks_field_widget_info_alter(array &$info) {
foreach ($info as $widget_id => &$widget_info) {
if (in_array('entity_reference', $widget_info['field_types'])) {
$widget_info['field_types'][] = 'bricks';
}
if (in_array('entity_reference_revisions', $widget_info['field_types'])) {
$widget_info['field_types'][] = 'bricks_revisioned';
}
}
}
function bricks_field_widget_entity_reference_autocomplete_form_alter(&$element, FormStateInterface $form_state, $context) {
$field_type = $context['items']
->getFieldDefinition()
->getType();
if (in_array($field_type, [
'bricks',
])) {
$element['#widget'] = 'entity_reference_autocomplete';
_bricks_form_element_alter($element, $context['items'][$context['delta']], $element['target_id']['#default_value']);
hide($element['depth']);
}
}
function bricks_field_widget_bricks_tree_autocomplete_form_alter(&$element, FormStateInterface $form_state, $context) {
bricks_field_widget_entity_reference_autocomplete_form_alter($element, $form_state, $context);
}
function bricks_field_widget_paragraphs_form_alter(&$element, FormStateInterface $form_state, $context) {
$field_type = $context['items']
->getFieldDefinition()
->getType();
if (in_array($field_type, [
'bricks_revisioned',
])) {
$element['#widget'] = 'paragraphs';
$item = $context['items'][$context['delta']];
$entity = $item->target_id ? \Drupal::entityTypeManager()
->getStorage('paragraph')
->load($item->target_id) : Paragraph::create([
'type' => $element['subform']['#process'][0][0]
->getTargetBundle(),
]);
_bricks_form_element_alter($element, $item, $entity);
hide($element['depth']);
}
}
function bricks_preprocess_field_multiple_value_form(&$variables) {
_bricks_preprocess_tabledrag_form($variables, 'element', 'entity_reference_autocomplete', $variables['element']['#field_name'] . '-delta-order');
_bricks_preprocess_tabledrag_form($variables, 'element', 'paragraphs', $variables['element']['#field_name'] . '-delta-order');
}
function _bricks_preprocess_tabledrag_form(&$variables, $element_key, $widget, $order_class, $render_options = FALSE) {
$element = $variables[$element_key];
$operation_key = NULL;
if (isset($element['#widget']) && $element['#widget'] == $widget || isset($element[0]['#widget']) && $element[0]['#widget'] == $widget) {
$variables['table']['#header'][0]['style'] = 'min-width: 150px';
$variables['table']['#header'][] = [
'data' => t('Depth'),
'class' => [
'bricks-depth-header',
],
];
if ($render_options) {
$operation_key = array_filter($variables['table']['#header'], function ($item) {
return isset($item['is_operation']);
});
if (!empty($operation_key) && is_array($operation_key)) {
$operation_key = array_keys($operation_key);
$operation_key = array_pop($operation_key);
array_splice($variables['table']['#header'], $operation_key, 0, [
[
'data' => t('Options'),
],
]);
}
}
$row = 0;
foreach (Element::children($element) as $i => $key) {
if ($key !== 'add_more' && $key !== 'header_actions') {
$depth = $element[$key]['depth']['#value'];
$indentation = [];
if ($depth > 0) {
$indentation = [
'#theme' => 'indentation',
'#size' => $depth,
];
}
$drag_cell =& $variables['table']['#rows'][$row]['data'][0];
$drag_cell['data'] = !empty($indentation) ? \Drupal::service('renderer')
->render($indentation) : '' . $drag_cell['data'];
$drag_cell['style'] = 'width: auto; min-width: 150px';
show($element[$key]['depth']);
$variables['table']['#rows'][$row]['data'][] = \Drupal::service('renderer')
->render($element[$key]['depth']);
if ($render_options && !is_null($operation_key)) {
array_splice($variables['table']['#rows'][$row]['data'], $operation_key, 0, [
[
'data' => \Drupal::service('renderer')
->render($element[$key]['options']),
'class' => 'inline-entity-form-brick-options',
],
]);
}
}
if ($key !== 'add_more') {
$row++;
}
}
$tabledrag_options =& $variables['table']['#tabledrag'];
$tabledrag_options[0]['relationship'] = 'all';
$tabledrag_options[] = [
'action' => 'depth',
'relationship' => 'group',
'group' => 'bricks-depth',
];
$tabledrag_options[] = [
'action' => 'match',
'relationship' => 'parent',
'group' => $order_class,
];
$variables['table']['#attached']['library'][] = 'bricks/tabledrag.relationship-all';
}
}
function _bricks_form_element_alter(&$element, $item, $entity) {
$element['depth'] = [
'#type' => 'hidden',
'#default_value' => !empty($item->depth) ? $item->depth : 0,
'#weight' => 10,
'#attributes' => [
'class' => [
'bricks-depth',
],
],
];
$element['options'] = [
'#type' => 'container',
'#weight' => 100,
'#attributes' => [
'class' => [
'container-inline',
],
],
];
if ($entity) {
if ($entity
->bundle() == 'layout' && \Drupal::service('module_handler')
->moduleExists('layout_discovery')) {
$element['options']['layout'] = [
'#type' => 'select',
'#options' => \Drupal::service('plugin.manager.core.layout')
->getLayoutOptions(),
'#default_value' => !empty($item->options['layout']) ? $item->options['layout'] : NULL,
];
}
if ($entity
->bundle() != 'layout') {
$element['options']['view_mode'] = [
'#type' => 'select',
'#options' => \Drupal::service('entity_display.repository')
->getViewModeOptionsByBundle($entity
->getEntityTypeId(), $entity
->bundle()),
'#default_value' => !empty($item->options['view_mode']) ? $item->options['view_mode'] : NULL,
];
}
}
$element['options']['css_class'] = [
'#type' => 'textfield',
'#default_value' => !empty($item->options['css_class']) ? $item->options['css_class'] : '',
'#size' => 10,
'#attributes' => [
'placeholder' => t('CSS class(-es)'),
],
];
}
function bricks_preprocess_block__system_powered_by_block(&$variables) {
$bricks_link = '<a href="https://uibricks.com">Bricks</a>';
$variables['content']['#markup'] = str_replace('>Drupal</a>', '>Drupal</a> & ' . $bricks_link, $variables['content']['#markup']);
}