View source
<?php
namespace Drupal\ckeditor_bs_grid\Form;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Ajax\SetDialogTitleCommand;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\editor\Ajax\EditorDialogSave;
use Drupal\editor\EditorInterface;
use Drupal\editor\Entity\Editor;
use Symfony\Component\DependencyInjection\ContainerInterface;
class GridDialog extends FormBase {
protected $formBuilder;
public function __construct(FormBuilderInterface $form_builder) {
$this->formBuilder = $form_builder;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('form_builder'));
}
public function getFormId() {
return 'ckeditor_bs_grid_dialog';
}
public function buildForm(array $form, FormStateInterface $form_state, Editor $editor = NULL) {
$form['#attached']['library'][] = 'editor/drupal.editor.dialog';
$form['#attached']['library'][] = 'ckeditor_bs_grid/dialog';
$values = $form_state
->getValues();
$input = $form_state
->getUserInput();
$settings = empty($values['bs_grid_settings']) ? [] : Json::decode($values['bs_grid_settings']);
$settings += empty($input['bs_grid_settings']) ? [] : Json::decode($input['bs_grid_settings']);
if (!$form_state
->get('bs_grid_settings')) {
$form_state
->set('bs_grid_settings', isset($input['editor_object']) ? $input['editor_object'] : []);
}
$settings += $form_state
->get('bs_grid_settings');
if ($editor instanceof EditorInterface) {
$editor_settings = $editor
->getSettings();
if (isset($editor_settings['plugins']['bs_grid'])) {
$settings['editor_settings'] = $editor_settings['plugins']['bs_grid'];
}
}
$form_state
->set('bs_grid_settings', $settings);
if (!$form_state
->get('step')) {
$form_state
->set('step', 'select');
}
$form['#tree'] = TRUE;
$form['#prefix'] = '<div id="bs_grid-dialog-form">';
$form['#suffix'] = '</div>';
$form['#attributes']['class'][] = 'bs_grid-dialog-step--' . $form_state
->get('step');
if ($form_state
->get('step') == 'select') {
$form = $this
->buildSelectStep($form, $form_state);
}
elseif ($form_state
->get('step') == 'layout') {
$form = $this
->buildLayoutStep($form, $form_state);
}
elseif ($form_state
->get('step') == 'advanced') {
$form = $this
->buildAdvancedStep($form, $form_state);
}
return $form;
}
public function buildSelectStep(array $form, FormStateInterface $form_state) {
$settings = $form_state
->get('bs_grid_settings');
$form['#title'] = $this
->t("Select columns");
$columns = [];
$available_cols = array_filter($settings['editor_settings']['available_columns']);
foreach ($available_cols as $column) {
$title = $this
->t('Column @num', [
'@num' => $column,
]);
$img = drupal_get_path('module', 'ckeditor_bs_grid') . '/images/ui/col_' . $column . '.png';
$img_src = '<img src="/' . $img . '" title="' . $title . '" />';
$columns[$column] = $img_src . '<p>' . $this
->t('Column @num', [
'@num' => $column,
]) . '</p>';
}
if (!empty($settings['saved'])) {
$form['bs_grid_settings'] = [
'#type' => 'hidden',
'#value' => Json::encode($settings),
];
}
$form['num_columns'] = [
'#title' => $this
->t('Select Number of Columns'),
'#type' => 'radios',
'#options' => $columns,
'#default_value' => $settings['num_columns'] ?? 1,
'#attributes' => [
'disabled' => $settings['saved'] ?? FALSE,
],
'#prefix' => $this
->t('Read-only on existing elements.'),
];
$form['actions'] = [
'#type' => 'actions',
];
$form['actions']['next'] = [
'#type' => 'submit',
'#value' => $this
->t('Next'),
'#button_type' => 'primary',
'#submit' => [],
'#ajax' => [
'callback' => '::submitStep',
'event' => 'click',
],
'#attributes' => [
'class' => [
'js-button-next',
],
],
];
return $form;
}
public function buildLayoutStep(array $form, FormStateInterface $form_state) {
$config = $this
->config('ckeditor_bs_grid.settings');
$settings = $form_state
->get('bs_grid_settings');
$form['#title'] = $this
->t("Choose a layout");
$form['add_container'] = [
'#title' => $this
->t('Add Container'),
'#type' => 'checkbox',
'#default_value' => $settings['add_container'] ?? FALSE,
'#attributes' => [
'class' => [
'bs_grid-add-container',
],
],
];
$form['container_type'] = [
'#title' => $this
->t('Container Type'),
'#type' => 'radios',
'#options' => [
'default' => $this
->t('Default'),
'fluid' => $this
->t('Fluid'),
'wrapper' => $this
->t('Wrapper'),
],
'#default_value' => $settings['container_type'] ?? 'default',
'#states' => [
'visible' => [
'.bs_grid-add-container' => [
'checked' => TRUE,
],
],
],
];
$form['no_gutter'] = [
'#title' => $this
->t('No Gutters'),
'#type' => 'checkbox',
'#default_value' => $settings['no_gutter'] ?? FALSE,
];
$num_cols = (int) $settings['num_columns'];
$options = [
'none' => $this
->t('None (advanced)'),
];
$available_breakpoints = array_filter($settings['editor_settings']['available_breakpoints']);
foreach ($config
->get('breakpoints') as $class => $breakpoint) {
if (!isset($available_breakpoints[$class])) {
continue;
}
$prefix = $breakpoint['prefix'];
$form['breakpoints'][$prefix] = [
'#title' => $breakpoint['label'],
'#type' => 'details',
'#open' => FALSE,
];
foreach ($breakpoint['columns'][$num_cols]['layouts'] as $layout) {
$options[implode('_', $layout['settings'])] = $layout['label'];
}
$form['breakpoints'][$prefix]['layout'] = [
'#type' => 'radios',
'#options' => $options,
'#default_value' => $settings['breakpoints'][$prefix]['layout'] ?? 'none',
'#attributes' => [
'data-bs-grid-option' => TRUE,
],
];
}
$form['actions'] = [
'#type' => 'actions',
];
$form['actions']['back'] = [
'#type' => 'submit',
'#value' => $this
->t('Back'),
'#button_type' => 'primary',
'#submit' => [],
'#ajax' => [
'callback' => '::submitBackStep',
'event' => 'click',
],
'#attributes' => [
'class' => [
'js-button-back',
],
],
];
$form['actions']['save_modal'] = [
'#type' => 'submit',
'#value' => $this
->t('Save'),
'#button_type' => 'primary',
'#submit' => [],
'#ajax' => [
'callback' => '::submitDialog',
'event' => 'click',
],
'#attributes' => [
'class' => [
'js-button-next',
],
],
];
$form['actions']['advanced'] = [
'#type' => 'submit',
'#value' => $this
->t('Advanced Settings'),
'#button_type' => 'primary',
'#submit' => [],
'#ajax' => [
'callback' => '::submitStep',
'event' => 'click',
],
'#attributes' => [
'class' => [
'js-button-next',
],
],
];
return $form;
}
public function buildAdvancedStep(array $form, FormStateInterface $form_state) {
$settings = $form_state
->get('bs_grid_settings');
$form['#title'] = $this
->t("Advanced Settings");
if (!empty($settings['add_container'])) {
$form['container_wrapper_class'] = [
'#title' => $this
->t('Container Wrapper Classes'),
'#type' => 'textfield',
'#description' => $this
->t('Add classes separated by space. Ex: bg-warning py-5'),
'#default_value' => $settings['container_wrapper_class'] ?? '',
];
$form['container_class'] = [
'#title' => $this
->t('Container Classes'),
'#type' => 'textfield',
'#description' => $this
->t('Add classes separated by space. Ex: bg-warning py-5'),
'#default_value' => $settings['container_class'] ?? '',
];
}
$form['row_class'] = [
'#title' => $this
->t('Row Classes'),
'#type' => 'textfield',
'#description' => $this
->t('Add classes separated by space. Ex: bg-warning py-5'),
'#default_value' => $settings['row_class'] ?? '',
];
for ($i = 1; $i <= $settings['num_columns']; $i++) {
$form['col_' . $i . '_classes'] = [
'#title' => $this
->t('Col @num classes', [
'@num' => $i,
]),
'#type' => 'textfield',
'#default_value' => $settings['col_' . $i . '_classes'] ?? '',
'#description' => $this
->t('Add classes separated by space. Ex: bg-warning py-5'),
];
}
$form['actions'] = [
'#type' => 'actions',
];
$form['actions']['back'] = [
'#type' => 'submit',
'#value' => $this
->t('Back'),
'#button_type' => 'primary',
'#submit' => [],
'#ajax' => [
'callback' => '::submitBackStep',
'event' => 'click',
],
'#attributes' => [
'class' => [
'js-button-back',
],
],
];
$form['actions']['save_modal'] = [
'#type' => 'submit',
'#value' => $this
->t('Save'),
'#button_type' => 'primary',
'#submit' => [],
'#ajax' => [
'callback' => '::submitDialog',
'event' => 'click',
],
'#attributes' => [
'class' => [
'js-button-next',
],
],
];
return $form;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
$settings = $form_state
->get('bs_grid_settings');
if ($form_state
->get('step') == 'select') {
$values_to_save = [
'num_columns',
];
}
elseif ($form_state
->get('step') == 'layout') {
$values_to_save = [
'add_container',
'container_type',
'no_gutter',
'breakpoints',
];
}
elseif ($form_state
->get('step') == 'advanced') {
$values_to_save = [
'container_wrapper_class',
'container_class',
'row_class',
];
for ($i = 1; $i <= $settings['num_columns']; $i++) {
$key = 'col_' . $i . '_classes';
$settings[$key] = $form_state
->getValue($key, '');
}
}
foreach ($values_to_save as $save) {
$settings[$save] = $form_state
->getValue($save);
}
$form_state
->set('bs_grid_settings', $settings);
}
public function submitStep(array &$form, FormStateInterface $form_state) {
$response = new AjaxResponse();
if ($form_state
->hasAnyErrors()) {
unset($form['#prefix'], $form['#suffix']);
$form['status_messages'] = [
'#type' => 'status_messages',
'#weight' => -10,
];
$response
->addCommand(new HtmlCommand('#bs_grid-dialog-form', $form));
}
else {
$form_state
->set('step', $form_state
->get('step') === 'select' ? 'layout' : 'advanced');
$form_state
->setRebuild(TRUE);
$rebuild_form = $this->formBuilder
->rebuildForm('ckeditor_bs_grid_dialog', $form_state, $form);
unset($rebuild_form['#prefix'], $rebuild_form['#suffix']);
$response
->addCommand(new HtmlCommand('#bs_grid-dialog-form', $rebuild_form));
$response
->addCommand(new SetDialogTitleCommand('', $rebuild_form['#title']));
}
return $response;
}
public function submitBackStep(array &$form, FormStateInterface $form_state) {
$response = new AjaxResponse();
$form_state
->set('step', $form_state
->get('step') === 'advanced' ? 'layout' : 'select');
$form_state
->setRebuild(TRUE);
$rebuild_form = $this->formBuilder
->rebuildForm('ckeditor_bs_grid_dialog', $form_state, $form);
unset($rebuild_form['#prefix'], $rebuild_form['#suffix']);
$response
->addCommand(new HtmlCommand('#bs_grid-dialog-form', $rebuild_form));
$response
->addCommand(new SetDialogTitleCommand('', $rebuild_form['#title']));
return $response;
}
public function submitDialog(array &$form, FormStateInterface $form_state) {
$response = new AjaxResponse();
$settings = $form_state
->get('bs_grid_settings');
if (isset($settings['add_container'])) {
$settings['container_class'] = $settings['container_class'] ?? '';
if ($settings['container_type'] === 'default') {
$settings['container_class'] = 'container ' . $settings['container_class'];
}
else {
$settings['container_class'] = 'container-fluid ' . $settings['container_class'];
}
}
else {
$settings['container_class'] = '';
}
if (isset($settings['row_class'])) {
if (strpos($settings['row_class'], 'row') === FALSE) {
$settings['row_class'] = 'row ' . $settings['row_class'];
}
if ($settings['no_gutter'] && strpos($settings['row_class'], 'no-gutters') === FALSE) {
$settings['row_class'] = 'no-gutters ' . $settings['row_class'];
}
}
elseif ($settings['no_gutter']) {
$settings['row_class'] = 'row no-gutters';
}
else {
$settings['row_class'] = 'row';
}
for ($i = 1; $i <= $settings['num_columns']; $i++) {
$keys = [];
$col = 'col_' . $i . '_classes';
foreach ($settings['breakpoints'] as $prefix => $selection) {
if ($selection['layout'] === 'none') {
continue;
}
else {
$vals = explode('_', $selection['layout']);
$col_value = $vals[$i - 1];
if (!empty($col_value)) {
$suffix = $col_value === 'equal' ? '' : '-' . $col_value;
if ($prefix === 'none') {
$keys['col' . $suffix] = TRUE;
}
else {
$keys['col-' . $prefix . $suffix] = TRUE;
}
}
}
}
$current = implode(' ', array_keys($keys));
if (!empty($settings[$col])) {
$settings[$col] = $current . ' ' . $settings[$col];
}
else {
$settings[$col] = $current;
}
}
$settings['saved'] = TRUE;
$response
->addCommand(new EditorDialogSave($settings));
$response
->addCommand(new CloseModalDialogCommand());
return $response;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
}
}