You are here

public function RateWidgetForm::form in Rate 8.2

Gets the actual form array to be built.

Overrides EntityForm::form

See also

\Drupal\Core\Entity\EntityForm::processForm()

\Drupal\Core\Entity\EntityForm::afterBuild()

File

src/RateWidgetForm.php, line 95

Class

RateWidgetForm
Form controller for vote type forms.

Namespace

Drupal\rate

Code

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(),
    ]);
  }

  // Collect rate widget templates from other modules.
  $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 we create a widget or change the template - show selector instead.
  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.'),
  ];

  // Template selector.
  $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.
    $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,
    ];
  }

  // Options table.
  $rate_widget_options = $rate_widget
    ->get('options');
  if ($rate_widget
    ->isNew()) {
    if (count($current_template->options) > 0) {

      // If the template has options defined - use them.
      $options_items = $current_template->options;
    }
    else {

      // Otherwise - create an empty row.
      $options_items = [];
    }
  }
  else {
    if (count($rate_widget_options) > 0) {
      if ($form_state
        ->get('overwrite_values') === TRUE) {

        // We are changing the template of an existing widget - overwrite.
        $options_items = $current_template->options;
      }
      else {

        // We are editing an existing widget - use saved values.
        $options_items = isset($rate_widget_options['table']) ? $rate_widget_options['table'] : $rate_widget_options;
      }
    }
    else {

      // Widget has no saved values - create an empty row.
      $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',
      ];
    }
  }

  // Hide the "Add another option" button, if template is not customizable.
  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',
      ],
    ];
  }

  // Entities.
  $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 voting on certain content types - not shown in the list.
    // Comments are handled throu the content types, blocks, menu items etc.
    // Also, don't allow voting on votes, that would be weird.
    $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(),
          ];

          // Entity column.
          $row['entity_enabled'] = [
            '#type' => 'checkbox',
            '#empty_value' => '',
            '#required' => FALSE,
            '#default_value' => in_array($return_value, $rate_widget_entities),
            '#return_value' => $return_value,
          ];

          // Comment column.
          $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,
      ];

      // Entity column.
      $row['entity_enabled'] = [
        '#type' => 'checkbox',
        '#empty_value' => '',
        '#required' => FALSE,
        '#default_value' => in_array($return_value, $rate_widget_entities),
        '#return_value' => $return_value,
      ];

      // Comment column.
      $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 settings.
  $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.'),
  ];

  // Additional settings for rollover 'Never' or 'Immediately'.
  // Work in progress for both options in votingapi module.
  // See https://www.drupal.org/project/votingapi/issues/3060468 (Reg. user).
  // See https://www.drupal.org/project/votingapi/issues/2791129 (Anonymous).
  // @TODO: When those options get committed in votingapi - rewrite this.
  $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 settings.
  $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 settings.
  $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;
}