trinion_suo-1.0.x-dev/src/Form/TestForm.php
src/Form/TestForm.php
<?php
namespace Drupal\trinion_suo\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\node\Entity\Node;
use Drupal\user\Entity\User;
/**
* Provides a TrinionCourse form.
*/
class TestForm extends FormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'trinion_suo_test';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
if ($test = $this->getTest()) {
$step = $this->getStep($form_state);
$form['#quest_num'] = $step + 1;
$form['#quest_cnt'] = count($test->get('field_ts_questions'));
$question = $test->get('field_ts_questions')[$step]->entity;
if ($question) {
$form['question'] = [
'#type' => 'container',
'#attributes' => ['id' => 'test-container'],
];
$form['question']['finish'] = [
'#markup' => 'Вопрос ' . ($step + 1) . ' из ' . count($test->get('field_ts_questions')),
];
$q_type = $question->get('field_ts_question_type')->getString();
if ($q_type == 'radio' || $q_type == 'radios') {
$options = [];
$right_answers = [];
foreach ($question->get('field_ts_answers') as $item) {
$answer = $item->entity;
$options[$answer->id()] = $answer->label();
if ($answer->get('field_ts_right')->getString()) {
$right_answers[] = $answer->id();
}
}
$form_state->set('right_answers', $right_answers);
}
switch ($q_type) {
case 'radio':
$type = 'radios';
break;
case 'radios':
$type = 'checkboxes';
break;
case 'text':
$type = 'textfield';
break;
}
$form_state->set('q_type', $q_type);
$form['question']['quest'] = [
'#type' => $type,
'#title' => $question->label(),
'#options' => $options,
];
$form['question']['actions'] = [
'#type' => 'container',
'#attributes' => ['class' => ['test-actions']],
];
$form['question']['actions']['next'] = [
'#type' => 'submit',
'#value' => 'Далее',
'#submit' => ['::next'],
'#validate' => ['::nextValidate'],
'#ajax' => [
'wrapper' => 'test-container',
'callback' => '::nextCallback',
]
];
}
else {
$form['question']['finish'] = [
'#markup' => 'Вы успешно прошли тест «' . $test->label() . '»',
];
if ($uid = \Drupal::currentUser()->id()) {
$user = User::load($uid);
$user->field_ts_completed_lessons[] = $test->id();
$user->save();
}
if ($next = $this->getNextLesson($test)) {dump($next);
$url = \Drupal\Core\Url::fromRoute('entity.node.canonical', ['node' => $next])->toString();
$form['question']['finish']['#markup'] .= '<br><br>' . '<a href="' . $url . '">Следующий урок</a>';
}
}
}
return $form;
}
public function nextCallback(array &$form, FormStateInterface $form_state) {
return $form['question'];
}
public function next(array &$form, FormStateInterface $form_state) {
$step = $this->getStep($form_state);
$form_state->set('step', $step + 1);
$form_state->setRebuild();
}
public function nextValidate(array &$form, FormStateInterface $form_state) {
$error = FALSE;
$right_answers = $form_state->get('right_answers');
$answer = $form_state->getValue('quest');
$q_type = $form_state->get('q_type');
if ($q_type == 'radio' || $q_type == 'radios') {
if (is_array($answer)) {
foreach ($answer as $key => $val)
if ($val == 0)
unset($answer[$key]);
}
else {
$answer = [$answer];
}
sort($answer);
sort($right_answers);
if ($answer != $right_answers)
$error = TRUE;
}
if ($error)
$form_state->setError($form['question'], 'Вы не правильно ответили на вопрос');
}
public function getStep($form_state) {
$step = $form_state->get('step');
if (empty($step))
$step = 0;
return $step;
}
public function getTest() {
$node = \Drupal::routeMatch()->getParameter('node');
return $node->bundle() == 'test' ? $node : [];
}
public function getNextLesson($test) {
$next = FALSE;
$query = \Drupal::entityQuery('node')
->condition('type', ['urok_kursa', 'test'], 'IN')
->condition('field_ts_kategoriya_kursa', $test->get('field_ts_kategoriya_kursa')->getString())
->condition('field_ts_lesson_number', $test->get('field_ts_lesson_number')->getString() + 1);
$res = $query->accessCheck()->execute();
if (empty($res)) { // если это последний урок в теме, то беру первый урок из следующей темы
$query = \Drupal::entityQuery('taxonomy_term')
->condition('vid', 'course_categories')
->condition('weight', 8);
$term = $query->accessCheck()->execute();
if ($term) {
$query = \Drupal::entityQuery('node')
->condition('type', 'urok_kursa')
->condition('field_ts_kategoriya_kursa', reset($term))
->condition('field_ts_lesson_number', 1);
$res = $query->accessCheck()->execute();
$next = reset($res);
}
}
else
$next = reset($res);
return $next;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
}
}
