View source
<?php
namespace Drupal\layout_builder_at\Plugin\Field\FieldWidget;
use Drupal\block_content\BlockContentInterface;
use Drupal\Component\Utility\Html;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Field\FieldFilteredMarkup;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\layout_builder\Plugin\SectionStorage\OverridesSectionStorage;
use Drupal\layout_builder\SectionComponent;
class LayoutBuilderCopyWidget extends WidgetBase {
protected function options() {
return [
'unchecked' => $this
->t('Unchecked'),
'checked' => $this
->t('Checked'),
'checked_hidden' => $this
->t('Checked and hidden'),
];
}
public static function defaultSettings() {
return [
'appearance' => 'unchecked',
] + parent::defaultSettings();
}
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;
}
public function settingsSummary() {
$summary = [];
$summary[] = t('Appearance: @checked', [
'@checked' => $this
->options()[$this
->getSetting('appearance')],
]);
return $summary;
}
public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
$field_name = $this->fieldDefinition
->getName();
$parents = $form['#parents'];
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);
}
$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)) {
$elements[$delta] = $element;
}
else {
$elements = $element;
}
}
$elements['#after_build'][] = [
get_class($this),
'afterBuild',
];
$elements['#field_name'] = $field_name;
$elements['#field_parents'] = $parents;
$elements['#parents'] = array_merge($parents, [
$field_name,
]);
$elements += [
'#tree' => TRUE,
];
$return = [
'#type' => 'container',
'#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;
}
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;
}
public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
if (!$form_state
->isValidationComplete()) {
return;
}
$field_name = $this->fieldDefinition
->getName();
if (isset($form[$field_name]['widget']['#layout_builder_at_access']) && !$form[$field_name]['widget']['#layout_builder_at_access']) {
return;
}
$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']) {
$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);
$layout = $default_entity
->get(OverridesSectionStorage::FIELD_NAME);
$uuid = \Drupal::service('uuid');
$sections = $layout
->getSections();
$new_sections = [];
foreach ($sections as $delta => $section) {
$cloned_section = clone $section;
foreach ($cloned_section
->getComponents() as $c) {
$cloned_section
->removeComponent($c
->getUuid());
}
$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');
if ($this
->isInlineBlock($configuration['id'])) {
$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);
\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(),
]));
}
}
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);
}
}
protected function cloneEntity($entity_type_id, $entity_id) {
$clone = NULL;
try {
$entity = \Drupal::service('entity_type.manager')
->getStorage($entity_type_id)
->load($entity_id);
$clone = $entity
->createDuplicate();
$field_definitions = \Drupal::service('entity_field.manager')
->getFieldDefinitions($entity
->getEntityTypeId(), $entity
->bundle());
foreach ($field_definitions as $definition) {
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) {
$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;
}
protected function isInlineBlock($block_id) {
return substr($block_id, 0, 13) === 'inline_block:';
}
protected function updateComponentConfiguration(array $configuration, BlockContentInterface $replicated_block) {
$configuration["block_revision_id"] = $replicated_block
->getRevisionId();
return $configuration;
}
}