webform_civicrm-8.x-5.0-beta3/src/Element/CivicrmSelectOptions.php

src/Element/CivicrmSelectOptions.php
<?php

namespace Drupal\webform_civicrm\Element;

use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\FormElement;

/**
 * @FormElement("civicrm_select_options")
 */
class CivicrmSelectOptions extends FormElement {

  public function getInfo() {
    $class = get_class($this);
    return [
      '#input' => TRUE,
      '#label' => t('option'),
      '#labels' => t('options'),
      '#civicrm_live_options' => TRUE,
      '#default_option' => NULL,
      '#form_key' => NULL,
      '#process' => [
        [$class, 'processSelectOptions'],
      ],
      '#theme_wrappers' => ['form_element'],
    ];
  }

  /**
   * {@inheritdoc}
   */
  public static function valueCallback(&$element, $input, FormStateInterface $form_state) {
    if ($input === FALSE) {
      if (!isset($element['#default_value'])) {
        return [];
      }

      return $element['#default_value'];
      // return static::convertOptionsToValues($options, $element['#options_description']);
    }
    elseif (is_array($input) && isset($input['options'])) {
      return $input['options'];
    }
    else {
      return $element['#default_value'];
    }
  }

  protected static function getFieldOptions($form_key, $data = []) {
    \Drupal::getContainer()->get('civicrm')->initialize();
    $field_options = \Drupal::service('webform_civicrm.field_options');
    return $field_options->get(['form_key' => $form_key], 'create', $data);
  }

  public static function processSelectOptions(&$element, FormStateInterface $form_state, &$complete_form) {
    $element['#tree'] = TRUE;
    // Add validate callback that extracts the associative array of options.
    $element += ['#element_validate' => []];
    array_unshift($element['#element_validate'], [get_called_class(), 'validateSelectOptions']);

    $element['options'] = [
      '#type' => 'table',
      '#tableselect' => TRUE,
      '#header' => [
        'item' => [
          'data' => ['#markup' => 'Item',]
        ],
        'enabled' => [
          'data' => [
            '#markup' => 'Enabled',
            '#access' => !$element['#civicrm_live_options'],
          ]
        ],
        'label' => [
          'data' => [
            '#markup' => 'Label',
            '#access' => !$element['#civicrm_live_options'],
          ]
        ],
        'default' => [
          'data' => [
            '#markup' => 'Default'
          ]
        ],
        'weight' => [
          'data' => [
            '#markup' => 'Weight',
            '#access' => !$element['#civicrm_live_options'],
          ]
        ],
      ],
      '#empty' => 'Nothing',
      '#tabledrag' => [
        [
          'action' => 'order',
          'relationship' => 'sibling',
          'group' => 'weight',
        ],
      ],
      '#value_callback' => [get_called_class(), 'valueCallback'],
    ];

    if ($element['#civicrm_live_options']) {
      $element['options']['#tabledrag'] = [];
      $element['options']['#tableselect'] = FALSE;
    }
    if (strpos($element['#form_key'], 'address_state_province_id') !== false || strpos($element['#form_key'], 'address_county_id') !== false) {
      $parent_label = (strpos($element['#form_key'], 'address_state_province_id') !== false) ? 'Country' : 'State/Province';
      $element['options']['#empty'] = t('Options are loaded dynamically on the webform based on the value selected in @key field.', ['@key' => $parent_label]);
    }

    $weight = 0;
    $webform = $form_state->getFormObject()->getWebform();
    $data = $webform->getHandler('webform_civicrm')->getConfiguration()['settings']['data'] ?? [];

    // $current_options is an array of [value => webform_label] listed in the order defined in the webform.
    // Options disabled in the webform are absent from this array.
    $current_options = $element['#default_value'];

    if (!$element['#civicrm_live_options']) {
      // $all_options is an array of [value => civi_label] listed in the order defined in civicrm.
      // Options disabed in civi are absent from this array, but it includes options disabled in the webform.
      $all_options = static::getFieldOptions($element['#form_key'], $data);

      // build the $field_options array using the order of $current_options, using the labels specified in the webform.
      foreach ($current_options as $key => $option) {
        $field_options[$key] = $all_options[$key];
      }

      // Add to the $field_options array any options that are disabled in the webform.
      // The order of the disabled options cannot be changed, and they will always
      // appear below the enabled options.
      foreach ($all_options as $key => $option) {
        if (!isset($field_options[$key])) {
          $field_options[$key] = $all_options[$key];
        }
      }
    } else { // static options
      $field_options = static::getFieldOptions($element['#form_key'], $data);
    }

    foreach ($field_options as $key => $option) {
      $row_key = 'civicrm_option_' . $key;
      $element['options'][$row_key]['#attributes']['class'][] = 'draggable';
      $element['options'][$row_key]['#weight'] = $weight;

      $element['options'][$row_key]['item'] = [
        '#plain_text' => $option,
      ];
      $element['options'][$row_key]['enabled'] = [
        '#type' => 'checkbox',
        '#title' => t('Enable @item', ['@item' => $option]),
        '#title_display' => 'invisible',
        '#default_value' => !empty($current_options[$key]),
        '#access' => !$element['#civicrm_live_options'],
      ];
      $element['options'][$row_key]['label'] = [
        '#type' => 'textfield',
        '#title' => t('Label for @item', ['@item' => $option]),
        '#title_display' => 'invisible',
        '#default_value' => !empty($current_options[$key]) ?  $current_options[$key] : $option,
        '#access' => !$element['#civicrm_live_options'],
      ];
      $element['options'][$row_key]['default_option'] = [
        '#type' => 'radio',
        '#title' => t('Mark @item as the default value', ['@item' => $option]),
        '#title_display' => 'invisible',
        '#default_value' => $element['#default_option'] == $key ? $key : '',
        '#parents' => array_merge($element['#parents'], ['default']),
        '#return_value' => $key,
      ];
      // Avoid 0 value to be selected as default. The patch from https://www.drupal.org/project/drupal/issues/1381140
      // renders 0 as the default option due to some casting equation check in preRenderRadio() function.
      // Pay later holds the value 0 and is always loaded as default on the edit element page.
      // Setting false for the #value key mitigates this problem.
      // https://www.drupal.org/project/drupal/issues/2908602 is an open ticket on drupal which looks similar.
      if ($key === 0 && $element['#default_option'] != $key) {
        $element['options'][$row_key]['default_option']['#value'] = FALSE;
      }
      $element['options'][$row_key]['weight'] = [
        '#type' => 'weight',
        '#title' => t('Weight for @option', ['@option' => $option]),
        '#title_display' => 'invisible',
        // @todo support these values.
        '#default_value' => $weight,
        '#attributes' => ['class' => ['weight']],
        '#access' => !$element['#civicrm_live_options'],

        // delta theoretically should control the number of items in the weight dropdown for each option, but
        // in reality that weight range seems to be fixed at -10 to +10. When there are more than 10 options present,
        // the weight dropdown therefore cannot be used to move an option below the 10th spot. In addition,
        // a bug related to this fixed -10 to +10 range prevents dragging options below the 22nd spot.
        // Therefore, when there are more than 10 options present, it's desireable to switch from a weight
        // listbox to an integer edit box. This is accomplished by setting
        // delta to a value greater than Drupal::config('system.site')->get('weight_select_max') (default value 100)
        // See Drupal\Core\Render\Element\Weight::processWeight()
        // Other than that threshold, the value specified here for delta is not significent.
        '#delta' => !$element['#civicrm_live_options'] && sizeof($all_options) > 10 ? '101' : "10",
      ];
      $weight++;
    }
    $element['#attached']['library'][] = 'webform_civicrm/civicrmoptions';
    return $element;
  }

  /**
   * Validates webform options element.
   */
  public static function validateSelectOptions(&$element, FormStateInterface $form_state, &$complete_form) {
    if ($element['#civicrm_live_options']) {
      $webform = $form_state->getFormObject()->getWebform();
      $data = $webform->getHandler('webform_civicrm')->getConfiguration()['settings']['data'] ?? [];
      $options_value = self::getFieldOptions($element['#form_key'], $data);
    }
    else {
      $raw_values = $form_state->getValue($element['options']['#parents']);
      uasort($raw_values, '\Drupal\Component\Utility\SortArray::sortByWeightElement');

      $options_value = [];
      foreach ($raw_values as $raw_key => $raw_value) {
        if (!empty($raw_value['enabled'])) {
          $new_key = str_replace('civicrm_option_', '', $raw_key);
          $options_value[$new_key] = $raw_value['label'];
        }
      }
    }

    $element['#default_option'] = $form_state->getValue(['properties', 'options', 'default']);
    $element['#value'] = $options_value;
    $form_state->setValueForElement($element, $options_value);
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc