View source
<?php
namespace Drupal\workbench_moderation\Plugin\Field\FieldWidget;
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\Plugin\Field\FieldWidget\OptionsSelectWidget;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\workbench_moderation\Entity\ModerationStateTransition;
use Drupal\workbench_moderation\ModerationInformation;
use Drupal\workbench_moderation\StateTransitionValidation;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ModerationStateWidget extends OptionsSelectWidget implements ContainerFactoryPluginInterface {
protected $currentUser;
protected $moderationStateTransitionEntityQuery;
protected $moderationStateStorage;
protected $moderationInformation;
protected $entityTypeManager;
protected $moderationStateTransitionStorage;
protected $validator;
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, AccountInterface $current_user, EntityTypeManagerInterface $entity_type_manager, EntityStorageInterface $moderation_state_storage, EntityStorageInterface $moderation_state_transition_storage, QueryInterface $entity_query, ModerationInformation $moderation_information, StateTransitionValidation $validator) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->moderationStateTransitionEntityQuery = $entity_query;
$this->moderationStateTransitionStorage = $moderation_state_transition_storage;
$this->moderationStateStorage = $moderation_state_storage;
$this->entityTypeManager = $entity_type_manager;
$this->currentUser = $current_user;
$this->moderationInformation = $moderation_information;
$this->validator = $validator;
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container
->get('current_user'), $container
->get('entity_type.manager'), $container
->get('entity_type.manager')
->getStorage('moderation_state'), $container
->get('entity_type.manager')
->getStorage('moderation_state_transition'), $container
->get('entity.query')
->get('moderation_state_transition', 'AND'), $container
->get('workbench_moderation.moderation_information'), $container
->get('workbench_moderation.state_transition_validation'));
}
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$entity = $items
->getEntity();
$bundle_entity = $this->entityTypeManager
->getStorage($entity
->getEntityType()
->getBundleEntityType())
->load($entity
->bundle());
if (!$this->moderationInformation
->isModeratableEntity($entity)) {
return $element + [
'#access' => FALSE,
];
}
$default = $items
->get($delta)->target_id ?: $bundle_entity
->getThirdPartySetting('workbench_moderation', 'default_moderation_state', FALSE);
$default_state = $this->entityTypeManager
->getStorage('moderation_state')
->load($default);
if (!$default || !$default_state) {
throw new \UnexpectedValueException(sprintf('The %s bundle has an invalid moderation state configuration, moderation states are enabled but no default is set.', $bundle_entity
->label()));
}
$transitions = $this->validator
->getValidTransitions($entity, $this->currentUser);
$target_states = [];
foreach ($transitions as $transition) {
$target_states[$transition
->getToState()] = $transition
->label();
}
$element += [
'#access' => FALSE,
'#type' => 'select',
'#options' => $target_states,
'#default_value' => $default,
'#published' => $default ? $default_state
->isPublishedState() : FALSE,
];
$element['#process'][] = [
get_called_class(),
'processActions',
];
return $element;
}
public static function updateStatus($entity_type_id, ContentEntityInterface $entity, array $form, FormStateInterface $form_state) {
$element = $form_state
->getTriggeringElement();
if (isset($element['#moderation_state'])) {
$entity->moderation_state->target_id = $element['#moderation_state'];
}
}
public static function processActions($element, FormStateInterface $form_state, array &$form) {
$default_button = $form['actions']['submit'];
$default_button['#access'] = TRUE;
$options = $element['#options'];
$entity = $form_state
->getFormObject()
->getEntity();
$translatable = !$entity
->isNew() && $entity
->isTranslatable();
foreach ($options as $id => $label) {
$button = [
'#dropbutton' => 'save',
'#moderation_state' => $id,
'#weight' => -10,
];
$button['#value'] = $translatable ? t('Save and @transition (this translation)', [
'@transition' => $label,
]) : t('Save and @transition', [
'@transition' => $label,
]);
$form['actions']['moderation_state_' . $id] = $button + $default_button;
}
foreach ([
'publish',
'unpublish',
'submit',
] as $key) {
$form['actions'][$key]['#access'] = FALSE;
unset($form['actions'][$key]['#dropbutton']);
}
$form['#entity_builders']['update_moderation_state'] = [
get_called_class(),
'updateStatus',
];
return $element;
}
public static function isApplicable(FieldDefinitionInterface $field_definition) {
return parent::isApplicable($field_definition) && $field_definition
->getName() === 'moderation_state';
}
public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
$field_name = $this->fieldDefinition
->getName();
$path = array_merge($form['#parents'], array(
$field_name,
));
$key_exists = NULL;
$values = $form_state
->getValues();
$value = NestedArray::getValue($values, $path, $key_exists);
if (empty($value)) {
parent::extractFormValues($items, $form, $form_state);
return;
}
if (!isset($value[0]['target_id'])) {
NestedArray::setValue($values, $path, [
[
'target_id' => reset($value),
],
]);
$form_state
->setValues($values);
}
parent::extractFormValues($items, $form, $form_state);
}
}