bricks-2.x-dev/bricks.module
bricks.module
<?php
use Drupal\bricks\Bricks;
use Drupal\bricks\BricksFieldItemInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
/**
* Prepares variables for `field.html.twig`.
*/
function bricks_preprocess_field(&$variables) {
$element = $variables['element'];
if (substr($element['#formatter'], 0, 7) === 'bricks_') {
$variables['items'] = [
[
'content' => Bricks::nestItems($variables['items'], $variables['element']['#items']),
],
];
}
}
/* BRICKS EDITING */
/**
* Implements hook_field_widget_info_alter().
*/
function bricks_field_widget_info_alter(array &$info) {
// Let Bricks to re-use ANY Entity Reference -compatible widgets:
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';
}
}
}
/**
* Implements hook_field_widget_WIDGET_TYPE_form_alter() for
* `entity_reference_autocomplete`.
*/
function bricks_field_widget_entity_reference_autocomplete_form_alter(&$element, FormStateInterface $form_state, $context) {
$field_type = $context['items']->getFieldDefinition()->getType();
// @TODO: Replace by 'Nested bricks' widget setting.
if (in_array($field_type, ['bricks'])) {
// @TODO: Find a better way to be used in _bricks_preprocess_tabledrag_form().
$element['#widget'] = 'entity_reference_autocomplete';
// #default_value is en Entity or NULL.
_bricks_form_element_alter($element, $context['items'][$context['delta']], $element['target_id']['#default_value']);
hide($element['depth']);
}
}
/**
* Implements hook_field_widget_WIDGET_TYPE_form_alter() for
* `bricks_tree_autocomplete`.
*/
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);
}
/**
* Prepares variables for `field-multiple-value-form.html.twig`.
*/
function bricks_preprocess_field_multiple_value_form(&$variables) {
_bricks_preprocess_tabledrag_form($variables, 'element', 'entity_reference_autocomplete', $variables['element']['#field_name'] . '-delta-order');
}
/**
* Helper function for hook_preprocess_field_multiple_value_form().
*/
function _bricks_preprocess_tabledrag_form(&$variables, $element_key, $widget, $order_class, $render_options = FALSE) {
$element = $variables[$element_key];
$operation_key = NULL;
// @TODO: Replace by 'Nested bricks' widget setting.
if (isset($element['#widget']) && $element['#widget'] == $widget ||
isset($element[0]['#widget']) && $element[0]['#widget'] == $widget) {
// @TODO: Tmp hack for the proper indent width calculation.
$variables['table']['#header'][0]['style'] = 'min-width: 150px';
$variables['table']['#header'][] = ['data' => t('Depth'), 'class' => ['bricks-depth-header']];
if ($render_options) {
// Find Operations column
$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);
// Insert new options column before operations.
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'];
// @TODO
$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)) {
// Insert data row in options column.
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',
];
// Fake option to enable indentation:
$tabledrag_options[] = [
'action' => 'match',
'relationship' => 'parent',
'group' => $order_class,
];
$variables['table']['#attached']['library'][] = 'bricks/tabledrag.relationship-all';
}
}
/**
* Helper function for widget's formElement().
*/
function _bricks_form_element_alter(&$element, $item, $entity) {
$element['depth'] = [
// @TODO: Other types break the correct indentations.
'#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)'),
],
];
$element['options']['css_id'] = [
'#type' => 'textfield',
'#default_value' => !empty($item->options['css_id']) ? $item->options['css_id'] : '',
'#size' => 10,
'#attributes' => [
'placeholder' => t('CSS ID'),
],
];
}
/* MISC */
/**
* Prepares variables for `block.html.twig` for `system_powered_by_block`.
*/
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']);
}
/**
* Implements hook_entity_presave().
*/
function bricks_entity_presave(EntityInterface $entity) {
if ($entity instanceof FieldableEntityInterface) {
foreach ($entity->getFields() as $field_item_list) {
if ($field_item_list->get(0) instanceof BricksFieldItemInterface) {
Bricks::correctDepths($field_item_list);
}
}
}
}
