View source
<?php
namespace Drupal\lightning_scheduler\Plugin\Field\FieldWidget;
use Drupal\Component\Serialization\Json;
use Drupal\content_moderation\Plugin\Field\FieldWidget\ModerationStateWidget as BaseModerationStateWidget;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\datetime\Plugin\Field\FieldType\DateTimeItemInterface;
use Drupal\lightning_scheduler\TransitionManager;
use Drupal\lightning_scheduler\TransitionSet;
use Symfony\Component\DependencyInjection\ContainerInterface;
final class ModerationStateWidget extends BaseModerationStateWidget {
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$configuration['third_party_settings'] += [
'lightning_scheduler' => [
'time_step' => $container
->get('config.factory')
->get('lightning_scheduler.settings')
->get('time_step'),
],
];
return parent::create($container, $configuration, $plugin_id, $plugin_definition);
}
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = parent::formElement($items, $delta, $element, $form, $form_state);
$entity = $items
->getEntity();
assert($entity instanceof ContentEntityInterface);
$has_fields = $entity
->hasField('scheduled_transition_date') && $entity
->hasField('scheduled_transition_state');
if (!$has_fields) {
return $element;
}
$states = $this
->getStates($entity);
$storage = $this->entityTypeManager
->getStorage($entity
->getEntityTypeId());
if (!$entity
->isNew() && $storage
->getEntityType()
->isRevisionable() && ($latest_revision_id = $storage
->getLatestRevisionId($entity
->id()))) {
$latest_revision = $storage
->loadRevision($latest_revision_id) ?: $entity;
}
else {
$latest_revision = $entity;
}
$transition_set = new TransitionSet($latest_revision
->get('scheduled_transition_date'), $latest_revision
->get('scheduled_transition_state'));
$element['scheduled_transitions'] = [
'#type' => 'html_tag',
'#tag' => 'TransitionSet',
'#attributes' => [
'states' => Json::encode($states),
'step' => $this
->getThirdPartySetting('lightning_scheduler', 'time_step', 60),
],
'#attached' => [
'library' => [
'lightning_scheduler/widget',
],
],
'data' => [
'#type' => 'hidden',
'#entity_uuid' => $entity
->uuid(),
'#element_validate' => [
[
TransitionManager::class,
'validate',
],
[
$this,
'storeValue',
],
],
'#default_value' => $transition_set
->toJSON(),
'#process' => [
[
$this,
'processComponentInput',
],
],
],
];
return $element;
}
public function processComponentInput(array $element, FormStateInterface $form_state) {
$key = $element['#parents'];
if ($form_state
->hasValue($key)) {
$element['#default_value'] = $form_state
->getValue($key);
}
return $element;
}
public function storeValue(array $element, FormStateInterface $form_state) {
if ($form_state
->getErrors()) {
return;
}
assert(!empty($element['#entity_uuid']));
$decoded = Json::decode($element['#value']);
assert(is_array($decoded));
$transition_storage = $form_state
->getValue('transition_storage') ?: [];
$uuid = $element['#entity_uuid'];
$transition_storage[$uuid] = $decoded;
$form_state
->setValue('transition_storage', $transition_storage);
}
public function extractFormValues(FieldItemListInterface $items, array $form, FormStateInterface $form_state) {
parent::extractFormValues($items, $form, $form_state);
$transitions = $form_state
->getValue('transition_storage');
$entity = $items
->getEntity();
$uuid = $entity
->uuid();
if (!isset($transitions[$uuid])) {
return;
}
$states = array_map(function (array $transition) {
assert(!empty($transition['state']) && is_string($transition['state']));
return [
'value' => $transition['state'],
];
}, $transitions[$uuid]);
$dates = array_map(function (array $transition) {
return [
'value' => gmdate(DateTimeItemInterface::DATETIME_STORAGE_FORMAT, $transition['when']),
];
}, $transitions[$uuid]);
assert(count($states) === count($dates));
$entity
->set('scheduled_transition_state', $states)
->set('scheduled_transition_date', $dates);
}
private function getStates(ContentEntityInterface $entity) {
$states = [];
$workflow = $this->moderationInformation
->getWorkflowForEntity($entity);
foreach ($workflow
->getTypePlugin()
->getTransitions() as $transition) {
$base_permission = $workflow
->id() . ' transition ' . $transition
->id();
if ($this->currentUser
->hasPermission("schedule {$base_permission}") || $this->currentUser
->hasPermission("use {$base_permission}")) {
$to_state = $transition
->to();
$states[$to_state
->id()] = $to_state
->label();
}
}
return $states;
}
}