class LayoutBuilderCopyWidget in Layout Builder Asymmetric Translation 8.2
A widget to display the copy widget form.
@FieldWidget( id = "layout_builder_at_copy", label = @Translation("Layout Builder Asymmetric Translation"), description = @Translation("A field widget for Layout Builder. This exposes a checkbox on the entity form to copy the blocks on translation."), field_types = { "layout_section", }, multiple_values = FALSE, )
@internal Plugin classes are internal.
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\Core\Field\PluginSettingsBase implements DependentPluginInterface, PluginSettingsInterface
- class \Drupal\Core\Field\WidgetBase implements WidgetInterface, ContainerFactoryPluginInterface uses AllowedTagsXssTrait
- class \Drupal\layout_builder_at\Plugin\Field\FieldWidget\LayoutBuilderCopyWidget
- class \Drupal\Core\Field\WidgetBase implements WidgetInterface, ContainerFactoryPluginInterface uses AllowedTagsXssTrait
- class \Drupal\Core\Field\PluginSettingsBase implements DependentPluginInterface, PluginSettingsInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of LayoutBuilderCopyWidget
File
- src/
Plugin/ Field/ FieldWidget/ LayoutBuilderCopyWidget.php, line 32
Namespace
Drupal\layout_builder_at\Plugin\Field\FieldWidgetView source
class LayoutBuilderCopyWidget extends WidgetBase {
/**
* Options for appearance.
*
* @return array
*/
protected function options() {
return [
'unchecked' => $this
->t('Unchecked'),
'checked' => $this
->t('Checked'),
'checked_hidden' => $this
->t('Checked and hidden'),
];
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'appearance' => 'unchecked',
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$element['appearance'] = [
'#type' => 'select',
'#title' => t('Checkbox appearance'),
'#options' => $this
->options(),
'#default_value' => $this
->getSetting('appearance'),
];
return $element;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = [];
$summary[] = t('Appearance: @checked', [
'@checked' => $this
->options()[$this
->getSetting('appearance')],
]);
return $summary;
}
/**
* {@inheritdoc}
*/
public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
$field_name = $this->fieldDefinition
->getName();
$parents = $form['#parents'];
// Store field information in $form_state.
if (!static::getWidgetState($parents, $field_name, $form_state)) {
$field_state = [
'items_count' => count($items),
'array_parents' => [],
];
static::setWidgetState($parents, $field_name, $form_state, $field_state);
}
// Collect widget elements.
$elements = [];
$delta = 0;
$element = [
'#title' => $this->fieldDefinition
->getLabel(),
'#description' => FieldFilteredMarkup::create(\Drupal::token()
->replace($this->fieldDefinition
->getDescription())),
];
$element = $this
->formSingleElement($items, $delta, $element, $form, $form_state);
if ($element) {
if (isset($get_delta)) {
// If we are processing a specific delta value for a field where the
// field module handles multiples, set the delta in the result.
$elements[$delta] = $element;
}
else {
// For fields that handle their own processing, we cannot make
// assumptions about how the field is structured, just merge in the
// returned element.
$elements = $element;
}
}
// Populate the 'array_parents' information in $form_state->get('field')
// after the form is built, so that we catch changes in the form structure
// performed in alter() hooks.
$elements['#after_build'][] = [
get_class($this),
'afterBuild',
];
$elements['#field_name'] = $field_name;
$elements['#field_parents'] = $parents;
// Enforce the structure of submitted values.
$elements['#parents'] = array_merge($parents, [
$field_name,
]);
// Most widgets need their internal structure preserved in submitted values.
$elements += [
'#tree' => TRUE,
];
$return = [
// Aid in theming of widgets by rendering a classified container.
'#type' => 'container',
// Assign a different parent, to keep the main id for the widget itself.
'#parents' => array_merge($parents, [
$field_name . '_wrapper',
]),
'#attributes' => [
'class' => [
'field--type-' . Html::getClass($this->fieldDefinition
->getType()),
'field--name-' . Html::getClass($field_name),
'field--widget-' . Html::getClass($this
->getPluginId()),
],
],
'widget' => $elements,
];
return $return;
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$entity = $items
->getEntity();
$access = FALSE;
if ($entity instanceof ContentEntityInterface) {
$access = $entity
->isNewTranslation() && !$entity
->isDefaultTranslation();
}
$element['#layout_builder_at_access'] = $access;
$checked = FALSE;
$v = $this
->getSetting('appearance');
if ($v == 'checked' || $v == 'checked_hidden') {
$checked = TRUE;
}
$element['value'] = $element + [
'#access' => TRUE,
'#type' => 'checkbox',
'#default_value' => $checked,
'#title' => $this
->t('Copy blocks into translation'),
];
if ($v == 'checked_hidden') {
$element['value']['#access'] = FALSE;
}
return $element;
}
/**
* Extract form values.
*
* @param \Drupal\Core\Field\FieldItemListInterface $items
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*
* @throws \Drupal\Core\Entity\EntityStorageException
* @throws \Drupal\Core\TypedData\Exception\ReadOnlyException
*/
public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
// @todo This isn't resilient to being set twice, during validation and
// save https://www.drupal.org/project/drupal/issues/2833682.
if (!$form_state
->isValidationComplete()) {
return;
}
$field_name = $this->fieldDefinition
->getName();
// We can only copy if the field is set and access is TRUE.
if (isset($form[$field_name]['widget']['#layout_builder_at_access']) && !$form[$field_name]['widget']['#layout_builder_at_access']) {
return;
}
// Extract the values from $form_state->getValues().
$path = array_merge($form['#parents'], [
$field_name,
]);
$key_exists = NULL;
$values = NestedArray::getValue($form_state
->getValues(), $path, $key_exists);
$values = $this
->massageFormValues($values, $form, $form_state);
if (isset($values['value']) && $values['value']) {
// Replicate.
/** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
/** @var \Drupal\Core\Entity\ContentEntityInterface $default_entity */
$entity = $items
->getEntity();
$sourceLanguage = NULL;
if ($form_state
->hasValue('source_langcode')) {
$sourceLanguageArray = $form_state
->getValue('source_langcode');
if (isset($sourceLanguageArray['source'])) {
$sourceLanguage = $sourceLanguageArray['source'];
}
}
$default_entity = is_null($sourceLanguage) ? $entity
->getUntranslated() : $entity
->getTranslation($sourceLanguage);
/** @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface $layout */
$layout = $default_entity
->get(OverridesSectionStorage::FIELD_NAME);
$uuid = \Drupal::service('uuid');
/** @var \Drupal\layout_builder\Section[] $sections */
$sections = $layout
->getSections();
$new_sections = [];
foreach ($sections as $delta => $section) {
$cloned_section = clone $section;
// Remove components from the cloned section.
foreach ($cloned_section
->getComponents() as $c) {
$cloned_section
->removeComponent($c
->getUuid());
}
// Sort the components by weight.
$components = $section
->getComponents();
uasort($components, function (SectionComponent $a, SectionComponent $b) {
return $a
->getWeight() > $b
->getWeight() ? 1 : -1;
});
foreach ($components as $component) {
$add_component = TRUE;
$cloned_component = clone $component;
$configuration = $component
->get('configuration');
// Replicate inline block content.
if ($this
->isInlineBlock($configuration['id'])) {
/** @var \Drupal\block_content\BlockContentInterface $block */
/** @var \Drupal\block_content\BlockContentInterface $replicated_block */
$block = \Drupal::service('entity_type.manager')
->getStorage('block_content')
->loadRevision($configuration['block_revision_id']);
$replicated_block = $this
->cloneEntity('block_content', $block
->id());
if ($replicated_block) {
$replicated_block
->set('langcode', $entity
->language()
->getId());
$replicated_block
->save();
$configuration = $this
->updateComponentConfiguration($configuration, $replicated_block);
$cloned_component
->setConfiguration($configuration);
// Store usage.
\Drupal::service('inline_block.usage')
->addUsage($replicated_block
->id(), $entity);
}
else {
$add_component = FALSE;
$this
->messenger()
->addMessage($this
->t('The inline block "@label" was not duplicated.', [
'@label' => $block
->label(),
]));
}
}
// Add component.
if ($add_component) {
$cloned_component
->set('uuid', $uuid
->generate());
$cloned_section
->appendComponent($cloned_component);
}
}
$new_sections[] = $cloned_section;
}
$items
->setValue($new_sections);
}
else {
$items
->setValue(NULL);
}
}
/**
* Replicate an entity.
*
* @param $entity_type_id
* @param $entity_id
*
* @return \Drupal\Core\Entity\EntityInterface|NULL
*/
protected function cloneEntity($entity_type_id, $entity_id) {
$clone = NULL;
try {
/** @var \Drupal\Core\Entity\EntityInterface $entity */
/** @var \Drupal\Core\Entity\EntityInterface $clone */
$entity = \Drupal::service('entity_type.manager')
->getStorage($entity_type_id)
->load($entity_id);
$clone = $entity
->createDuplicate();
/** @var \Drupal\Core\Field\FieldDefinitionInterface[] $field_definitions */
$field_definitions = \Drupal::service('entity_field.manager')
->getFieldDefinitions($entity
->getEntityTypeId(), $entity
->bundle());
foreach ($field_definitions as $definition) {
// Support for Entity reference revisions.
if ($definition
->getFieldStorageDefinition()
->getType() == 'entity_reference_revisions') {
$new_values = [];
$target_type = $definition
->getFieldStorageDefinition()
->getSetting('target_type');
$values = $clone
->get($definition
->getName())
->getValue();
if (!empty($values)) {
foreach ($values as $value) {
/** @var \Drupal\Core\Entity\EntityInterface $reference */
/** @var \Drupal\Core\Entity\EntityInterface $reference_clone */
$reference = \Drupal::service('entity_type.manager')
->getStorage($target_type)
->load($value['target_id']);
$reference_clone = $reference
->createDuplicate();
$reference_clone
->save();
$new_values[] = [
'target_id' => $reference_clone
->id(),
'target_revision_id' => $reference_clone
->getRevisionId(),
];
}
if (!empty($new_values)) {
$clone
->set($definition
->getName(), $new_values);
}
}
}
}
} catch (\Exception $e) {
\Drupal::logger('layout_builder_at')
->error('Error cloning entity: @message', [
'@message' => $e
->getMessage(),
]);
}
return $clone;
}
/**
* Does the block id represent an inline block.
*
* @param $block_id
* The block id.
* @return bool
* True if this is an inline block else false.
*/
protected function isInlineBlock($block_id) {
return substr($block_id, 0, 13) === 'inline_block:';
}
/**
* Modify the supplied component configuration based on modified block.
*
* @param array $configuration
* The Layout Builder component configuration array.
* @param BlockContentInterface $replicated_block
* The cloned block.
* @return array
* A modified configuration array.
*/
protected function updateComponentConfiguration(array $configuration, BlockContentInterface $replicated_block) {
$configuration["block_revision_id"] = $replicated_block
->getRevisionId();
return $configuration;
}
}
Members
Name![]() |
Modifiers | Type | Description | Overrides |
---|---|---|---|---|
AllowedTagsXssTrait:: |
public | function | Returns a list of tags allowed by AllowedTagsXssTrait::fieldFilterXss(). | |
AllowedTagsXssTrait:: |
public | function | Returns a human-readable list of allowed tags for display in help texts. | |
AllowedTagsXssTrait:: |
public | function | Filters an HTML string to prevent XSS vulnerabilities. | |
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
LayoutBuilderCopyWidget:: |
protected | function | Replicate an entity. | |
LayoutBuilderCopyWidget:: |
public static | function |
Defines the default settings for this plugin. Overrides PluginSettingsBase:: |
|
LayoutBuilderCopyWidget:: |
public | function |
Extract form values. Overrides WidgetBase:: |
|
LayoutBuilderCopyWidget:: |
public | function |
Creates a form element for a field. Overrides WidgetBase:: |
|
LayoutBuilderCopyWidget:: |
public | function |
Returns the form for a single field widget. Overrides WidgetInterface:: |
|
LayoutBuilderCopyWidget:: |
protected | function | Does the block id represent an inline block. | |
LayoutBuilderCopyWidget:: |
protected | function | Options for appearance. | |
LayoutBuilderCopyWidget:: |
public | function |
Returns a form to configure settings for the widget. Overrides WidgetBase:: |
|
LayoutBuilderCopyWidget:: |
public | function |
Returns a short summary for the current widget settings. Overrides WidgetBase:: |
|
LayoutBuilderCopyWidget:: |
protected | function | Modify the supplied component configuration based on modified block. | |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
PluginSettingsBase:: |
protected | property | Whether default settings have been merged into the current $settings. | |
PluginSettingsBase:: |
protected | property | The plugin settings injected by third party modules. | |
PluginSettingsBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
6 |
PluginSettingsBase:: |
public | function |
Returns the value of a setting, or its default value if absent. Overrides PluginSettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Returns the array of settings, including defaults for missing settings. Overrides PluginSettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Gets the list of third parties that store information. Overrides ThirdPartySettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Gets the value of a third-party setting. Overrides ThirdPartySettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Gets all third-party settings of a given module. Overrides ThirdPartySettingsInterface:: |
|
PluginSettingsBase:: |
protected | function | Merges default settings values into $settings. | |
PluginSettingsBase:: |
public | function |
Informs the plugin that some configuration it depends on will be deleted. Overrides PluginSettingsInterface:: |
3 |
PluginSettingsBase:: |
public | function |
Sets the value of a setting for the plugin. Overrides PluginSettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Sets the settings for the plugin. Overrides PluginSettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Sets the value of a third-party setting. Overrides ThirdPartySettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Unsets a third-party setting. Overrides ThirdPartySettingsInterface:: |
|
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
WidgetBase:: |
protected | property | The field definition. | |
WidgetBase:: |
protected | property |
The widget settings. Overrides PluginSettingsBase:: |
|
WidgetBase:: |
public static | function | Ajax callback for the "Add another item" button. | |
WidgetBase:: |
public static | function | Submission handler for the "Add another item" button. | |
WidgetBase:: |
public static | function | After-build handler for field elements in a form. | |
WidgetBase:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
5 |
WidgetBase:: |
public | function |
Assigns a field-level validation error to the right widget sub-element. Overrides WidgetInterface:: |
8 |
WidgetBase:: |
public | function |
Reports field-level validation errors against actual form elements. Overrides WidgetBaseInterface:: |
2 |
WidgetBase:: |
protected | function | Special handling to create form elements for multiple values. | 1 |
WidgetBase:: |
protected | function | Generates the form element for a single copy of the widget. | |
WidgetBase:: |
protected | function | Returns the value of a field setting. | |
WidgetBase:: |
protected | function | Returns the array of field settings. | |
WidgetBase:: |
protected | function | Returns the filtered field description. | |
WidgetBase:: |
public static | function |
Retrieves processing information about the widget from $form_state. Overrides WidgetBaseInterface:: |
|
WidgetBase:: |
protected static | function | Returns the location of processing information within $form_state. | |
WidgetBase:: |
protected | function | Returns whether the widget handles multiple values. | |
WidgetBase:: |
public static | function |
Returns if the widget can be used for the provided field. Overrides WidgetInterface:: |
4 |
WidgetBase:: |
protected | function | Returns whether the widget used for default value form. | |
WidgetBase:: |
public | function |
Massages the form values into the format expected for field values. Overrides WidgetInterface:: |
7 |
WidgetBase:: |
public static | function |
Stores processing information about the widget in $form_state. Overrides WidgetBaseInterface:: |
|
WidgetBase:: |
public | function |
Constructs a WidgetBase object. Overrides PluginBase:: |
5 |