View source
<?php
namespace Drupal\context\Reaction\Blocks\Form;
use Drupal\block\BlockRepositoryInterface;
use Drupal\block\Entity\Block;
use Drupal\context\ContextManager;
use Drupal\context\ContextReactionManager;
use Drupal\context\Form\AjaxFormTrait;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseModalDialogCommand;
use Drupal\Core\Ajax\RemoveCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\context\ContextInterface;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Component\Plugin\PluginManagerInterface;
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
use Drupal\Core\Plugin\ContextAwarePluginInterface;
use Drupal\Core\Render\Element\StatusMessages;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
abstract class BlockFormBase extends FormBase {
use AjaxFormTrait;
protected $block;
protected $context;
protected $reaction;
protected $blockManager;
protected $contextRepository;
protected $themeHandler;
protected $formBuilder;
protected $contextReactionManager;
protected $contextManager;
protected $request;
protected $moduleHandler;
public function __construct(PluginManagerInterface $block_manager, ContextRepositoryInterface $contextRepository, ThemeHandlerInterface $themeHandler, FormBuilderInterface $formBuilder, ContextReactionManager $contextReactionManager, ContextManager $contextManager, RequestStack $requestStack, ModuleHandlerInterface $moduleHandler) {
$this->blockManager = $block_manager;
$this->contextRepository = $contextRepository;
$this->themeHandler = $themeHandler;
$this->formBuilder = $formBuilder;
$this->contextReactionManager = $contextReactionManager;
$this->contextManager = $contextManager;
$this->request = $requestStack
->getCurrentRequest();
$this->moduleHandler = $moduleHandler;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('plugin.manager.block'), $container
->get('context.repository'), $container
->get('theme_handler'), $container
->get('form_builder'), $container
->get('plugin.manager.context_reaction'), $container
->get('context.manager'), $container
->get('request_stack'), $container
->get('module_handler'));
}
protected abstract function prepareBlock($block_id);
protected abstract function getSubmitValue();
public function buildForm(array $form, FormStateInterface $form_state, ContextInterface $context = NULL, $reaction_id = NULL, $block_id = NULL) {
$this->context = $context;
$this->reaction = $this->context
->getReaction($reaction_id);
$this->block = $this
->prepareBlock($block_id);
$theme = $this
->getRequest()->query
->get('theme', $this->themeHandler
->getDefault());
$form_state
->set('block_theme', $theme);
$form_state
->setTemporaryValue('gathered_contexts', $this->contextRepository
->getAvailableContexts());
$configuration = $this->block
->getConfiguration();
$form['#tree'] = TRUE;
$form['settings'] = $this->block
->buildConfigurationForm([], $form_state);
$form['settings']['id'] = [
'#type' => 'value',
'#value' => $this->block
->getPluginId(),
];
$form['custom_id'] = [
'#type' => 'machine_name',
'#maxlength' => 64,
'#description' => $this
->t('A unique name for this block instance. Must be alpha-numeric and underscore separated.'),
'#default_value' => isset($configuration['custom_id']) ? $configuration['custom_id'] : preg_replace("/\\W+/", "_", $this->block
->getPluginId()),
'#machine_name' => [
'source' => [
'settings',
'label',
],
],
'#required' => TRUE,
];
$form['region'] = [
'#type' => 'select',
'#title' => $this
->t('Region'),
'#description' => $this
->t('Select the region where this block should be displayed.'),
'#options' => $this
->getThemeRegionOptions($theme),
'#default_value' => isset($configuration['region']) ? $configuration['region'] : '',
];
$form['unique'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Unique'),
'#description' => $this
->t('Check if the block should be uniquely placed. This means that the block can not be overridden by other blocks of the same type in the selected region. Most often you want this checked if a block unintentionally contains the same content as another block on the same page.'),
'#default_value' => isset($configuration['unique']) ? $configuration['unique'] : FALSE,
];
$form['theme'] = [
'#type' => 'value',
'#value' => $theme,
];
$form['css_class'] = [
'#type' => 'textfield',
'#title' => $this
->t('Block Class'),
'#default_value' => isset($configuration['css_class']) ? $configuration['css_class'] : '',
];
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this
->getSubmitValue(),
'#button_type' => 'primary',
'#ajax' => [
'callback' => '::submitFormAjax',
],
];
if (!$this->request
->isXmlHttpRequest()) {
unset($form['actions']['submit']['#ajax']);
}
$form_state
->disableCache();
$dummy_form_id = 'block_form';
$this->moduleHandler
->alter([
'form',
'form_block_form',
], $form, $form_state, $dummy_form_id);
return $form;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
$settings = (new FormState())
->setValues($form_state
->getValue('settings'));
$this->block
->validateConfigurationForm($form['settings'], $settings);
$form_state
->setValue('settings', $settings
->getValues());
foreach ($settings
->getErrors() as $name => $error) {
$form_state
->setErrorByName($name, $error);
}
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$settings = SubformState::createForSubform($form['settings'], $form, $form_state);
$this->block
->submitConfigurationForm($form, $settings);
$form_state
->setValue('settings', $settings
->getValues());
if ($this->block instanceof ContextAwarePluginInterface) {
$this->block
->setContextMapping($form_state
->getValue([
'settings',
'context_mapping',
], []));
}
$configuration = array_merge($this->block
->getConfiguration(), [
'custom_id' => $form_state
->getValue('custom_id'),
'region' => $form_state
->getValue('region'),
'theme' => $form_state
->getValue('theme'),
'css_class' => $form_state
->getValue('css_class'),
'unique' => $form_state
->getValue('unique'),
'context_id' => $this->context
->id(),
'third_party_settings' => $form_state
->getValue('third_party_settings', []),
]);
if (!isset($configuration['uuid'])) {
$this->reaction
->addBlock($configuration);
}
else {
$this->reaction
->updateBlock($configuration['uuid'], $configuration);
}
$this->context
->save();
$form_state
->setRedirectUrl(Url::fromRoute('entity.context.edit_form', [
'context' => $this->context
->id(),
]));
}
public function submitFormAjax(array &$form, FormStateInterface $form_state) {
$response = new AjaxResponse();
if ($form_state
->getErrors()) {
$messages = StatusMessages::renderMessages(NULL);
$output[] = $messages;
$output[] = $form;
$form_class = '.' . str_replace('_', '-', $form_state
->getFormObject()
->getFormId());
$response
->addCommand(new RemoveCommand('#drupal-modal .messages--error'));
$response
->addCommand(new ReplaceCommand($form_class, $output));
}
else {
$form = $this->contextManager
->getForm($this->context, 'edit');
$response
->addCommand(new CloseModalDialogCommand());
$response
->addCommand(new ReplaceCommand('#context-reactions', $form['reactions']));
}
return $response;
}
protected function getThemeRegionOptions($theme, $show = BlockRepositoryInterface::REGIONS_ALL) {
$regions = system_region_list($theme, $show);
foreach ($regions as $region => $title) {
$regions[$region] = $title;
}
return $regions;
}
public function getEntity() {
return Block::create($this->block
->getConfiguration() + [
'plugin' => $this->block
->getPluginId(),
]);
}
}