View source
<?php
namespace Drupal\abjs\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Component\Datetime\Time;
use Drupal\Core\Database\Connection;
class AbjsTestForm extends FormBase {
protected $time;
protected $database;
public function __construct(Connection $database, Time $time) {
$this->database = $database;
$this->time = $time;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('database'), $container
->get('datetime.time'));
}
public function getFormId() {
return 'abjs_test';
}
public function buildForm(array $form, FormStateInterface $form_state, $tid = NULL) {
$form = [];
$test_name_default = "";
$test_active_default = 0;
if (!empty($tid)) {
$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,
];
}
$form['#tree'] = TRUE;
$form['name'] = [
'#type' => 'textfield',
'#title' => $this
->t('Test Name'),
'#default_value' => $test_name_default,
'#size' => 30,
'#maxlength' => 50,
'#required' => TRUE,
];
$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 . ')';
}
$form['conditions_fieldset'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Conditions'),
'#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')) {
$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);
}
}
}
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,
];
}
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,
];
}
$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' => [],
];
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' => [],
];
}
$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 . ')';
}
$form['experiences_fieldset'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Experiences'),
'#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')) {
$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);
}
}
}
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,
];
}
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,
];
}
$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' => [],
];
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' => [],
];
}
$form['active'] = [
'#type' => 'select',
'#title' => $this
->t('Status'),
'#options' => [
0 => $this
->t('Inactive'),
1 => $this
->t('Active'),
],
'#default_value' => $test_active_default,
];
$form['actions']['save'] = [
'#type' => 'submit',
'#value' => $this
->t('Save'),
'#weight' => 5,
'#validate' => [
'::validateTest',
],
'#submit' => [
'::saveTest',
],
'#attributes' => [
'class' => [
"button button-action button--primary",
],
],
];
$form['actions']['cancel'] = [
'#type' => 'submit',
'#value' => $this
->t('Cancel'),
'#weight' => 10,
'#submit' => [
'::cancelTest',
],
'#limit_validation_errors' => [],
];
if (!empty($tid)) {
$form['actions']['delete'] = [
'#type' => 'submit',
'#value' => $this
->t('Delete'),
'#weight' => 15,
'#submit' => [
'::deleteTest',
],
];
}
return $form;
}
public function abjsAjaxAddCondition(array $form, FormStateInterface $form_state) {
$form_state
->set('num_conditions', $form_state
->get('num_conditions') + 1);
$form_state
->setRebuild();
}
public function abjsAjaxConditionsCallback(array $form, FormStateInterface $form_state) {
return $form['conditions_fieldset'];
}
public function abjsAjaxRemoveCondition(array $form, FormStateInterface $form_state) {
if ($form_state
->get('num_conditions') > 1) {
$form_state
->set('num_conditions', $form_state
->get('num_conditions') - 1);
}
$form_state
->setRebuild();
}
public function abjsAjaxAddExperience(array $form, FormStateInterface $form_state) {
$form_state
->set('num_experiences', $form_state
->get('num_experiences') + 1);
$form_state
->setRebuild();
}
public function abjsAjaxExperiencesCallback(array $form, FormStateInterface $form_state) {
return $form['experiences_fieldset'];
}
public function abjsAjaxRemoveExperience(array $form, FormStateInterface $form_state) {
if ($form_state
->get('num_experiences') > 1) {
$form_state
->set('num_experiences', $form_state
->get('num_experiences') - 1);
}
$form_state
->setRebuild();
}
public function submitForm(array &$form, FormStateInterface $form_state) {
}
public function validateTest(array &$form, FormStateInterface $form_state) {
for ($i = 0; $i < count($form_state
->getValue([
'experiences_fieldset',
'experiences',
])); $i++) {
if (!preg_match('#^[0-9./]+$#', $form_state
->getValue([
'experiences_fieldset',
'experiences',
])[$i]['fraction'])) {
$form_state
->setErrorByName("experiences_fieldset][experiences][{$i}][fraction", $this
->t('Invalid character used in Experience @i Fraction. Only numbers, decimals, and slashes are allowed. Other characters, including spaces, are not allowed.', [
'@i' => $i + 1,
]));
}
}
}
public function saveTest(array &$form, FormStateInterface $form_state) {
$user = $this
->currentUser();
if ($form_state
->hasValue('tid')) {
$tid = $form_state
->getValue('tid');
$this->database
->update('abjs_test')
->fields([
'name' => $form_state
->getValue('name'),
'active' => $form_state
->getValue('active'),
'changed' => $this->time
->getRequestTime(),
'changed_by' => $user
->id(),
])
->condition('tid', $tid, '=')
->execute();
$this->database
->delete('abjs_test_condition')
->condition('tid', $tid)
->execute();
$this->database
->delete('abjs_test_experience')
->condition('tid', $tid)
->execute();
}
else {
$tid = $this->database
->insert('abjs_test')
->fields([
'name' => $form_state
->getValue('name'),
'active' => $form_state
->getValue('active'),
'created' => $this->time
->getRequestTime(),
'created_by' => $user
->id(),
'changed' => $this->time
->getRequestTime(),
'changed_by' => $user
->id(),
])
->execute();
}
foreach ($form_state
->getValue([
'conditions_fieldset',
'conditions',
]) as $cid) {
if ($cid > 0) {
$this->database
->merge('abjs_test_condition')
->key([
'tid' => $tid,
'cid' => $cid,
])
->fields([
'tid' => $tid,
'cid' => $cid,
])
->execute();
}
}
foreach ($form_state
->getValue([
'experiences_fieldset',
'experiences',
]) as $experience) {
if (isset($experience['experience']) && $experience['experience'] > 0) {
$this->database
->merge('abjs_test_experience')
->key([
'tid' => $tid,
'eid' => $experience['experience'],
])
->fields([
'tid' => $tid,
'eid' => $experience['experience'],
'fraction' => $experience['fraction'],
])
->execute();
}
}
$msg = $form_state
->hasValue('tid') ? $this
->t("Successfully updated test") : $this
->t("Successfully saved new test");
$this
->messenger()
->addMessage($msg);
$form_state
->setRedirect('abjs.test_admin');
}
public function cancelTest(array &$form, FormStateInterface $form_state) {
$form_state
->setRedirect('abjs.test_admin');
}
public function deleteTest(array &$form, FormStateInterface $form_state) {
$form_state
->setRedirect('abjs.test_delete_confirm_form', [
'tid' => $form_state
->getValue('tid'),
]);
}
}