diff --git a/src/Plugin/UiPatterns/Source/BlockSource.php b/src/Plugin/UiPatterns/Source/BlockSource.php index 12aa4b8b2ba907aaedd802e1255cca24cfe9f4d7..beaaac3cda9fba4f9faf3a0e029b42b452d5fc12 100644 --- a/src/Plugin/UiPatterns/Source/BlockSource.php +++ b/src/Plugin/UiPatterns/Source/BlockSource.php @@ -31,11 +31,10 @@ use Symfony\Component\DependencyInjection\ContainerInterface; #[Source( id: 'block', label: new TranslatableMarkup('Block'), - description: new TranslatableMarkup('instantiate a block'), + description: new TranslatableMarkup('instantiate a block plugin'), prop_types: ['slot'] )] class BlockSource extends SourcePluginBase { - /** * Block to be rendered. * @@ -273,14 +272,16 @@ class BlockSource extends SourcePluginBase { protected function listBlockDefinitions() : array { $context_for_block_discovery = $this->context; $definitions = $this->blockManager->getFilteredDefinitions('ui_patterns', $context_for_block_discovery, []); + // Filter plugins based on the flag 'ui_patterns_compatibility'. + // @see function ui_patterns_plugin_filter_block__ui_patterns_alter + // from ui_patterns.module file + $definitions = array_filter($definitions, function ($definition, $plugin_id) { + return !isset($definition['_ui_patterns_compatible']) || $definition['_ui_patterns_compatible']; + }, ARRAY_FILTER_USE_BOTH); + // Filter based on contexts. $definitions = $this->contextHandler->filterPluginDefinitionsByContexts($context_for_block_discovery, $definitions); // Order by category, and then by admin label. $definitions = $this->blockManager->getSortedDefinitions($definitions); - /* - // Filter out definitions that are not intended to be placed by the UI. - $definitions = array_filter($definitions, function (array $definition) { - return empty($definition['_block_ui_hidden']); - });*/ return $definitions; } diff --git a/ui_patterns.module b/ui_patterns.module index f75c3c9f6595798069b9b3b1ef5a30253e1a3c6b..324fdc4c8727e20c5001310cb90f12dbc8c2a963 100644 --- a/ui_patterns.module +++ b/ui_patterns.module @@ -21,9 +21,18 @@ function ui_patterns_element_info_alter(array &$types) { } /** + * Prepare list of block plugins returned when using consumer 'ui_patterns'. + * + * @see \Drupal\ui_patterns\Plugin\UiPatterns\Source\BlockSource::listBlockDefinitions() + * * Implements hook_plugin_filter_TYPE__CONSUMER_alter(). */ function ui_patterns_plugin_filter_block__ui_patterns_alter(array &$definitions, array $extra) { + // @todo Determine the 'inline_block' blocks should be allowed outside + // of layout_builder https://www.drupal.org/node/2979142. + $definitions = array_filter($definitions, function ($definition) { + return $definition['id'] !== 'inline_block'; + }); // Remove blocks that are not useful within Layout Builder. unset($definitions['system_messages_block']); unset($definitions['help_block']); @@ -33,19 +42,42 @@ function ui_patterns_plugin_filter_block__ui_patterns_alter(array &$definitions, unset($definitions['system_main_block']); // @todo Restore the page title block in https://www.drupal.org/node/2938129. unset($definitions['page_title_block']); -} + // Add a boolean marker '_ui_patterns_compatible' to all remaining definitions + // Other modules can use the same hook to modify this value. + // This allows to whitelist or blacklist blocks. + $whitelisted_blocks = [ + "id" => ["search_form_block", "system_menu_block"], + "provider" => ["views"], + ]; + foreach ($definitions as $id => &$definition) { + if (isset($definitions[$id]['_ui_patterns_compatible'])) { + // When a block plugin already has 'ui_patterns_compatibilty' + // It probably means it has been marked by another code. + // Honor what the other code has done and do not override. + continue; + } + $compatibilityFlag = TRUE; + if (in_array($definition['provider'], $whitelisted_blocks["provider"]) || + in_array($definition["id"], $whitelisted_blocks["id"])) { + // Those blacks are accepted. + } + elseif (isset($definition['class'])) { + try { + $class_name = $definition['class']; + $reflector = new \ReflectionClass($class_name); + if ($reflector->hasMethod("blockSubmit") && ($reflector->getMethod("blockSubmit")->getDeclaringClass()->getName() === $class_name)) { + // Blocks having a custom implementation are discarded, + // because some blocks may store in their configuration + // a different structure than the form structure. + // We can't support this properly yet. + $compatibilityFlag = FALSE; + } + } + catch (\ReflectionException $e) { -/** - * Implements hook_plugin_filter_TYPE_alter(). - */ -function ui_patterns_plugin_filter_block_alter(array &$definitions, array $extra, $consumer) { - // @todo Determine the 'inline_block' blocks should be allowed outside - // of layout_builder https://www.drupal.org/node/2979142. - if ($consumer !== 'layout_builder' || !isset($extra['list']) || $extra['list'] !== 'inline_blocks') { - foreach ($definitions as $id => $definition) { - if ($definition['id'] === 'inline_block') { - unset($definitions[$id]); } } + // Filter out blocks with _block_ui_hidden ? + $definitions[$id]['_ui_patterns_compatible'] = $compatibilityFlag; } }