You are here

public function LearningPathStepsController::nextStep in Opigno Learning path 8

Same name and namespace in other branches
  1. 3.x src/Controller/LearningPathStepsController.php \Drupal\opigno_learning_path\Controller\LearningPathStepsController::nextStep()

Redirect the user to the next step.

1 string reference to 'LearningPathStepsController::nextStep'
opigno_learning_path.routing.yml in ./opigno_learning_path.routing.yml
opigno_learning_path.routing.yml

File

src/Controller/LearningPathStepsController.php, line 386

Class

LearningPathStepsController
Class LearningPathStepsController.

Namespace

Drupal\opigno_learning_path\Controller

Code

public function nextStep(Group $group, OpignoGroupManagedContent $parent_content) {

  // Get the user score of the parent content.
  // First, get the content type object of the parent content.
  $content_type = $this->content_type_manager
    ->createInstance($parent_content
    ->getGroupContentTypeId());
  $user_score = $content_type
    ->getUserScore(\Drupal::currentUser()
    ->id(), $parent_content
    ->getEntityId());

  // If no no score and content is mandatory, show a message.
  if ($user_score === FALSE && $parent_content
    ->isMandatory()) {
    return $this
      ->failedStep('no_score');
  }
  $user = $this
    ->currentUser();
  $uid = $user
    ->id();
  $gid = $group
    ->id();
  $is_owner = $uid === $group
    ->getOwnerId();
  $cid = $parent_content
    ->id();

  // Get training guided navigation option.
  $freeNavigation = !OpignoGroupManagerController::getGuidedNavigation($group);

  // Load group steps.
  if ($freeNavigation) {

    // Get all steps for LP.
    $steps = LearningPathContent::getAllStepsOnlyModules($gid, $uid, TRUE);
  }
  else {
    $steps = LearningPathContent::getAllStepsOnlyModules($gid, $uid);
  }

  // Find current & next step.
  $count = count($steps);
  $current_step = NULL;
  $current_step_index = 0;
  for ($i = 0; $i < $count - 1; ++$i) {
    if ($steps[$i]['cid'] === $cid || !$freeNavigation && $steps[$i]['required score'] > $steps[$i]['best score']) {
      $current_step_index = $i;
      $current_step = $steps[$i];
      break;
    }
  }

  // Check mandatory step requirements.
  if (!$freeNavigation && isset($current_step) && $current_step['mandatory'] === 1) {
    $name = $current_step['name'];
    $required = $current_step['required score'];
    if ($required >= 0 || $current_step['typology'] == 'Meeting') {

      // Check if it's "skills module" with skills which user is already passed.
      if ($current_step['typology'] == 'Module') {
        $module = \Drupal::entityTypeManager()
          ->getStorage('opigno_module')
          ->load($current_step['id']);
        $moduleHandler = \Drupal::service('module_handler');
        if ($moduleHandler
          ->moduleExists('opigno_skills_system') && $module
          ->getSkillsActive()) {
          $current_step['current attempt score'] = $current_step['best score'];
        }
      }
      if ($current_step['mandatory'] && !$current_step['attempts'] || $current_step['mandatory'] && $current_step['attempts'] && empty($current_step['completed on']) || $current_step['best score'] < $required || OpignoGroupManagerController::mustBeVisitedMeeting($current_step, $group) && !$is_owner) {
        $course_entity = OpignoGroupManagedContent::load($current_step['cid']);
        $course_content_type = $this->content_type_manager
          ->createInstance($course_entity
          ->getGroupContentTypeId());
        $current_step_url = $course_content_type
          ->getStartContentUrl($course_entity
          ->getEntityId(), $gid);

        // Message if current step score less than required.
        $message = $this
          ->requiredStepMessage($name, $required, $current_step_url
          ->toString());
        $message = $this
          ->failedStep('none', FALSE, $message);

        // Check if current step is module and has activities
        // with manual evaluation which haven't been evaluated yet.
        if ($current_step['typology'] == 'Module') {
          $module = OpignoModule::load($current_step['id']);
          if (!empty($module)) {
            $activities = $module
              ->getModuleActivities();
            $activities = array_map(function ($activity) {
              return OpignoActivity::load($activity->id);
            }, $activities);
            $attempts = $module
              ->getModuleAttempts($user);
            if (!empty($attempts)) {

              // If "newest" score - get the last attempt,
              // else - get the best attempt.
              $attempt = $this
                ->getTargetAttempt($attempts, $module);
            }
            else {
              $attempt = NULL;
            }
            if ($activities) {
              foreach ($activities as $activity) {
                $answer = isset($attempt) ? $activity
                  ->getUserAnswer($module, $attempt, $user) : NULL;
                if ($answer && $activity
                  ->hasField('opigno_evaluation_method') && $activity
                  ->get('opigno_evaluation_method')->value && !$answer
                  ->isEvaluated()) {

                  // Message if current step is module and has activities
                  // with manual evaluation which haven't been evaluated yet.
                  $training_url = Url::fromRoute('entity.group.canonical', [
                    'group' => $group
                      ->id(),
                  ]);
                  $message = $this
                    ->t('One or several activities in module %step require a manual grading. You will be allowed to continue the training as soon as these activities have been graded and if you reach the minimum score %required.<br /><a href=":link">Back to training homepage.</a>', [
                    '%step' => $name,
                    '%required' => $required,
                    ':link' => $training_url
                      ->toString(),
                  ]);
                  $message = $this
                    ->failedStep('none', FALSE, $message);
                  break;
                }
              }
            }
          }
        }
        OpignoGroupContext::setGroupId($group
          ->id());
        OpignoGroupContext::setCurrentContentId($current_step['cid']);
        return $message;
      }
    }
  }
  if (isset($current_step['is last child']) && $current_step['is last child'] && isset($current_step['parent'])) {
    $course = $current_step['parent'];

    // Check mandatory course requirements.
    if ($course['mandatory'] === 1) {
      $name = $course['name'];
      $required = $course['required score'];
      if ($required >= 0) {
        if ($course['best score'] < $required) {
          $module_content = OpignoGroupManagedContent::getFirstStep($course['id']);
          $module_content_type = $this->content_type_manager
            ->createInstance($module_content
            ->getGroupContentTypeId());
          $module_url = $module_content_type
            ->getStartContentUrl($module_content
            ->getEntityId(), $gid);
          OpignoGroupContext::setGroupId($group
            ->id());
          OpignoGroupContext::setCurrentContentId($module_content
            ->id());
          return $this
            ->failedStep('none', FALSE, $this
            ->requiredStepMessage($name, $required, $module_url
            ->toString()));
        }
      }
      else {
        if ($course['attempts'] === 0) {
          $module_content = OpignoGroupManagedContent::getFirstStep($course['id']);
          OpignoGroupContext::setGroupId($group
            ->id());
          OpignoGroupContext::setCurrentContentId($module_content
            ->id());
          return $this
            ->failedStep('none', FALSE, $this
            ->requiredStepMessage($name));
        }
      }
    }
  }

  // Skip live meetings and instructor-led trainings.
  $skip_types = [];

  //['Meeting', 'ILT'];
  for ($next_step_index = $current_step_index + 1; $next_step_index < $count && in_array($steps[$next_step_index]['typology'], $skip_types); ++$next_step_index) {
    $next_step = $steps[$next_step_index];
    $is_mandatory = $next_step['mandatory'] === 1;
    if ($next_step['typology'] === 'Meeting') {

      /** @var \Drupal\opigno_moxtra\MeetingInterface $entity */
      $entity = $this
        ->entityTypeManager()
        ->getStorage('opigno_moxtra_meeting')
        ->load($next_step['id']);
      if (!$entity
        ->isMember($uid)) {
        $is_mandatory = FALSE;
      }
    }
    elseif ($next_step['typology'] === 'ILT') {

      /** @var \Drupal\opigno_ilt\ILTInterface $entity */
      $entity = $this
        ->entityTypeManager()
        ->getStorage('opigno_ilt')
        ->load($next_step['id']);
      if (!$entity
        ->isMember($uid)) {
        $is_mandatory = FALSE;
      }
    }
    if ($is_mandatory) {
      $name = $next_step['name'];
      $required = $next_step['required score'];

      // But if the live meeting or instructor-led training is
      // a mandatory and not passed,
      // block access to the next step.
      if ($required > 0) {
        if ($next_step['best score'] < $required) {
          return $this
            ->failedStep('none', FALSE, $this
            ->requiredStepMessage($name, $required));
        }
      }
      else {
        if ($next_step['attempts'] === 0) {
          return $this
            ->failedStep('none', FALSE, $this
            ->requiredStepMessage($name));
        }
      }
    }
  }
  $next_step = isset($steps[$next_step_index]) ? $steps[$next_step_index] : NULL;

  // If there is no next step, show a message.
  if ($next_step === NULL) {

    // Redirect to training home page.
    $this
      ->messenger()
      ->addWarning($this
      ->t('You reached the last content of that training.'));
    return $this
      ->redirect('entity.group.canonical', [
      'group' => $group
        ->id(),
    ]);
  }

  // Load next step entity.
  $next_step = OpignoGroupManagedContent::load($next_step['cid']);

  // Before redirect, change the content context.
  OpignoGroupContext::setCurrentContentId($next_step
    ->id());
  OpignoGroupContext::setGroupId($group
    ->id());

  // Finally, redirect the user to the next step URL.
  $next_step_content_type = $this->content_type_manager
    ->createInstance($next_step
    ->getGroupContentTypeId());
  $next_step_url = $next_step_content_type
    ->getStartContentUrl($next_step
    ->getEntityId(), $group
    ->id());
  return $this
    ->redirect($next_step_url
    ->getRouteName(), $next_step_url
    ->getRouteParameters(), $next_step_url
    ->getOptions());
}