whitelabel-8.x-2.x-dev/src/Plugin/Field/FieldWidget/InlineWhiteLabelWidget.php
src/Plugin/Field/FieldWidget/InlineWhiteLabelWidget.php
<?php
namespace Drupal\whitelabel\Plugin\Field\FieldWidget;
use Drupal\altcolor\Form\ColorForm;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Ajax\SettingsCommand;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\whitelabel\Entity\WhiteLabel;
use Drupal\whitelabel\Entity\WhiteLabelInterface;
use League\ColorExtractor\Color;
use League\ColorExtractor\ColorExtractor;
use League\ColorExtractor\Palette;
/**
* Plugin implementation of the 'white label entity_reference' widget.
*
* @FieldWidget(
* id = "entity_reference_whitelabel",
* label = @Translation("White label"),
* description = @Translation("A white label inline form widget."),
* field_types = {
* "entity_reference_revisions"
* }
* )
*/
class InlineWhiteLabelWidget extends WidgetBase {
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'color_scanner' => TRUE,
'color_scanner_amount' => 5,
'form_display_mode' => 'default',
];
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$elements = [];
$elements['color_scanner'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enable color scanner'),
'#description' => $this->t('This shows the most used colors in the uploaded logo.'),
'#default_value' => $this->getSetting('color_scanner'),
];
$elements['color_scanner_amount'] = [
'#type' => 'number',
'#title' => $this->t('Amount of colors to detect'),
'#default_value' => $this->getSetting('color_scanner_amount'),
'#states' => [
'visible' => [
':input[name="fields[field_white_label][settings_edit_form][settings][color_scanner]"]' => ['checked' => TRUE],
],
],
];
$elements['form_display_mode'] = [
'#type' => 'select',
'#options' => \Drupal::service('entity_display.repository')->getFormModeOptions($this->getFieldSetting('target_type')),
'#title' => $this->t('Form display mode'),
'#description' => $this->t('The form display mode to use when rendering the white label form.'),
'#default_value' => $this->getSetting('form_display_mode'),
'#required' => TRUE,
];
return $elements;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$enabled = $this->getSetting('color_scanner');
$amount = $this->getSetting('color_scanner_amount');
$summary = [];
$summary[] = $this->t('Color scanner: @color_scanner', ['@color_scanner' => $enabled ? $this->t('Listing @amount colors', ['@amount' => $amount]) : $this->t('Disabled')]);
$summary[] = $this->t('Form display mode: @form_display_mode', ['@form_display_mode' => $this->getSetting('form_display_mode')]);
return $summary;
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
/** @var \Drupal\whitelabel\Entity\WhiteLabelInterface $whitelabel_entity */
if (!$whitelabel_entity = $items[$delta]->entity) {
$whitelabel_entity = WhiteLabel::create();
}
$field_name = $this->fieldDefinition->getName();
$parents = $element['#field_parents'];
$element_parents = $parents;
$element_parents[] = $field_name;
$element_parents[] = $delta;
$element += [
'#type' => 'details',
'#open' => TRUE,
'#attributes' => [
'class' => ['whitelabel-form'],
],
'#parents' => $element_parents,
];
$display = EntityFormDisplay::collectRenderDisplay($whitelabel_entity, $this->getSetting('form_display_mode'));
$display->buildForm($whitelabel_entity, $element, $form_state);
$element['theme']['widget']['#empty_option'] = $this->t('Use the default theme');
unset($element['theme']['widget']['#options']['_none']);
// Get the theme from the white label, otherwise check white label settings
// for an override. Fallback to the configured default theme.
$configured_theme = !empty(\Drupal::config('whitelabel.settings')->get('site_admin_theme'))
? \Drupal::config('whitelabel.settings')->get('site_admin_theme')
: null;
$theme = $whitelabel_entity->getTheme()
?? $configured_theme
?? \Drupal::config('system.theme')->get('default');
if (\Drupal::service('module_handler')->moduleExists('altcolor')) {
['colors' => $colors] = \Drupal::service('altcolor.fetcher')->fetch($theme);
// Only do something if the theme has defined colors in THEME.colors.yml.
if ($colors) {
/** @var \Drupal\Core\DependencyInjection\ClassResolver $class_resolver */
$class_resolver = \Drupal::service('class_resolver');
/** @var \Drupal\altcolor\Form\ColorForm $colorform */
$color_form = $class_resolver->getInstanceFromDefinition(ColorForm::class);
$new_form_state = (new FormState());
$element += $color_form->buildForm([], $new_form_state, $theme);
// Inject the white label defined colors into the white label color form.
$palette = $whitelabel_entity->getPalette();
foreach ($element['altcolor']['colors']['colors'] as $key => &$color) {
// If this subkey is a property instead of a subfield, skip it.
// Also make sure that it is defined in the white label palette.
if (stripos($key, '#') !== 0 && !empty($palette[$key])) {
$color['#default_value'] = $palette[$key];
}
}
}
}
$widget_state['whitelabel'][$delta]['entity'] = $whitelabel_entity;
$widget_state['whitelabel'][$delta]['display'] = $display;
static::setWidgetState($parents, $field_name, $form_state, $widget_state);
return $element;
}
/**
* {@inheritdoc}
*/
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
$field_name = $this->fieldDefinition->getName();
$widget_state = static::getWidgetState($form['#parents'], $field_name, $form_state);
$element = NestedArray::getValue($form_state->getCompleteForm(), $widget_state['array_parents']);
foreach ($values as $delta => &$item) {
if (isset($widget_state['whitelabel'][$item['_original_delta']]['entity'])) {
/** @var \Drupal\whitelabel\Entity\WhiteLabelInterface $whitelabel_entity */
$whitelabel_entity = $widget_state['whitelabel'][$item['_original_delta']]['entity'];
/** @var \Drupal\Core\Entity\Display\EntityFormDisplayInterface $form_display */
$form_display = $widget_state['whitelabel'][$item['_original_delta']]['display'];
$form_display->extractFormValues($whitelabel_entity, $element[$item['_original_delta']], $form_state);
// A content entity form saves without any rebuild. It needs to set the
// language to update it in case of language change.
$langcode_key = $whitelabel_entity->getEntityType()->getKey('langcode');
if ($whitelabel_entity->get($langcode_key)->value != $form_state->get('langcode')) {
// If a translation in the given language already exists, switch to
// that. If there is none yet, update the language.
if ($whitelabel_entity->hasTranslation($form_state->get('langcode'))) {
$whitelabel_entity = $whitelabel_entity->getTranslation($form_state->get('langcode'));
}
else {
$whitelabel_entity->set($langcode_key, $form_state->get('langcode'));
}
}
// Update the palette only if the theme supports it.
if ($palette = $form_state->getValue('altcolor')['colors']) {
$whitelabel_entity->setPalette($palette);
}
// Get the owner of the parent entity so it can be set for white labels.
if ($parent_entity_owner = $form_state->getValue('uid')[0]['target_id']) {
$whitelabel_entity->setOwnerId($parent_entity_owner);
}
$whitelabel_entity->setNeedsSave(TRUE);
$item['entity'] = $whitelabel_entity;
$item['target_id'] = $whitelabel_entity->id();
$item['target_revision_id'] = $whitelabel_entity->getRevisionId();
}
}
return $values;
}
/**
* Callback to update parts of the form after an AJAX request.
*
* @param array $form
* An associative array containing the structure of the form.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* The AJAX response.
*/
public function ajaxCallback(array $form, FormStateInterface &$form_state) {
$triggeringElement = $form_state->getTriggeringElement();
$field_name = $this->fieldDefinition->getName();
$delta = $triggeringElement['#delta'];
$new_form_part = $form[$field_name]['widget'][$delta]['color_ajax_wrapper'];
$new_logo_setting = $form[$field_name]['widget'][$delta]['logo']['widget']['#attached']['drupalSettings'];
$new_scheme_setting = $form[$field_name]['widget'][$delta]['color_ajax_wrapper']['altcolor']['scheme']['#attached']['drupalSettings'];
$replace_selector = $form[$field_name]['widget'][$delta]['theme']['widget']['#ajax']['wrapper'];
$response = new AjaxResponse();
// Update the color schemes and gradients.
$settings = NestedArray::mergeDeep($new_logo_setting, $new_scheme_setting);
$response->addCommand(new SettingsCommand($settings, FALSE));
$response->addCommand(new ReplaceCommand($replace_selector, $new_form_part));
return $response;
}
/**
* {@inheritdoc}
*/
public function form(FieldItemListInterface $items, array &$form, FormStateInterface $form_state, $get_delta = NULL) {
$parents = $form['#parents'];
// Identify the manage field settings default value form.
if (in_array('default_value_input', $parents, TRUE)) {
// Since the entity is not reusable neither cloneable, having a default
// value is not supported.
return ['#markup' => $this->t('Default values are not supported for: %label.', ['%label' => $items->getFieldDefinition()->getLabel()])];
}
return parent::form($items, $form, $form_state, $get_delta);
}
/**
* {@inheritdoc}
*/
public static function isApplicable(FieldDefinitionInterface $field_definition) {
// Only allow this widget for references to white label entities.
$target_type = $field_definition->getSetting('target_type');
$entity_type = \Drupal::entityTypeManager()->getDefinition($target_type);
if ($entity_type) {
return $entity_type->entityClassImplements(WhiteLabelInterface::class);
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
// Filter possible empty items.
// @todo This is also being done in the parent class. Omit is here?
$items->filterEmptyItems();
return parent::extractFormValues($items, $form, $form_state);
}
}
