component_library-1.0.x-dev/modules/gcomponent_library/src/Plugin/Field/FieldWidget/StyleOverridesWidget.php
modules/gcomponent_library/src/Plugin/Field/FieldWidget/StyleOverridesWidget.php
<?php
declare(strict_types=1);
namespace Drupal\gcomponent_library\Plugin\Field\FieldWidget;
use Drupal\component_library\Entity\ComponentLibraryPattern;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element;
use Drupal\gcomponent_library\BaseFields;
use Drupal\gcomponent_library\Entity\LibraryCollection;
use Drupal\group\Entity\GroupInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Defines the 'gcomponent_library_style_overrides' field widget.
*
* @FieldWidget(
* id = "gcomponent_library_style_overrides",
* label = @Translation("Style Overrides"),
* field_types = {"map"},
* )
*/
final class StyleOverridesWidget extends WidgetBase {
private EntityTypeManagerInterface $entityTypeManager;
/**
* {@inheritdoc}
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->entityTypeManager = $entity_type_manager;
}
/**
* {@inheritdoc}
*/
public static function isApplicable(FieldDefinitionInterface $field_definition): bool {
return $field_definition->getTargetEntityTypeId() === 'group' && $field_definition->getName() === BaseFields::OVERRIDE_FIELD;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition): self {
return new self(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['third_party_settings'],
$container->get('entity_type.manager'),
);
}
/**
* {@inheritdoc}
*
* @return array
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state): array {
$group = $items->getEntity();
\assert($group instanceof GroupInterface);
// Exit early in case of a new group or one that doesn't have a collection
// set.
if ($group->isNew() || $group->get(BaseFields::COLLECTION_FIELD)->isEmpty()) {
return $element;
}
$element['style'] = [
'#type' => 'details',
'#title' => $this->t('Style'),
'#tree' => TRUE,
];
$library_collection = $group->get(BaseFields::COLLECTION_FIELD)->entity;
\assert($library_collection instanceof LibraryCollection);
foreach (LibraryCollection::getSupportedStyles() as $key => $label) {
$pattern = $this->entityTypeManager
->getStorage('component_library_pattern')
->load($key);
\assert($pattern instanceof ComponentLibraryPattern);
$tags = $pattern->get('tags');
$tag = !empty($tags) ? (string) \reset($tags) : (string) $this->t('Default');
$overridden = (bool) ($items[$delta]->getValue()[$key] ?? FALSE);
$element['style'][$tag][$key] = [
'#type' => 'container',
'#attributes' => ['data-style-override-container' => TRUE],
];
$element['style'][$tag][$key]['override'] = [
'#type' => 'checkbox',
'#title' => $this->t('Override'),
'#default_value' => $overridden,
'#attributes' => ['data-style-override-toggler' => TRUE],
];
$element['style'][$tag][$key]['value'] = [
'#type' => 'select',
'#title' => $label,
'#options' => [],
'#default_value' => $overridden ? $items[$delta]->getValue()[$key] : $library_collection->getStyle($key),
'#attributes' => ['data-style-override-input' => TRUE],
];
foreach ($pattern->getVariants() as $variation) {
$element['style'][$tag][$key]['value']['#options'][$variation->id()] = $variation->label();
}
\asort($element['style'][$tag][$key]['value']['#options'], \SORT_NATURAL);
}
foreach (Element::children($element['style']) as $key) {
$value =& $element['style'][$key];
$value['#type'] = 'details';
$value['#title'] = $key;
$value['#tree'] = TRUE;
}
$element['#attached']['library'][] = 'gcomponent_library/override_toggler';
return $element;
}
/**
* {@inheritdoc}
*
* @return array<int, mixed>
*/
public function massageFormValues(array $values, array $form, FormStateInterface $form_state): array {
$new_values = [];
foreach ($values as $delta => $value) {
foreach (\array_keys($value['style']) as $tag) {
foreach ($value['style'][$tag] as $key => $style_value) {
$new_values[$delta][$key] = $style_value['override'] ? $style_value['value'] : NULL;
}
}
}
return $new_values;
}
}
