You are here

public function AbjsTestForm::buildForm in A/B Test JS 8

Same name and namespace in other branches
  1. 2.0.x src/Form/AbjsTestForm.php \Drupal\abjs\Form\AbjsTestForm::buildForm()

Building the form.

Parameters

array $form: The form.

\Drupal\Core\Form\FormStateInterface $form_state: The state of forms.

int $tid: The ID of the item.

Overrides FormInterface::buildForm

File

src/Form/AbjsTestForm.php, line 65

Class

AbjsTestForm
Class for build form test.

Namespace

Drupal\abjs\Form

Code

public function buildForm(array $form, FormStateInterface $form_state, $tid = NULL) {
  $form = [];
  $test_name_default = "";
  $test_active_default = 0;
  if (!empty($tid)) {

    // Retrieve the test to prefill the edit form.
    $test_result = $this->database
      ->query('SELECT name, active FROM {abjs_test} WHERE tid = :tid', [
      ':tid' => $tid,
    ]);
    $test = $test_result
      ->fetchObject();
    if (empty($test)) {
      $this
        ->messenger()
        ->addMessage($this
        ->t('The requested test does not exist.'), 'error');
      return $form;
    }
    $test_name_default = $test->name;
    $test_active_default = $test->active;
    $form['tid'] = [
      '#type' => 'value',
      '#value' => $tid,
    ];
  }

  // Because we have many fields with the same values, we have to set
  // #tree to be able to access them.
  $form['#tree'] = TRUE;
  $form['name'] = [
    '#type' => 'textfield',
    '#title' => $this
      ->t('Test Name'),
    '#default_value' => $test_name_default,
    '#size' => 30,
    '#maxlength' => 50,
    '#required' => TRUE,
  ];

  // Make select list of conditions.
  $conditions = $this->database
    ->query("SELECT cid, name FROM {abjs_condition} ORDER BY cid ASC, created DESC");
  $options_array = [
    0 => $this
      ->t('Select Condition'),
  ];
  foreach ($conditions as $condition) {
    $options_array[$condition->cid] = $condition->name . ' (c_' . $condition->cid . ')';
  }

  // Group conditions together, and allow for adding and removing conditions
  // via AJAX incide this fieldset.
  $form['conditions_fieldset'] = [
    '#type' => 'fieldset',
    '#title' => $this
      ->t('Conditions'),
    // Set up the wrapper so that AJAX will be able to replace the fieldset.
    '#prefix' => '<div id="conditions-fieldset-wrapper">',
    '#suffix' => '</div>',
    '#description' => $this
      ->t('Select Conditions for which the test will apply. All conditions must must be satisfied for the test to apply'),
  ];
  $existing_conditions_count = 0;
  if (!$form_state
    ->has('num_conditions')) {

    // On initial load, get the number of condition select fields (1 for add
    // form, query the number for edit form).
    $form_state
      ->set('num_conditions', 1);
    if (!empty($tid)) {
      $existing_conditions = $this->database
        ->query("SELECT cid FROM {abjs_test_condition} WHERE tid = :tid", [
        ':tid' => $tid,
      ])
        ->fetchAll();
      if (!empty($existing_conditions)) {
        $existing_conditions_count = count($existing_conditions);
        $form_state
          ->set('num_conditions', $existing_conditions_count);
      }
    }
  }

  // Prefill all the condition select fields that exist.
  for ($i = 0; $i < $existing_conditions_count; $i++) {
    $form['conditions_fieldset']['conditions'][$i] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Select Condition'),
      '#options' => $options_array,
      '#default_value' => $existing_conditions[$i]->cid,
      '#required' => TRUE,
    ];
  }

  // Add number of sesgment fields determined by use of Ajax Add and
  // remove buttons.
  for ($i = $existing_conditions_count; $i < $form_state
    ->get('num_conditions'); $i++) {
    $form['conditions_fieldset']['conditions'][$i] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Select Condition'),
      '#options' => $options_array,
      '#default_value' => 0,
      '#required' => TRUE,
    ];
  }

  // Ajax add button.
  $form['conditions_fieldset']['add_condition'] = [
    '#type' => 'submit',
    '#value' => $this
      ->t('Add'),
    '#name' => 'add-condition',
    '#submit' => [
      '::abjsAjaxAddCondition',
    ],
    '#ajax' => [
      'callback' => '::abjsAjaxConditionsCallback',
      'wrapper' => 'conditions-fieldset-wrapper',
    ],
    '#limit_validation_errors' => [],
  ];

  // Ajax Remove button.
  if ($form_state
    ->get('num_conditions') > 1) {
    $form['conditions_fieldset']['remove_condition'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Remove'),
      '#name' => 'remove-condition',
      '#submit' => [
        '::abjsAjaxRemoveCondition',
      ],
      '#ajax' => [
        'callback' => '::abjsAjaxConditionsCallback',
        'wrapper' => 'conditions-fieldset-wrapper',
      ],
      '#limit_validation_errors' => [],
    ];
  }

  // Now do the same for experiences.
  // Make select list of experiences.
  $experiences = $this->database
    ->query("SELECT eid, name FROM {abjs_experience} ORDER BY changed DESC, created DESC");
  $options_array = [
    0 => $this
      ->t('Select Experience'),
  ];
  foreach ($experiences as $experience) {
    $options_array[$experience->eid] = $experience->name . ' (e_' . $experience->eid . ')';
  }

  // Group experiences together, and allow for adding and removing experiences
  // via AJAX incide this fieldset.
  $form['experiences_fieldset'] = [
    '#type' => 'fieldset',
    '#title' => $this
      ->t('Experiences'),
    // Set up the wrapper so that AJAX will be able to replace the fieldset.
    '#prefix' => '<div id="experiences-fieldset-wrapper">',
    '#suffix' => '</div>',
    '#description' => $this
      ->t('Select one or more Experiences for the test, and assign fractions to each Experience (e.g. 1/2, 1/3, 0, 1, 0.5, .95, etc...). You cannot use the same Experience ID twice in the same test, so you must duplicate an Experience to use it twice.'),
  ];
  $existing_experiences_count = 0;
  if (!$form_state
    ->has('num_experiences')) {

    // On initial load, get the number of experience select fields (1 for add
    // form, query the number for edit form).
    $form_state
      ->set('num_experiences', 1);
    if (!empty($tid)) {
      $existing_experiences = $this->database
        ->query("SELECT eid, fraction FROM {abjs_test_experience} WHERE tid = :tid", [
        ':tid' => $tid,
      ])
        ->fetchAll();
      if (!empty($existing_experiences)) {
        $existing_experiences_count = count($existing_experiences);
        $form_state
          ->set('num_experiences', $existing_experiences_count);
      }
    }
  }

  // Prefill all the experience select fields that exist, including fractions
  // for each experience.
  for ($i = 0; $i < $existing_experiences_count; $i++) {
    $form['experiences_fieldset']['experiences'][$i]['experience'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Experience %i', [
        '%i' => $i + 1,
      ]),
      '#options' => $options_array,
      '#default_value' => $existing_experiences[$i]->eid,
      '#required' => TRUE,
    ];
    $form['experiences_fieldset']['experiences'][$i]['fraction'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Experience %i Fraction', [
        '%i' => $i + 1,
      ]),
      '#default_value' => $existing_experiences[$i]->fraction,
      '#size' => 5,
      '#maxlength' => 10,
      '#required' => TRUE,
    ];
  }

  // Add number of experience fields determined by use of Ajax Add and remove
  // buttons.
  for ($i = $existing_experiences_count; $i < $form_state
    ->get('num_experiences'); $i++) {
    $form['experiences_fieldset']['experiences'][$i]['experience'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Experience %i', [
        '%i' => $i + 1,
      ]),
      '#options' => $options_array,
      '#default_value' => 0,
      '#required' => TRUE,
    ];
    $form['experiences_fieldset']['experiences'][$i]['fraction'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Experience %i Fraction', [
        '%i' => $i + 1,
      ]),
      '#default_value' => '',
      '#size' => 5,
      '#maxlength' => 10,
      '#required' => TRUE,
    ];
  }

  // Ajax add button.
  $form['experiences_fieldset']['add_experience'] = [
    '#type' => 'submit',
    '#value' => $this
      ->t('Add'),
    '#name' => 'add-experience',
    '#submit' => [
      '::abjsAjaxAddExperience',
    ],
    '#ajax' => [
      'callback' => '::abjsAjaxExperiencesCallback',
      'wrapper' => 'experiences-fieldset-wrapper',
    ],
    '#limit_validation_errors' => [],
  ];

  // Ajax Remove button.
  if ($form_state
    ->get('num_experiences') > 1) {
    $form['experiences_fieldset']['remove_experience'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Remove'),
      '#name' => 'remove-experience',
      '#submit' => [
        '::abjsAjaxRemoveExperience',
      ],
      '#ajax' => [
        'callback' => '::abjsAjaxExperiencesCallback',
        'wrapper' => 'experiences-fieldset-wrapper',
      ],
      '#limit_validation_errors' => [],
    ];
  }

  // Add selector for activating/deactivating test.
  $form['active'] = [
    '#type' => 'select',
    '#title' => $this
      ->t('Status'),
    '#options' => [
      0 => $this
        ->t('Inactive'),
      1 => $this
        ->t('Active'),
    ],
    '#default_value' => $test_active_default,
  ];

  // Save test.
  $form['actions']['save'] = [
    '#type' => 'submit',
    '#value' => $this
      ->t('Save'),
    '#weight' => 5,
    '#validate' => [
      '::validateTest',
    ],
    '#submit' => [
      '::saveTest',
    ],
    '#attributes' => [
      'class' => [
        "button button-action button--primary",
      ],
    ],
  ];

  // Cancel test and return to admin tests page.
  $form['actions']['cancel'] = [
    '#type' => 'submit',
    '#value' => $this
      ->t('Cancel'),
    '#weight' => 10,
    '#submit' => [
      '::cancelTest',
    ],
    '#limit_validation_errors' => [],
  ];

  // Delete test.
  if (!empty($tid)) {
    $form['actions']['delete'] = [
      '#type' => 'submit',
      '#value' => $this
        ->t('Delete'),
      '#weight' => 15,
      '#submit' => [
        '::deleteTest',
      ],
    ];
  }
  return $form;
}