Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
ui_patterns
Manage
Activity
Members
Labels
Plan
Wiki
Custom issue tracker
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Model registry
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Terms and privacy
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
project
ui_patterns
Commits
8436ee8d
Commit
8436ee8d
authored
10 months ago
by
Mikael Meulle
Browse files
Options
Downloads
Patches
Plain Diff
better filter methodology
parent
4052117e
No related branches found
No related tags found
1 merge request
!147
Disallow some blocks
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/Plugin/UiPatterns/Source/BlockSource.php
+9
-63
9 additions, 63 deletions
src/Plugin/UiPatterns/Source/BlockSource.php
ui_patterns.module
+43
-11
43 additions, 11 deletions
ui_patterns.module
with
52 additions
and
74 deletions
src/Plugin/UiPatterns/Source/BlockSource.php
+
9
−
63
View file @
8436ee8d
...
...
@@ -9,7 +9,6 @@ use Drupal\Component\Utility\Html;
use
Drupal\Component\Utility\NestedArray
;
use
Drupal\Core\Block\BlockManagerInterface
;
use
Drupal\Core\Block\BlockPluginInterface
;
use
Drupal\Core\Cache\CacheBackendInterface
;
use
Drupal\Core\Entity\EntityDisplayBase
;
use
Drupal\Core\Form\FormStateInterface
;
use
Drupal\Core\Form\SubformState
;
...
...
@@ -32,13 +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
{
const
CACHE_KEY
=
'ui_patterns_block_metadata'
;
/**
* Block to be rendered.
*
...
...
@@ -60,7 +56,6 @@ class BlockSource extends SourcePluginBase {
protected
BlockManagerInterface
$blockManager
,
protected
PluginFormFactoryInterface
$pluginFormFactory
,
protected
ContextHandlerInterface
$contextHandler
,
protected
CacheBackendInterface
$cacheBackend
,
)
{
parent
::
__construct
(
$configuration
,
$plugin_id
,
$plugin_definition
,
$propTypeManager
,
$contextRepository
,
$routeMatch
,
$sampleEntityGenerator
);
}
...
...
@@ -84,8 +79,7 @@ class BlockSource extends SourcePluginBase {
$container
->
get
(
'ui_patterns.sample_entity_generator'
),
$container
->
get
(
'plugin.manager.block'
),
$container
->
get
(
'plugin_form.factory'
),
$container
->
get
(
'context.handler'
),
$container
->
get
(
'cache.default'
),
$container
->
get
(
'context.handler'
)
);
return
$instance
;
}
...
...
@@ -278,67 +272,19 @@ 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
);
// ---
$metadataAboutBlocks
=
[];
$cached_version
=
$this
->
cacheBackend
->
get
(
static
::
CACHE_KEY
);
if
(
$cached_version
)
{
$metadataAboutBlocks
=
$cached_version
->
data
;
}
// @todo Add a way to alter this list properly (hook, event, etc).
$whitelisted_blocks
=
[
"id"
=>
[
"search_form_block"
,
"system_menu_block"
],
"provider"
=>
[
"layout_builder"
,
"views"
],
];
foreach
(
$definitions
as
$plugin_id
=>
$definition
)
{
if
(
!
isset
(
$metadataAboutBlocks
[
$plugin_id
]))
{
$blockAccepted
=
TRUE
;
if
(
in_array
(
$definition
[
'provider'
],
$whitelisted_blocks
[
"provider"
])
||
in_array
(
$definition
[
"id"
],
$whitelisted_blocks
[
"id"
]))
{
$blockAccepted
=
TRUE
;
}
elseif
(
isset
(
$definition
[
'class'
])
&&
static
::
classImplementsMethod
(
$definition
[
'class'
],
'blockSubmit'
))
{
$blockAccepted
=
FALSE
;
}
$metadataAboutBlocks
[
$plugin_id
]
=
$blockAccepted
;
}
}
$definitions
=
array_filter
(
$definitions
,
function
(
$plugin_id
)
use
(
$metadataAboutBlocks
)
{
return
$metadataAboutBlocks
[
$plugin_id
];
},
ARRAY_FILTER_USE_KEY
);
$this
->
cacheBackend
->
set
(
static
::
CACHE_KEY
,
$metadataAboutBlocks
,
CacheBackendInterface
::
CACHE_PERMANENT
);
// 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
;
}
/**
* Checks if a class implements a method.
*
* @param string $class_name
* The fully qualified class name.
* @param string $method_name
* Method name to check.
*
* @return bool
* TRUE if the class implements the method, FALSE otherwise.
*/
protected
static
function
classImplementsMethod
(
string
$class_name
,
string
$method_name
)
:
bool
{
try
{
$reflector
=
new
\ReflectionClass
(
$class_name
);
return
(
$reflector
->
hasMethod
(
$method_name
)
&&
$reflector
->
getMethod
(
$method_name
)
->
getDeclaringClass
()
->
getName
()
===
$class_name
);
}
catch
(
\ReflectionException
$e
)
{
// Handle exception if class does not exist or method not found.
}
return
TRUE
;
}
/**
* Get options for block select.
*/
...
...
This diff is collapsed.
Click to expand it.
ui_patterns.module
+
43
−
11
View file @
8436ee8d
...
...
@@ -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
;
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment