diff --git a/src/BlockFieldManager.php b/src/BlockFieldManager.php index 3c50168..5cae7d7 100644 --- a/src/BlockFieldManager.php +++ b/src/BlockFieldManager.php @@ -46,4 +46,11 @@ class BlockFieldManager implements BlockFieldManagerInterface { return $block_definitions; } + /** + * {@inheritdoc} + */ + public function getBlockCategories() { + return $this->blockManager->getCategories(); + } + } diff --git a/src/BlockFieldManagerInterface.php b/src/BlockFieldManagerInterface.php index e57580f..8d20864 100644 --- a/src/BlockFieldManagerInterface.php +++ b/src/BlockFieldManagerInterface.php @@ -15,4 +15,12 @@ interface BlockFieldManagerInterface { */ public function getBlockDefinitions(); + /** + * Get list of all block categories. + * + * @return string[] + * A numerically indexed array of block categories. + */ + public function getBlockCategories(); + } diff --git a/src/Plugin/Field/FieldType/BlockFieldItem.php b/src/Plugin/Field/FieldType/BlockFieldItem.php index 4f56b52..c49de08 100644 --- a/src/Plugin/Field/FieldType/BlockFieldItem.php +++ b/src/Plugin/Field/FieldType/BlockFieldItem.php @@ -29,6 +29,8 @@ class BlockFieldItem extends FieldItemBase implements BlockFieldItemInterface { public static function defaultFieldSettings() { return [ 'plugin_ids' => [], + 'categories' => [], + 'filter' => [], ] + parent::defaultFieldSettings(); } @@ -84,6 +86,15 @@ class BlockFieldItem extends FieldItemBase implements BlockFieldItemInterface { /** @var \Drupal\block_field\BlockFieldManagerInterface $block_field_manager */ $block_field_manager = \Drupal::service('block_field.manager'); $definitions = $block_field_manager->getBlockDefinitions(); + $categories = $block_field_manager->getBlockCategories(); + + $category_options = []; + + foreach ($categories as $category) { + $category = (string) $category; + $category_options[$category] = $category; + } + foreach ($definitions as $plugin_id => $definition) { $options[$plugin_id] = [ ['category' => (string) $definition['category']], @@ -92,14 +103,31 @@ class BlockFieldItem extends FieldItemBase implements BlockFieldItemInterface { ]; } - $default_value = $field->getSetting('plugin_ids') ?: array_keys($options); + $filter_options = [ + 'plugin_ids' => $this->t('Blocks'), + 'categories' => $this->t('Categories'), + ]; + + $default_value_plugin_ids = $field->getSetting('plugin_ids') ?: array_keys($options); + $default_value_categories = $field->getSetting('categories') ?: array_keys($category_options); + $default_value_filter = $field->getSetting('filter') ?: reset($filter_options); $element = []; + + $element['filter'] = [ + '#type' => 'radios', + '#title' => $this->t('Filter'), + '#description' => $this->t('Filter blocks by...'), + '#options' => $filter_options, + '#required' => TRUE, + '#default_value' => $default_value_filter, + ]; + $element['blocks'] = [ '#type' => 'details', '#title' => $this->t('Blocks'), '#description' => $this->t('Please select available blocks.'), - '#open' => $field->getSetting('plugin_ids') ? TRUE : FALSE, + '#open' => $field->getSetting('filter') == 'plugin_ids', ]; $element['blocks']['plugin_ids'] = [ '#type' => 'tableselect', @@ -110,11 +138,28 @@ class BlockFieldItem extends FieldItemBase implements BlockFieldItemInterface { ], '#options' => $options, '#js_select' => TRUE, - '#required' => TRUE, '#empty' => t('No blocks are available.'), '#parents' => ['settings', 'plugin_ids'], '#element_validate' => [[get_called_class(), 'validatePluginIds']], - '#default_value' => array_combine($default_value, $default_value), + '#default_value' => array_combine($default_value_plugin_ids, $default_value_plugin_ids), + ]; + + $element['categories'] = [ + '#type' => 'details', + '#title' => $this->t('Categories'), + '#description' => $this->t('Please select available categories.'), + '#open' => $field->getSetting('filter') == 'categories', + ]; + $element['categories']['category_list'] = [ + '#type' => 'checkboxes', + '#header' => [ + 'Category', + ], + '#options' => $category_options, + '#js_select' => TRUE, + '#empty' => t('No categories are available.'), + '#parents' => ['settings', 'categories'], + '#default_value' => array_combine($default_value_categories, $default_value_categories), ]; return $element; } diff --git a/src/Plugin/Field/FieldWidget/BlockFieldWidget.php b/src/Plugin/Field/FieldWidget/BlockFieldWidget.php index cc5958a..1f8d053 100644 --- a/src/Plugin/Field/FieldWidget/BlockFieldWidget.php +++ b/src/Plugin/Field/FieldWidget/BlockFieldWidget.php @@ -2,7 +2,11 @@ namespace Drupal\block_field\Plugin\Field\FieldWidget; +use Drupal\block\Entity\Block; +use Drupal\block_content\Entity\BlockContent; +use Drupal\Component\Annotation\Plugin; use Drupal\Component\Utility\NestedArray; +use Drupal\Core\Entity\Entity; use Drupal\Core\Block\BlockManagerInterface; use Drupal\Core\Field\FieldItemListInterface; use Drupal\Core\Field\WidgetBase; @@ -69,6 +73,27 @@ class BlockFieldWidget extends WidgetBase implements ContainerFactoryPluginInter } /** + * Checks whether given plugin is allowed in field. + * + * @param string $plugin_id, array $definition + * + * @return bool + */ + public function pluginIsAllowed($plugin_id, $definition) { + $filter = $this->fieldDefinition->getSetting('filter'); + + if ($filter == 'plugin_ids') { + $plugin_ids = $this->fieldDefinition->getSetting('plugin_ids'); + return $plugin_ids && !isset($plugin_ids[$plugin_id]); + } + elseif ($filter == 'categories') { + $allowed_categories = $this->fieldDefinition->getSetting('categories'); + $category = (string) $definition['category']; + return $allowed_categories && isset($allowed_categories[$category]) && !$allowed_categories[$category]; + } + } + + /** * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { @@ -81,8 +106,6 @@ class BlockFieldWidget extends WidgetBase implements ContainerFactoryPluginInter [$field_name, $delta, 'settings'] )); - $plugin_ids = $this->fieldDefinition->getSetting('plugin_ids'); - $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'])) { @@ -99,7 +122,7 @@ class BlockFieldWidget extends WidgetBase implements ContainerFactoryPluginInter foreach ($definitions as $id => $definition) { // If allowed plugin ids are set then check that this block should be // included. - if ($plugin_ids && !isset($plugin_ids[$id])) { + if ($this->pluginIsAllowed($id, $definition)) { // Remove the definition, so that we have an accurate list of allowed // blocks definitions. unset($definitions[$id]); @@ -110,7 +133,7 @@ class BlockFieldWidget extends WidgetBase implements ContainerFactoryPluginInter } // Make sure the plugin id is allowed, if not clear all settings. - if ($item->plugin_id && !isset($definitions[$item->plugin_id])) { + if (isset($definitions[$item->plugin_id]) && $this->pluginIsAllowed($item->plugin_id, $definitions[$item->plugin_id])) { $item->plugin_id = ''; $item->setting = []; }