View source
<?php
namespace Drupal\gridstack\Layout;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformStateInterface;
use Drupal\Core\Layout\LayoutDefault;
use Drupal\Core\Layout\LayoutInterface;
use Drupal\Core\Layout\LayoutDefinition;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Session\AccountInterface;
use Drupal\Component\Serialization\Json;
use Drupal\gridstack\GridStackManagerInterface;
use Drupal\gridstack\Entity\GridStack;
use Symfony\Component\DependencyInjection\ContainerInterface;
class GridStackLayout extends LayoutDefault implements ContainerFactoryPluginInterface, LayoutInterface, PluginFormInterface {
use GridStackLayoutTrait;
public function __construct(array $configuration, $plugin_id, $plugin_definition, AccountInterface $current_user, GridStackManagerInterface $manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->currentUser = $current_user;
$this->manager = $manager;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('current_user'), $container
->get('gridstack.manager'));
}
public function build(array $regions) {
$config = $this
->getConfiguration();
$definition = $this
->getPluginDefinition();
$id = $definition
->id();
$item_id = 'box';
$name = $definition
->get('optionset');
$optionset = GridStack::load($name);
$grids = $optionset
->getEndBreakpointGrids();
$ipe_exists = $this->manager
->getModuleHandler()
->moduleExists('panels_ipe');
$is_builder = $this->manager
->getModuleHandler()
->moduleExists('layout_builder');
$config['_ipe'] = $config['_layout_builder'] = FALSE;
if ($ipe_exists && $this->currentUser
->hasPermission('access panels in-place editing')) {
$config['_ipe'] = TRUE;
}
if ($is_builder && $this->currentUser
->hasPermission('configure any layout')) {
$config['_layout_builder'] = TRUE;
}
$config['extras'] = empty($config['extras']) ? [] : Json::decode($config['extras']);
$settings = [
'id' => $id,
'item_id' => $item_id,
'namespace' => 'gridstack',
'optionset' => $name,
] + $config;
$optionset
->gridsJsonToArray($settings);
$items = [];
foreach ($grids as $delta => $grid) {
$region = 'gridstack_' . $delta;
$box = [];
$box_settings = $settings;
unset($box_settings['attributes'], $box_settings['wrapper'], $box_settings['wrapper_classes']);
$box['settings'] = $box_settings;
$nested_grids = $optionset
->getNestedGridsByDelta($delta);
$is_nested = array_filter($nested_grids);
if (!empty($is_nested)) {
foreach ($nested_grids as $key => $nested_grid) {
$nested_id = $delta . '_' . $key;
$region = 'gridstack_' . $nested_id;
$box[$item_id][$key][$item_id] = isset($regions[$region]) && !Element::isEmpty($regions[$region]) ? $regions[$region] : [];
}
}
else {
$box[$item_id] = isset($regions[$region]) && !Element::isEmpty($regions[$region]) ? $regions[$region] : [];
}
$items[] = $box;
unset($box);
}
$build = [
'items' => $items,
'optionset' => $optionset,
'settings' => $settings,
'layout' => $definition,
];
return empty($items) ? [] : $this->manager
->build($build);
}
public static function layoutAlter(&$definitions) {
$manager = \Drupal::service('gridstack.manager');
$optionsets = $manager
->entityLoadMultiple('gridstack');
$framework = $manager
->configLoad('framework', 'gridstack.settings');
$path = drupal_get_path('module', 'gridstack');
foreach ($optionsets as $key => $optionset) {
if ($key == 'default') {
continue;
}
$static = !empty($framework) && $optionset
->getOption('use_framework');
$id = $optionset
->id();
$layout_id = 'gridstack_' . $id;
$regions = self::prepareRegions($optionset);
$default = isset($regions['gridstack_0']) ? 'gridstack_0' : 'gridstack_0_0';
$additional = [
'optionset' => $id,
];
$definition = [
'label' => strip_tags($optionset
->label()),
'category' => $static ? 'GridStack ' . ucwords($framework) : 'GridStack JS',
'class' => '\\Drupal\\gridstack\\Layout\\GridStackLayout',
'default_region' => $default,
'icon' => $optionset
->getIconUrl(),
'id' => $layout_id,
'provider' => 'gridstack',
'additional' => $additional,
'regions' => $regions,
'theme_hook' => 'gridstack',
'path' => $path,
'library' => 'gridstack/layout',
'config_dependencies' => [
'config' => [
'gridstack.optionset.' . $id,
],
'module' => [
'gridstack',
],
],
];
$definitions[$layout_id] = new LayoutDefinition($definition);
}
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
if ($form_state instanceof SubformStateInterface) {
$form_state = $form_state
->getCompleteFormState();
}
$access = $this->currentUser
->hasPermission('administer gridstack');
$config = $this
->getConfiguration();
$definition = $this
->getPluginDefinition();
$regions = $definition
->getRegions();
$name = $definition
->get('optionset');
$optionset = GridStack::load($name);
$regions_all = self::prepareRegions($optionset, FALSE);
$extras = [];
$entity_form = $form_state
->getFormObject();
if (method_exists($entity_form, 'getEntity') && ($display = $entity_form
->getEntity())) {
$extras = [
'bundle' => $display
->getTargetBundle(),
'entity_type' => $display
->getTargetEntityTypeId(),
'view_mode' => $display
->getMode(),
];
}
$settings = [];
foreach ([
'attributes',
'wrapper_classes',
'skin',
'wrapper',
] as $key) {
$default = $key == 'wrapper' ? 'div' : '';
$default = isset($config[$key]) ? $config[$key] : $default;
$settings[$key] = $form_state
->getValue([
'settings',
$key,
], $default);
}
$prefix = '<h3>';
if ($this->manager
->getModuleHandler()
->moduleExists('gridstack_ui') && $access) {
$prefix .= $this
->t('Outer wrapper settings [<small><a href=":url">Edit @id</a></small>]', [
':url' => $optionset
->toUrl('edit-form')
->toString(),
'@id' => strip_tags($optionset
->label()),
]);
}
else {
$prefix .= $this
->t('Outer wrapper settings');
}
$prefix .= '</h3>';
$form['settings'] = [
'#type' => 'container',
'#tree' => TRUE,
'#weight' => 20,
'#prefix' => $prefix,
];
$form['settings']['skin'] = [
'#type' => 'select',
'#title' => $this
->t('Skin'),
'#options' => $this->manager
->getSkinOptions(),
'#empty_option' => $this
->t('- None -'),
'#description' => $this
->t('Choose a skin to load for this layout. Check out, or clone, gridstack_example.module to register skins here. Leave empty to disable.'),
'#default_value' => $settings['skin'],
'#prefix' => '<div class="form-wrapper form-wrapper--inline form-wrapper--left">',
];
$form['settings']['extras'] = [
'#type' => 'hidden',
'#value' => empty($extras) ? '' : Json::encode($extras),
];
$form['settings'] += $this
->buildFormElements($settings);
$closing = '</div><div class="form-wrapper form-wrapper--inline form-wrapper--icon form-wrapper--right">';
if ($uri = $optionset
->getIconUri()) {
$image = [
'#theme' => 'image',
'#uri' => $uri,
'#alt' => $this
->t('Thumbnail'),
];
$closing .= $this->manager
->getRenderer()
->render($image);
}
$closing .= '</div>';
$form['settings']['attributes']['#suffix'] = $closing;
$form['regions'] = [
'#type' => 'container',
'#tree' => TRUE,
'#prefix' => '<p>' . $this
->t('A region has direct contents. A container contains a single, or multiple regions, grouped by their container index.') . '</p>',
];
$settings = [];
foreach ($regions_all as $region => $info) {
foreach ([
'attributes',
'wrapper_classes',
'wrapper',
] as $key) {
$default = $key == 'wrapper' ? 'div' : '';
$default = isset($config['regions'][$region][$key]) ? $config['regions'][$region][$key] : $default;
$default = $form_state
->getValue([
'regions',
$region,
$key,
], $default);
$settings['regions'][$region][$key] = $default;
}
$prefix = !array_key_exists($region, $regions) ? 'Container' : 'Region';
$form['regions'][$region] = [
'#type' => 'details',
'#title' => $this
->t('@prefix: <em>@label</em>', [
'@prefix' => $prefix,
'@label' => $info['label'],
]),
'#open' => TRUE,
'#tree' => TRUE,
'#attributes' => [
'class' => [
'form-wrapper',
],
],
];
$form['regions'][$region] += $this
->buildFormElements($settings['regions'][$region]);
}
$form['#attached']['library'][] = 'gridstack/admin_base';
return $form;
}
}