View source
<?php
namespace Drupal\block_field\Plugin\Field\FieldWidget;
use Drupal\block_field\BlockFieldSelectionManager;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Block\BlockManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Plugin\ContextAwarePluginInterface;
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class BlockFieldWidget extends WidgetBase implements ContainerFactoryPluginInterface {
protected $contextRepository;
protected $blockManager;
protected $blockFieldSelectionManager;
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, BlockManagerInterface $block_manager, BlockFieldSelectionManager $block_field_selection_manager, ContextRepositoryInterface $contextRepository) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->blockManager = $block_manager;
$this->blockFieldSelectionManager = $block_field_selection_manager;
$this->contextRepository = $contextRepository;
$this->blockManager = $block_manager;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container
->get('plugin.manager.block'), $container
->get('plugin.manager.block_field_selection'), $container
->get('context.repository'));
}
public static function defaultSettings() {
return [
'plugin_id' => '',
'settings' => [],
'configuration_form' => 'full',
] + parent::defaultSettings();
}
public function settingsForm(array $form, FormStateInterface $form_state) {
$elements['configuration_form'] = [
'#type' => 'select',
'#title' => $this
->t('Configuration form'),
'#description' => $this
->t('How the block configuration form will be shown.'),
'#options' => [
'full' => $this
->t('Full'),
'hidden' => $this
->t('Hidden'),
],
'#default_value' => $this
->getSetting('configuration_form'),
'#required' => TRUE,
];
return $elements;
}
public function settingsSummary() {
$summary[] = $this
->t('Configuration form: @configuration_form', [
'@configuration_form' => $this
->getSetting('configuration_form'),
]);
return $summary;
}
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$item =& $items[$delta];
$field_name = $this->fieldDefinition
->getName();
$settings_id = implode('-', array_merge($element['#field_parents'], [
$field_name,
$delta,
'settings',
]));
$values = $form_state
->getValues();
$item->plugin_id = isset($values[$field_name][$delta]['plugin_id']) ? $values[$field_name][$delta]['plugin_id'] : $item->plugin_id;
if (!empty($values[$field_name][$delta]['settings'])) {
$item->settings = $values[$field_name][$delta]['settings'];
}
else {
$item->settings = $item->settings ?: [];
}
$options = $this->blockFieldSelectionManager
->getWidgetOptions($this->fieldDefinition);
if ($item->plugin_id) {
if (!in_array($item->plugin_id, array_keys(call_user_func_array('array_merge', array_values($options))), TRUE)) {
$item->plugin_id = '';
$item->setting = [];
}
}
$element['plugin_id'] = [
'#type' => 'select',
'#title' => $this
->t('Block'),
'#options' => $options,
'#empty_option' => $this
->t('- None -'),
'#default_value' => $item->plugin_id,
'#required' => $element['#required'],
];
if ($this
->getSetting('configuration_form') === 'full') {
$element['plugin_id']['#ajax'] = [
'callback' => [
$this,
'configurationForm',
],
'wrapper' => $settings_id,
];
$element['settings'] = [
'#type' => 'container',
'#attributes' => [
'id' => $settings_id,
],
'#tree' => TRUE,
];
if ($block_instance = $item
->getBlock()) {
$form_state
->setTemporaryValue('gathered_contexts', $this->contextRepository
->getAvailableContexts());
$element['settings'] += $block_instance
->buildConfigurationForm([], $form_state);
if (isset($element['settings']['admin_label'])) {
$element['settings']['admin_label']['#access'] = FALSE;
}
$element['#element_validate'] = [
[
$this,
'validate',
],
];
}
}
return $element;
}
protected function formSingleElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = parent::formSingleElement($items, $delta, $element, $form, $form_state);
$element['plugin_id']['#title'] = $element['#title'];
$element['plugin_id']['#title_display'] = $element['#title_display'];
$element['plugin_id']['#description'] = $element['#description'];
return $element;
}
public function configurationForm(array $form, FormStateInterface $form_state) {
$trigger_element = $form_state
->getTriggeringElement();
$array_parents = $trigger_element['#array_parents'];
$array_parents[count($array_parents) - 1] = 'settings';
$settings_element = NestedArray::getValue($form, $array_parents);
$plugin_id = $trigger_element['#value'];
if ($block_instance = $this->blockManager
->createInstance($plugin_id)) {
$settings_element['label']['#value'] = $block_instance
->label();
}
return $settings_element;
}
public static function validate($element, FormStateInterface $form_state, $form) {
$block_manager = \Drupal::service('plugin.manager.block');
$values = $form_state
->getValues();
$plugin_id = NestedArray::getValue($values, $element['plugin_id']['#parents']);
if (!empty($plugin_id) && $block_manager
->hasDefinition($plugin_id)) {
$settings = NestedArray::getValue($values, $element['settings']['#parents']);
if ($settings['label_display'] === 0) {
$settings['label_display'] = FALSE;
}
$block_instance = $block_manager
->createInstance($plugin_id, $settings);
$settings = (new FormState())
->setValues($settings);
$block_instance
->validateConfigurationForm($element['settings'], $settings);
foreach ($settings
->getErrors() as $key => $error) {
$parents = implode('][', $element['settings']['#parents']);
if (strpos($key, $parents) === FALSE) {
$key = sprintf('%s][%s', $parents, $key);
}
$form_state
->setErrorByName($key, $error);
}
NestedArray::setValue($values, $element['settings']['#parents'], $settings
->getValues());
$form_state
->setValues($values);
}
else {
NestedArray::setValue($values, $element['settings']['#parents'], []);
}
}
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
$field_name = $this->fieldDefinition
->getName();
$form_state = clone $form_state;
foreach ($values as &$value) {
if (!empty($value['plugin_id']) && !empty($value['settings']) && ($block = $this->blockManager
->createInstance($value['plugin_id']))) {
$elements =& $form[$field_name]['widget'][$value['_original_delta']]['settings'];
$subform_state = SubformState::createForSubform($elements, $form_state
->getCompleteForm(), $form_state);
$block
->submitConfigurationForm($elements, $subform_state);
if ($block instanceof ContextAwarePluginInterface && $block
->getContextDefinitions()) {
$context_mapping = $subform_state
->getValue('context_mapping', []);
$block
->setContextMapping($context_mapping);
}
$value['settings'] = $block
->getConfiguration();
}
}
return $values;
}
}