View source
<?php
namespace Drupal\rate;
use Drupal\Core\Datetime\DateFormatter;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Url;
use Drupal\field\Entity\FieldConfig;
use Symfony\Component\DependencyInjection\ContainerInterface;
class RateWidgetForm extends EntityForm {
protected $entityTypeManager;
protected $entityFieldManager;
protected $moduleHandler;
protected $dateFormatter;
protected $messenger;
public function __construct(EntityTypeManagerInterface $entity_manager, EntityFieldManagerInterface $entity_field_manager, ModuleHandlerInterface $module_handler, DateFormatter $date_formatter, MessengerInterface $messenger) {
$this->entityTypeManager = $entity_manager;
$this->entityFieldManager = $entity_field_manager;
$this->moduleHandler = $module_handler;
$this->dateFormatter = $date_formatter;
$this->messenger = $messenger;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('entity_type.manager'), $container
->get('entity_field.manager'), $container
->get('module_handler'), $container
->get('date.formatter'), $container
->get('messenger'));
}
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$rate_widget = $this->entity;
$widget_template = $rate_widget
->get('template');
if ($this->operation == 'add') {
$form['#title'] = $this
->t('Add rate widget');
}
else {
$form['#title'] = $this
->t('Edit %label rate widget', [
'%label' => $rate_widget
->label(),
]);
}
$template_list = [];
foreach ($this->moduleHandler
->getImplementations('rate_templates') as $module) {
foreach ($this->moduleHandler
->invoke($module, 'rate_templates') as $name => $template) {
$template_list[$name] = $template->template_title;
if ($name == $widget_template) {
$current_template = $template;
$current_template->id = $name;
}
}
}
$form_state
->set('template_list', $template_list);
if (is_null($widget_template) || $this->operation == 'template' || $form_state
->has('page') && $form_state
->get('page') == 'template_selector') {
return self::templateSelector($form, $form_state);
}
$form_state
->set('page', 'rate_widget_form');
$form['label'] = [
'#title' => $this
->t('Name'),
'#type' => 'textfield',
'#default_value' => $rate_widget
->label(),
'#description' => $this
->t('The human-readable name of this rate widget. This name must be unique.'),
'#required' => TRUE,
'#size' => 30,
];
$form['id'] = [
'#type' => 'machine_name',
'#default_value' => $rate_widget
->id(),
'#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
'#machine_name' => [
'exists' => [
'Drupal\\rate\\Entity\\RateWidget',
'load',
],
'source' => [
'label',
],
],
'#description' => $this
->t('A unique machine-readable name for this rate widget. It must only contain lowercase letters, numbers, and underscores.'),
];
$form['template'] = [
'#type' => 'hidden',
'#value' => $rate_widget
->get('template'),
];
$form['template-selector'] = [
'#type' => 'textfield',
'#title' => $this
->t('Template'),
'#required' => TRUE,
'#default_value' => $template_list[$rate_widget
->get('template')] ? $template_list[$rate_widget
->get('template')] : '',
'#size' => 30,
'#attributes' => [
'disabled' => 'disabled',
],
];
if ($this->operation == 'edit') {
$url = Url::fromRoute('entity.rate_widget.template_form', [
'rate_widget' => $this->entity
->id(),
])
->toString();
$form['template-selector']['#description'] = $this
->t('The template can be changed [<a href="@template-selector">Change</a>]', [
'@template-selector' => $url,
]);
}
if ($current_template->customizable) {
$vote_types = [
'percent' => $this
->t('Percentage'),
'points' => $this
->t('Points'),
'option' => $this
->t('Options'),
];
$form['value_type'] = [
'#type' => 'radios',
'#title' => $this
->t('Value type'),
'#options' => $vote_types,
'#default_value' => $rate_widget
->get('value_type') ? $rate_widget
->get('value_type') : $current_template->value_type,
'#required' => TRUE,
];
}
else {
$form['value_type'] = [
'#type' => 'textfield',
'#title' => $this
->t('Value type'),
'#default_value' => $current_template->value_type ? $current_template->value_type : 'option',
'#size' => 30,
'#attributes' => [
'disabled' => 'disabled',
],
'#required' => TRUE,
];
}
$rate_widget_options = $rate_widget
->get('options');
if ($rate_widget
->isNew()) {
if (count($current_template->options) > 0) {
$options_items = $current_template->options;
}
else {
$options_items = [];
}
}
else {
if (count($rate_widget_options) > 0) {
if ($form_state
->get('overwrite_values') === TRUE) {
$options_items = $current_template->options;
}
else {
$options_items = isset($rate_widget_options['table']) ? $rate_widget_options['table'] : $rate_widget_options;
}
}
else {
$options_items = [];
}
}
$form['#tree'] = TRUE;
$form['options'] = [
'#type' => 'details',
'#title' => $this
->t('Options'),
'#description' => $this
->t('Define the available voting options/buttons. To delete an option - delete its values in the fields <i>value, label</i> and <i>class</i> and save the rate widget.'),
'#open' => TRUE,
'#prefix' => '<div id="options-table-wrapper">',
'#suffix' => '</div>',
];
$form['options']['table'] = [
'#type' => 'table',
'#header' => [
$this
->t('Value'),
$this
->t('Label'),
$this
->t('Class'),
],
'#responsive' => TRUE,
];
$options_items_count = count($options_items) + $form_state
->get('options_items_count');
for ($i = 0; $i < $options_items_count; $i++) {
$form['options']['table'][$i]['value'] = [
'#type' => 'textfield',
'#title' => $this
->t('Value'),
'#title_display' => 'invisible',
'#default_value' => isset($options_items[$i]['value']) ? $options_items[$i]['value'] : '',
'#size' => 8,
];
$form['options']['table'][$i]['label'] = [
'#type' => 'textfield',
'#title' => $this
->t('Label'),
'#title_display' => 'invisible',
'#default_value' => isset($options_items[$i]['label']) ? $options_items[$i]['label'] : '',
'#size' => 40,
];
$form['options']['table'][$i]['class'] = [
'#type' => 'textfield',
'#title' => $this
->t('Class'),
'#title_display' => 'invisible',
'#default_value' => isset($options_items[$i]['class']) ? $options_items[$i]['class'] : '',
'#size' => 40,
];
if (!$current_template->customizable) {
$form['options']['table'][$i]['value']['#attributes'] = [
'disabled' => 'disabled',
];
$form['options']['table'][$i]['label']['#attributes'] = [
'disabled' => 'disabled',
];
}
}
if ($current_template->customizable) {
$form['options']['actions'] = [
'#type' => 'actions',
'#prefix' => '<div id="action-buttons-wrapper">',
'#suffix' => '</div>',
];
$form['options']['actions']['add_item'] = [
'#type' => 'submit',
'#value' => $this
->t('Add another option'),
'#submit' => [
'::addOne',
],
'#ajax' => [
'callback' => '::addmoreCallback',
'wrapper' => 'options-table-wrapper',
],
];
}
$form['entities'] = [
'#type' => 'details',
'#title' => $this
->t('Entities'),
'#description' => $this
->t('Select the entities and/or comments on those entities, on which to enable this widget.'),
'#open' => TRUE,
'#prefix' => '<div id="options-table-wrapper">',
'#suffix' => '</div>',
];
$comment_module_enabled = $this->moduleHandler
->moduleExists('comment');
$comment_header = $comment_module_enabled ? $this
->t('Comment') : $this
->t('Comment (disabled)');
$form['entities']['table'] = [
'#type' => 'table',
'#header' => [
$this
->t('Name'),
$this
->t('Entity Type'),
$this
->t('Entity'),
$comment_header,
],
'#responsive' => TRUE,
];
$entity_types = $this->entityTypeManager
->getDefinitions();
$entity_type_ids = array_keys($entity_types);
$rate_widget_entities = $rate_widget
->get('entity_types') ? $rate_widget
->get('entity_types') : [];
$rate_widget_comments = $rate_widget
->get('comment_types') ? $rate_widget
->get('comment_types') : [];
foreach ($entity_types as $entity_type_id => $entity_type) {
$restrict_entities = [
'comment',
'block_content',
'contact_message',
'path_alias',
'menu_link_content',
'shortcut',
'vote',
'vote_result',
];
if ($entity_type
->getBundleOf() && !in_array($entity_type
->getBundleOf(), $restrict_entities)) {
$bundles = $this->entityTypeManager
->getStorage($entity_type_id)
->loadMultiple();
if (!empty($bundles)) {
foreach ($bundles as $bundle) {
$row = [];
$return_value = $entity_type
->getBundleOf() . '.' . $bundle
->id();
$row['entity_type'] = [
'#plain_text' => $bundle
->label(),
];
$row['entity_type_id'] = [
'#plain_text' => $entity_type
->getBundleOf(),
];
$row['entity_enabled'] = [
'#type' => 'checkbox',
'#empty_value' => '',
'#required' => FALSE,
'#default_value' => in_array($return_value, $rate_widget_entities),
'#return_value' => $return_value,
];
$row['comment_enabled'] = [
'#type' => 'checkbox',
'#empty_value' => '',
'#required' => FALSE,
'#default_value' => in_array($return_value, $rate_widget_comments),
'#return_value' => $return_value,
'#disabled' => !$comment_module_enabled,
];
$form['entities']['table'][] = $row;
}
}
}
elseif ($entity_type
->getGroup() == 'content' && !in_array($entity_type
->getBundleEntityType(), $entity_type_ids) && !in_array($entity_type
->id(), $restrict_entities)) {
$row = [];
$return_value = $entity_type_id . '.' . $entity_type_id;
$row['entity_type'] = [
'#plain_text' => $entity_type
->getLabel()
->__toString(),
];
$row['entity_type_id'] = [
'#plain_text' => $entity_type_id,
];
$row['entity_enabled'] = [
'#type' => 'checkbox',
'#empty_value' => '',
'#required' => FALSE,
'#default_value' => in_array($return_value, $rate_widget_entities),
'#return_value' => $return_value,
];
$row['comment_enabled'] = [
'#type' => 'checkbox',
'#empty_value' => '',
'#required' => FALSE,
'#default_value' => in_array($return_value, $rate_widget_comments),
'#return_value' => $return_value,
'#disabled' => !$comment_module_enabled,
];
$form['entities']['table'][] = $row;
}
}
$voting = $rate_widget
->get('voting');
$form['voting'] = [
'#type' => 'details',
'#title' => $this
->t('Voting settings'),
'#open' => TRUE,
];
$form['voting']['use_deadline'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Use a vote deadline'),
'#default_value' => isset($voting['use_deadline']) ? $voting['use_deadline'] : 0,
'#description' => $this
->t('Enables a deadline date field on the respective node. If deadline is set and date passed, the widget will be shown as disabled.'),
];
$unit_options = [
300,
900,
1800,
3600,
10800,
21600,
32400,
43200,
86400,
172800,
345600,
604800,
];
$options = [];
foreach ($unit_options as $option) {
$options[$option] = $this->dateFormatter
->formatInterval($option);
}
$options[0] = $this
->t('Immediately');
$options[-1] = $this
->t('Never');
$options[-2] = $this
->t('Votingapi setting');
$form['voting']['anonymous_window'] = [
'#type' => 'select',
'#title' => $this
->t('Anonymous vote rollover'),
'#description' => $this
->t('The amount of time that must pass before two anonymous votes from the same computer are considered unique. Setting this to <i>never</i> will eliminate most double-voting, but will make it impossible for multiple anonymous on the same computer (like internet cafe customers) from casting votes.'),
'#options' => $options,
'#default_value' => isset($voting['anonymous_window']) ? $voting['anonymous_window'] : -2,
];
$form['voting']['user_window'] = [
'#type' => 'select',
'#title' => $this
->t('Registered user vote rollover'),
'#description' => $this
->t('The amount of time that must pass before two registered user votes from the same user ID are considered unique. Setting this to <i>never</i> will eliminate most double-voting for registered users.'),
'#options' => $options,
'#default_value' => isset($voting['user_window']) ? $voting['user_window'] : -2,
];
$display = $rate_widget
->get('display');
$form['display'] = [
'#type' => 'details',
'#title' => $this
->t('Display settings'),
'#open' => TRUE,
];
$form['display']['display_label'] = [
'#type' => 'textfield',
'#title' => $this
->t('Label'),
'#default_value' => isset($display['display_label']) ? $display['display_label'] : '',
'#description' => $this
->t('Optional label for the rate widget.'),
];
$form['display']['label_class'] = [
'#type' => 'textfield',
'#title' => $this
->t('Label classes'),
'#default_value' => isset($display['label_class']) ? $display['label_class'] : '',
'#description' => $this
->t('Enter classes, separated with space.'),
];
$options = [
'inline' => $this
->t('Inline with the widget'),
'above' => $this
->t('Above the widget'),
'hidden' => $this
->t('Hide the label'),
];
$form['display']['label_position'] = [
'#type' => 'radios',
'#title' => $this
->t('Position of the label'),
'#options' => $options,
'#default_value' => isset($display['label_position']) ? $display['label_position'] : 'above',
];
$form['display']['description'] = [
'#type' => 'textfield',
'#title' => $this
->t('Description'),
'#default_value' => isset($display['description']) ? $display['description'] : '',
'#description' => $this
->t('Optional description which will be visible on the rate widget.'),
];
$form['display']['description_class'] = [
'#type' => 'textfield',
'#title' => $this
->t('Description classes'),
'#default_value' => isset($display['description_class']) ? $display['description_class'] : '',
'#description' => $this
->t('Enter classes, separated with space.'),
];
$options = [
'below' => $this
->t('Under the widget'),
'right' => $this
->t('To the right of the widget'),
'hidden' => $this
->t('Hide the description'),
];
$form['display']['description_position'] = [
'#type' => 'radios',
'#title' => $this
->t('Position of the description'),
'#options' => $options,
'#default_value' => isset($display['description_position']) ? $display['description_position'] : 'below',
];
$form['display']['readonly'] = [
'#type' => 'checkbox',
'#title' => $this
->t('Read only widget'),
'#default_value' => isset($display['readonly']) ? $display['readonly'] : 0,
];
$results = $rate_widget
->get('results');
$form['results'] = [
'#type' => 'details',
'#title' => $this
->t('Results'),
'#description' => $this
->t('Note that these settings do not apply for rate widgets inside views. Widgets in views will display the average voting when a relationship to the voting results is used and the users vote in case of a relationship to the votes.'),
'#open' => TRUE,
];
$options = [
'below' => $this
->t('Under the widget (or option)'),
'right' => $this
->t('To the right of the widget'),
'hidden' => $this
->t('Hide the results summary'),
];
$form['results']['result_position'] = [
'#type' => 'radios',
'#title' => $this
->t('Position of the results summary'),
'#options' => $options,
'#default_value' => isset($results['result_position']) ? $results['result_position'] : 'right',
];
$options = [
'user_vote_empty' => $this
->t('User vote if available, empty otherwise'),
'user_vote_average' => $this
->t('User vote if available, option results otherwise'),
'vote_average' => $this
->t('Option results'),
'vote_hidden' => $this
->t('Hide option results'),
];
$form['results']['result_type'] = [
'#type' => 'radios',
'#title' => $this
->t('Which rating (option results) should be displayed?'),
'#options' => $options,
'#default_value' => isset($results['result_type']) ? $results['result_type'] : 'user_vote_empty',
'#description' => $this
->t('Option results: shown for each option and based on the value type function - average (percentage), count (option) or sum (points).'),
];
return $form;
}
public function templateSelector(array &$form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$rate_widget = $this->entity;
$form_state
->set('page', 'template_selector');
$template_list = $form_state
->get('template_list');
$form['template'] = [
'#type' => 'select',
'#title' => $this
->t('Template'),
'#empty_value' => '',
'#required' => TRUE,
'#options' => $template_list,
'#default_value' => $rate_widget
->get('template'),
];
if ($this->operation == 'template') {
$form_state
->set('overwrite_values', TRUE);
$form['template']['#description'] = $this
->t('CAUTION: Changing the template will overwrite your current settings for options and value type!');
}
return $form;
}
protected function actions(array $form, FormStateInterface $form_state) {
$page = $form_state
->get('page');
if (isset($page) && $page == 'template_selector') {
$actions['next'] = [
'#type' => 'submit',
'#button_type' => 'primary',
'#value' => $this
->t('Next'),
'#validate' => [
'::templateSelectorNextValidate',
],
'#submit' => [
'::templateSelectorNextSubmit',
],
];
}
else {
$actions = parent::actions($form, $form_state);
$actions['submit']['#value'] = $this
->t('Save rate widget');
$actions['delete']['#value'] = $this
->t('Delete rate widget');
}
return $actions;
}
public function templateSelectorNextValidate(array &$form, FormStateInterface $form_state) {
$template = $form_state
->getValue('template');
if (!isset($template) || $template == '') {
$form_state
->setErrorByName('template', $this
->t('Select a template to continue!'));
}
}
public function templateSelectorNextSubmit(array &$form, FormStateInterface $form_state) {
$form_state
->set('page', 'rate_widget_form');
if (!$this->entity
->isNew()) {
$this
->setOperation('edit');
}
else {
$this
->setOperation('add');
}
$form_state
->setRebuild(TRUE);
}
public function addmoreCallback(array &$form, FormStateInterface $form_state) {
return $form['options'];
}
public function addOne(array &$form, FormStateInterface $form_state) {
$form_state
->set('options_items_count', 1);
$form_state
->setRebuild();
}
public function save(array $form, FormStateInterface $form_state) {
$rate_widget = $this->entity;
$rate_widget
->set('id', trim($rate_widget
->id()));
$rate_widget
->set('label', trim($rate_widget
->label()));
$rate_widget
->set('template', $rate_widget
->get('template'));
$rate_widget
->set('value_type', $rate_widget
->get('value_type'));
$options = $rate_widget
->get('options');
unset($options['actions']);
$options = $options['table'];
foreach ($options as $key => $value) {
if ($options[$key]['value'] == NULL) {
unset($options[$key]);
}
}
$options = array_values($options);
$rate_widget
->set('options', $options);
$entities = $rate_widget
->get('entities');
$entities = $entities['table'];
foreach ($entities as $key => $value) {
if ($entities[$key]['entity_enabled'] == NULL && $entities[$key]['comment_enabled'] == NULL) {
unset($entities[$key]);
}
}
$entities = array_values($entities);
$entity_types = [];
$comment_types = [];
$current_entities = $rate_widget
->get('entity_types');
$rate_widget
->set('entities', $entities);
foreach ($entities as $key => $value) {
if ($value['entity_enabled'] && $value['comment_enabled']) {
$entity_types[] = $value['entity_enabled'];
$comment_types[] = $value['comment_enabled'];
}
elseif ($value['entity_enabled']) {
$entity_types[] = $value['entity_enabled'];
}
elseif ($value['comment_enabled']) {
$comment_types[] = $value['comment_enabled'];
}
}
$rate_widget
->set('entity_types', $entity_types);
$rate_widget
->set('comment_types', $comment_types);
$removed_entities = array_diff($current_entities, $rate_widget
->get('entity_types'));
$deadline_value = $form['voting']['use_deadline']['#default_value'];
$deadline_new_value = $form['voting']['use_deadline']['#value'];
if ($deadline_new_value == 0 && $deadline_new_value != $deadline_value) {
$remove_deadline = TRUE;
}
$field_name = 'field_rate_vote_deadline';
if (isset($remove_deadline) && !empty($current_entities)) {
foreach ($current_entities as $key => $entity) {
$parameter = explode('.', $entity);
$field_config = FieldConfig::loadByName($parameter[0], $parameter[1], $field_name);
if (!empty($field_config)) {
$field_config
->delete();
$this->messenger
->addStatus($this
->t('Field %field removed from %entity.', [
'%field' => 'Rate vote deadline',
'%entity' => $entity,
]));
}
}
}
if ($deadline_new_value == 1 && !isset($remove_deadline) && !empty($removed_entities)) {
foreach ($removed_entities as $key => $entity) {
$parameter = explode('.', $entity);
$field_config = FieldConfig::loadByName($parameter[0], $parameter[1], $field_name);
if (!empty($field_config)) {
$field_config
->delete();
$this->messenger
->addStatus($this
->t('Field %field removed from %entity.', [
'%field' => 'Rate vote deadline',
'%entity' => $entity,
]));
}
}
}
$voting = $rate_widget
->get('voting') ? $rate_widget
->get('voting') : [];
$display = $rate_widget
->get('display') ? $rate_widget
->get('display') : [];
$results = $rate_widget
->get('results') ? $rate_widget
->get('results') : [];
$rate_widget
->set('voting', $voting);
$rate_widget
->set('display', $display);
$rate_widget
->set('results', $results);
$status = $rate_widget
->save();
$t_args = [
'%name' => $rate_widget
->label(),
];
if ($status == SAVED_UPDATED) {
$this
->messenger()
->addStatus($this
->t('The rate widget %name has been updated.', $t_args));
}
elseif ($status == SAVED_NEW) {
$this
->messenger()
->addStatus($this
->t('The rate widget %name has been added.', $t_args));
$context = array_merge($t_args, [
'link' => $rate_widget
->toLink($this
->t('View'), 'collection')
->toString(),
]);
$this
->logger('rate_widget')
->notice('Added rate widget %name.', $context);
}
$this->entityFieldManager
->clearCachedFieldDefinitions();
$form_state
->setRedirect('entity.rate_widget.collection');
}
}