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) {
  }

}

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

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