View source
<?php
namespace Drupal\votingapi_reaction\Form;
use Drupal\Component\Datetime\TimeInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Session\AccountProxy;
use Drupal\votingapi\Entity\Vote;
use Drupal\votingapi_reaction\Plugin\Field\FieldType\VotingApiReactionItemInterface;
use Drupal\votingapi_reaction\VotingApiReactionManager;
use Symfony\Component\DependencyInjection\ContainerInterface;
class VotingApiReactionForm extends ContentEntityForm {
protected $entity;
protected $reactionManager;
protected $currentUser;
public function __construct(VotingApiReactionManager $reaction_manager, AccountProxy $current_user, EntityRepositoryInterface $entity_repository, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) {
parent::__construct($entity_repository, $entity_type_bundle_info, $time);
$this->reactionManager = $reaction_manager;
$this->currentUser = $current_user;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('votingapi_reaction.manager'), $container
->get('current_user'), $container
->get('entity.repository'), $container
->get('entity_type.bundle.info'), $container
->get('datetime.time'));
}
public function getFormId() {
$entity = $this
->getEntity();
return implode('_', [
'votingapi_reaction',
$entity
->getVotedEntityType(),
$entity
->getVotedEntityId(),
$entity
->get('field_name')->value,
]);
}
public function buildForm(array $form, FormStateInterface $form_state) {
$field_items = $form_state
->get('field_items');
$settings = $form_state
->get('formatter_settings') + $field_items
->getSettings();
$form = parent::buildForm($form, $form_state);
$form['#id'] = Html::getUniqueId('votingapi_reaction_form');
$form['#attached']['library'][] = 'votingapi_reaction/scripts';
$form['#attributes']['class'][] = 'votingapi-reaction-form';
$form['#attributes']['autocomplete'] = 'off';
$form['#cache']['max-age'] = 0;
if ($entity = $this->reactionManager
->lastReaction($this->entity, $settings)) {
$this->entity = $entity;
}
$status = $this
->checkStatus($form_state);
$access = $this
->checkAccess($form_state, $this->entity);
$form['#access'] = !is_null($status) && !is_null($access);
$results = $this->reactionManager
->getResults($this->entity, $settings);
if ($settings['show_summary']) {
$total = array_sum(array_column($results, 'vote_sum'));
$form['summary'] = [
'#type' => '#markup',
'#markup' => $this
->formatPlural($total, '@count reaction', '@count reactions'),
];
}
$form['type'] = [
'#type' => 'radios',
'#options' => $this->reactionManager
->getReactions($settings, $results),
'#default_value' => $this->entity
->bundle(),
'#id' => $form['#id'] . '-vote',
'#ajax' => [
'callback' => [
$this,
'ajaxSubmitForm',
],
'event' => 'click',
'wrapper' => $form['#id'],
'progress' => [
'type' => NULL,
'message' => NULL,
],
],
'#disabled' => !$status || !$access,
];
$form['reactions'] = [
'#type' => 'value',
'#value' => $form_state
->hasValue('reactions') ? $form_state
->getValue('reactions') : array_keys($form['type']['#options']),
];
$form['actions'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#noscript' => TRUE,
'#weight' => 1,
];
$form['actions']['submit'] = [
'#type' => 'submit',
'#value' => $this
->t('Submit'),
'#disabled' => !$status || !$access,
'#submit' => [
'::submitForm',
],
];
$form['actions']['reset'] = [
'#type' => 'submit',
'#value' => $this
->t('Reset'),
'#disabled' => !$status || !$access,
];
return $form;
}
public function processForm($element, FormStateInterface $form_state, $form) {
$field_items = $form_state
->get('field_items');
$settings = $form_state
->get('formatter_settings') + $field_items
->getSettings();
if ($entity = $this->reactionManager
->lastReaction($this->entity, $settings)) {
$this->entity = $entity;
}
else {
$this->entity = Vote::create([
'type' => '',
'entity_id' => $this->entity
->getVotedEntityId(),
'entity_type' => $this->entity
->getVotedEntityType(),
'value_type' => 'option',
'value' => 1,
'field_name' => $this->entity
->get('field_name')->value,
]);
}
return $element;
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$reaction = NULL;
$trigger = $form_state
->getTriggeringElement();
if ($this->entity
->bundle() != $form_state
->getValue('type') && array_search('reset', $trigger['#parents']) === FALSE) {
parent::submitForm($form, $form_state);
parent::save($form, $form_state);
$reaction = $form_state
->getValue('type');
$this->reactionManager
->rememberReaction($this->entity);
}
else {
$this->reactionManager
->forgetReaction($this->entity);
$this->entity
->delete();
}
$this->reactionManager
->recalculateResults($this->entity
->getVotedEntityType(), $this->entity
->getVotedEntityId(), $this->entity
->bundle());
$this->reactionManager
->recalculateResults($this->entity
->getVotedEntityType(), $this->entity
->getVotedEntityId(), $reaction);
$field_items = $form_state
->get('field_items');
$settings = $form_state
->get('formatter_settings') + $field_items
->getSettings();
$results = $this->reactionManager
->getResults($this->entity, $settings);
if (isset($form['summary'])) {
$form['summary']['#markup'] = $this
->formatPlural(array_sum(array_column($results, 'vote_sum')), '@count reaction', '@count reactions');
}
$form['type']['#options'] = $this->reactionManager
->getReactions($settings, $results);
foreach ($form['reactions']['#value'] as $weight => $id) {
$form['type'][$id]['#title'] = $form['type']['#options'][$id];
$form['type'][$id]['#value'] = $reaction;
$form['type'][$id]['#weight'] = $weight / 100;
}
}
public function ajaxSubmitForm(array $form, FormStateInterface $form_state) {
$this
->submitForm($form, $form_state);
return $form;
}
private function checkStatus(FormStateInterface $form_state) {
$items = $form_state
->get('field_items');
if ($items->status == VotingApiReactionItemInterface::HIDDEN) {
return NULL;
}
return $items->status == VotingApiReactionItemInterface::OPEN;
}
private function checkAccess(FormStateInterface $form_state, $modify = FALSE) {
$items = $form_state
->get('field_items');
$instance = implode(':', [
$items
->getEntity()
->getEntityTypeId(),
$items
->getEntity()
->bundle(),
$items
->getName(),
]);
if (!$this->currentUser
->hasPermission('view reactions on ' . $instance)) {
return NULL;
}
return $this->currentUser
->hasPermission($modify ? 'modify reaction on ' . $instance : 'create reaction on ' . $instance);
}
}