Last active
October 21, 2024 09:38
-
-
Save anotherjames/bcb7ba55ec56359240b26d322fe2f5a5 to your computer and use it in GitHub Desktop.
Config form from schema
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
block.settings.mymodule_my_schema_form_block: | |
type: block_settings | |
label: 'MySchemaFormBlock block settings' | |
mapping: | |
svcid: | |
type: string | |
label: 'Service ID' | |
constraints: | |
Regex: | |
pattern: '/^[a-zA-Z0-9_\-]+$/' | |
message: "The Service ID can only contain simple letters, numbers, underscores or hyphens." | |
# The following two properties are custom. | |
default: 'abcde' | |
locked: true | |
envid: | |
type: string | |
label: 'Environment ID' | |
constraints: | |
Regex: | |
pattern: '/^[a-zA-Z0-9_\-]+$/' | |
message: "The Environment ID can only contain simple letters, numbers, underscores or hyphens." | |
# This is a custom property. | |
default: 'x-j9WsahRe_1An51DhErab-C' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Drupal\MYMODULE\Plugin\Block; | |
use Drupal\Core\Block\Attribute\Block; | |
use Drupal\Core\Block\BlockBase; | |
use Drupal\Core\Config\TypedConfigManagerInterface; | |
use Drupal\Core\Form\FormStateInterface; | |
use Drupal\Core\Plugin\ContainerFactoryPluginInterface; | |
use Drupal\Core\StringTranslation\TranslatableMarkup; | |
use Symfony\Component\DependencyInjection\ContainerInterface; | |
/** | |
* Provides a 'MySchemaFormBlock' embed widget block. | |
*/ | |
#[Block( | |
id: "mymodule_my_schema_form_block", | |
admin_label: new TranslatableMarkup("MyBlock embed widget") | |
)] | |
class MySchemaFormBlock extends BlockBase implements ContainerFactoryPluginInterface { | |
/** | |
* The typed config manager. | |
* | |
* @var \Drupal\Core\Config\TypedConfigManagerInterface | |
*/ | |
protected $typedConfigManager; | |
/** | |
* Constructs a new MySchemaFormBlock. | |
* | |
* @param array $configuration | |
* A configuration array containing information about the plugin instance. | |
* @param string $plugin_id | |
* The plugin ID for the plugin instance. | |
* @param mixed $plugin_definition | |
* The plugin implementation definition. | |
* @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config_manager | |
* The typed config manager. | |
*/ | |
public function __construct( | |
array $configuration, | |
$plugin_id, | |
$plugin_definition, | |
TypedConfigManagerInterface $typed_config_manager | |
) { | |
// Typed config manager must be set first, because the parent constructor | |
// will set configuration, which involves pulling defaults from the schema. | |
$this->typedConfigManager = $typed_config_manager; | |
parent::__construct($configuration, $plugin_id, $plugin_definition); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { | |
return new static( | |
$configuration, | |
$plugin_id, | |
$plugin_definition, | |
$container->get('config.typed') | |
); | |
} | |
/** | |
* Return the configurable parameters for this donation widget. | |
*/ | |
protected function getConfigurables(): array { | |
$specific_schema = $this->typedConfigManager->getDefinition('block.settings.' . $this->getBaseId()); | |
$parent_schema = $this->typedConfigManager->getDefinition('block_settings'); | |
$own_properties = array_diff_key( | |
$specific_schema['mapping'], | |
$parent_schema['mapping'] | |
); | |
return $own_properties; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function defaultConfiguration() { | |
return [ | |
'label_display' => FALSE, | |
] + array_map(function ($schema_info) { | |
return $schema_info['default'] ?? NULL; | |
}, $this->getConfigurables()); | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function blockForm($form, FormStateInterface $form_state) { | |
foreach ($this->getConfigurables() as $key => $schema_info) { | |
$form[$key] = [ | |
// Explicit support for certain types only. This is a bit like what | |
// config_translation_config_schema_info_alter() helps achieve. | |
'#type' => match ($schema_info['type']) { | |
'string', 'label' => 'textfield', | |
'text' => 'textarea', | |
'boolean' => 'checkbox', | |
'integer', 'float' => 'number', | |
'email' => 'email', | |
}, | |
'#title' => $schema_info['label'], | |
'#default_value' => $this->configuration[$key], | |
'#required' => empty($schema_info['nullable']), | |
// The 'locked' property is not specified in core. | |
'#disabled' => $schema_info['locked'] ?? FALSE, | |
]; | |
// Convert general regex in schema into whole-string regex for HTML. | |
if (!empty($schema_info['constraints']['Regex']['pattern'])) { | |
$pattern = $schema_info['constraints']['Regex']['pattern']; | |
// Extract the pattern within delimiters, ignore any regex modifiers, | |
// and strip off string start & end characters. The HTML pattern spec | |
// does not cater for any of these. | |
$delimiter = $pattern[0]; | |
$last_delimiter_position = strrpos($pattern, $delimiter); | |
$pattern = substr($pattern, 1, $last_delimiter_position - 1); | |
if (str_starts_with($pattern, '^')) { | |
$pattern = substr($pattern, 1); | |
} | |
if ( | |
str_ends_with($pattern, '$') && | |
// Some basic detection of escaped dollar signs at the end. | |
(!str_ends_with($pattern, '\$') || str_ends_with($pattern, '\\\\\$')) | |
) { | |
$pattern = substr($pattern, 0, -1); | |
} | |
$form[$key]['#pattern'] = $pattern; | |
if (!empty($schema_info['constraints']['Regex']['message'])) { | |
$form[$key]['#attributes']['title'] = $schema_info['constraints']['Regex']['message']; | |
} | |
} | |
} | |
return $form; | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function blockSubmit($form, FormStateInterface $form_state) { | |
foreach (array_keys($this->getConfigurables()) as $key) { | |
$this->configuration[$key] = $form_state->getValue($key); | |
} | |
} | |
/** | |
* {@inheritdoc} | |
*/ | |
public function build() { | |
foreach ($this->getConfigurables() as $key => $schema_info) { | |
$params[$key] = $this->configuration[$key] ?? $schema_info['default'] ?? ''; | |
} | |
// Double-check parameters are safe (though this should have been enforced | |
// by the config schema). | |
$params = array_map(function ($value) { | |
return preg_replace('/[^a-zA-Z0-9_-]/', '', $value); | |
}, $params); | |
$build = [ | |
'placeholder' => [ | |
'#type' => 'container', | |
], | |
'loader' => [ | |
'#type' => 'html_tag', | |
'#tag' => 'script', | |
'#attributes' => [ | |
'src' => 'https://example.com/embed-script-thing.js', | |
], | |
], | |
]; | |
$imploded_params = "'" . implode("', '", $params) . "'"; | |
$build['initialiser'] = [ | |
'#type' => 'html_tag', | |
'#tag' => 'script', | |
'#value' => 'SomeGlobal.someMethod(' . $imploded_params . ')', | |
]; | |
return $build; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment