You are here

public function SalesforceMappingFieldsForm::buildForm in Salesforce Suite 8.3

Form constructor.

Parameters

array $form: An associative array containing the structure of the form.

\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.

Return value

array The form structure.

Overrides EntityForm::buildForm

File

modules/salesforce_mapping/src/Form/SalesforceMappingFieldsForm.php, line 19

Class

SalesforceMappingFieldsForm
Salesforce Mapping Fields Form.

Namespace

Drupal\salesforce_mapping\Form

Code

public function buildForm(array $form, FormStateInterface $form_state) {
  if (!$this
    ->ensureConnection('objectDescribe', $this->entity
    ->getSalesforceObjectType())) {
    return $form;
  }
  $form = parent::buildForm($form, $form_state);

  // Previously "Field Mapping" table on the map edit form.
  // @TODO add a header with Fieldmap Property information.
  // Add #entity property to expose it to our field plugin forms.
  $form['#entity'] = $this->entity;
  $form['#attached']['library'][] = 'salesforce/admin';

  // This needs to be loaded now as it can't be loaded via AJAX for the AC
  // enabled fields.
  $form['#attached']['library'][] = 'core/drupal.autocomplete';

  // For each field on the map, add a row to our table.
  $form['overview'] = [
    '#markup' => 'Field mapping overview goes here.',
  ];
  $form['key_wrapper'] = [
    '#title' => t('Upsert Key'),
    '#type' => 'details',
    '#open' => TRUE,
    '#description' => t('An Upsert Key can be assigned to map a Drupal property to a Salesforce External Identifier. If specified an UPSERT will be used to limit data duplication.'),
  ];
  $key_options = $this
    ->getUpsertKeyOptions();
  if (empty($key_options)) {
    $form['key_wrapper']['#description'] .= ' ' . t('To add an upsert key for @sobject_name, assign a field as an External Identifier in Salesforce.', [
      '@sobject_name' => $this->entity
        ->get('salesforce_object_type'),
    ]);
    $form['key_wrapper']['key'] = [
      '#type' => 'value',
      '#value' => '',
    ];
  }
  else {
    $form['key_wrapper']['key'] = [
      '#type' => 'select',
      '#title' => t('Upsert Key'),
      '#options' => $key_options,
      '#default_value' => $this->entity
        ->getKeyField(),
      '#empty_option' => t('(none)'),
      '#empty_value' => '',
    ];
    $form['key_wrapper']['always_upsert'] = [
      '#type' => 'checkbox',
      '#title' => t('Always Upsert'),
      '#default_value' => $this->entity
        ->get('always_upsert'),
      '#description' => t('If checked, always use "upsert" to push data to Salesforce. Otherwise, prefer a Salesforce ID if available. For example, given a user mapping with "email" set for upsert key, leave this checkbox off; otherwise, a new Salesforce record will be created whenever a user changes their email.'),
    ];
  }
  $form['field_mappings_wrapper'] = [
    '#title' => t('Mapped Fields'),
    '#type' => 'details',
    '#id' => 'edit-field-mappings-wrapper',
    '#open' => TRUE,
  ];
  $field_mappings_wrapper =& $form['field_mappings_wrapper'];

  // Check to see if we have enough information to allow mapping fields.  If
  // not, tell the user what is needed in order to have the field map show up.
  $field_mappings_wrapper['field_mappings'] = [
    '#tree' => TRUE,
    '#type' => 'container',
    // @TODO there's probably a better way to tie ajax callbacks to this element than by hard-coding an HTML DOM ID here.
    '#id' => 'edit-field-mappings',
    '#attributes' => [
      'class' => [
        'container-striped',
      ],
    ],
  ];
  $rows =& $field_mappings_wrapper['field_mappings'];
  $form['field_mappings_wrapper']['ajax_warning'] = [
    '#type' => 'container',
    '#attributes' => [
      'id' => 'edit-ajax-warning',
    ],
  ];
  $add_field_text = !empty($field_mappings) ? t('Add another field mapping') : t('Add a field mapping to get started');
  $form['buttons'] = [
    '#type' => 'container',
  ];
  $form['buttons']['field_type'] = [
    '#title' => t('Field Type'),
    '#type' => 'select',
    '#options' => $this
      ->getDrupalTypeOptions($this->entity),
    '#attributes' => [
      'id' => 'edit-mapping-add-field-type',
    ],
    '#empty_option' => $this
      ->t('- Select -'),
  ];
  $form['buttons']['add'] = [
    '#value' => $add_field_text,
    '#type' => 'submit',
    '#executes_submit_callback' => FALSE,
    '#limit_validation_errors' => [],
    '#ajax' => [
      'callback' => [
        $this,
        'fieldAddCallback',
      ],
      'wrapper' => 'edit-field-mappings-wrapper',
    ],
    '#states' => [
      'disabled' => [
        ':input#edit-mapping-add-field-type' => [
          'value' => '',
        ],
      ],
    ],
  ];
  $row_template = [
    '#type' => 'container',
    '#attributes' => [
      'class' => [
        'field_mapping_field',
        'row',
      ],
    ],
  ];

  // Add a row for each saved mapping.
  $zebra = 0;
  foreach ($this->entity
    ->getFieldMappings() as $field_plugin) {
    $row = $row_template;
    $row['#attributes']['class']['zebra'] = $zebra % 2 ? 'odd' : 'even';
    $rows[] = $row + $this
      ->getRow($field_plugin, $form, $form_state);
    $zebra++;
  }

  // Apply any changes from form_state to existing fields.
  $input = $form_state
    ->getUserInput();
  if (!empty($input['field_mappings'])) {
    for ($i = count($this->entity
      ->getFieldMappings()); $i < count($input['field_mappings']); $i++) {
      $row = $row_template;
      $row['#attributes']['class']['zebra'] = $zebra % 2 ? 'odd' : 'even';
      $field_plugin = $this->entity
        ->getFieldMapping($input['field_mappings'][$i]);
      $rows[] = $row + $this
        ->getRow($field_plugin, $form, $form_state);
      $zebra++;
    }
  }

  // @TODO input does not contain the clicked button, have to go to values for
  // that. This may change?
  // Add button was clicked. See if we have a field_type value -- it's
  // required. If not, take no action. #states is already used to prevent
  // users from adding without selecting field_type. If they've worked
  // around that, they're going to have problems.
  if (!empty($form_state
    ->getValues()) && $form_state
    ->getValue('add') == $form_state
    ->getValue('op') && !empty($input['field_type']) && $form_state
    ->getTriggeringElement()['#name'] != 'context_drupal_field_value') {
    $row = $row_template;
    $row['#attributes']['class']['zebra'] = $zebra % 2 ? 'odd' : 'even';
    $rows[] = $row + $this
      ->getRow(NULL, $form, $form_state);
    $zebra++;
  }

  // Retrieve and add the form actions array.
  $actions = $this
    ->actionsElement($form, $form_state);
  if (!empty($actions)) {
    $form['actions'] = $actions;
  }
  return $form;
}