You are here

public function LearningPathStepsController::start 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::start()

Start the learning path.

This page will redirect the user to the first learning path content.

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

File

src/Controller/LearningPathStepsController.php, line 149

Class

LearningPathStepsController
Class LearningPathStepsController.

Namespace

Drupal\opigno_learning_path\Controller

Code

public function start(Group $group, $type = 'group') {

  // Create empty result attempt if current attempt doesn't exist.
  // Will be used to detect if user already started LP or not.
  $current_attempt = opigno_learning_path_started($group, \Drupal::currentUser());
  $this->source_type = $type;
  $this->group = $group;
  if (!$current_attempt) {
    $result = LPResult::createWithValues($group
      ->id(), \Drupal::currentUser()
      ->id(), FALSE, 0);
    $result
      ->save();
  }
  $user = $this
    ->currentUser();
  $uid = $user
    ->id();
  $gid = $group
    ->id();
  $is_owner = $uid === $group
    ->getOwnerId();
  $is_ajax = \Drupal::request()
    ->isXmlHttpRequest();

  // Load group steps.
  $steps = LearningPathContent::getAllStepsOnlyModules($gid, $uid);
  foreach ($steps as $step) {
    if (in_array($step['typology'], [
      'Meeting',
      'ILT',
    ])) {

      // If training starts with a mandatory live meeting
      // or instructor-led training, check requirements.
      $is_mandatory = $step['mandatory'] === 1;
      if ($step['typology'] === 'Meeting') {

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

        /** @var \Drupal\opigno_ilt\ILTInterface $entity */
        $entity = $this
          ->entityTypeManager()
          ->getStorage('opigno_ilt')
          ->load($step['id']);
        if (!$entity
          ->isMember($uid)) {
          $is_mandatory = FALSE;
        }
      }
      if ($is_mandatory) {
        $name = $step['name'];
        $required = $step['required score'];
        if ($required >= 0 || $step['typology'] == 'Meeting' && !$is_owner) {
          if ($step['best score'] < $required || OpignoGroupManagerController::mustBeVisitedMeeting($step, $group)) {
            $course_entity = OpignoGroupManagedContent::load($step['cid']);
            $course_content_type = $this->content_type_manager
              ->createInstance($course_entity
              ->getGroupContentTypeId());
            $current_step_url = $course_content_type
              ->getStartContentUrl($course_entity
              ->getEntityId(), $gid);
            return $this
              ->failedStep('none', $is_ajax, $this
              ->requiredStepMessage($name, $required, $current_step_url
              ->toString()));
          }
        }
        else {
          if ($step['attempts'] === 0) {
            return $this
              ->failedStep('none', $is_ajax, $this
              ->requiredStepMessage($name));
          }
        }
      }
    }
    else {
      break;
    }
  }

  // Skip live meetings and instructor-led trainings from the group steps.
  $steps = array_filter($steps, function ($step) {
    return !in_array($step['typology'], [
      'Meeting',
      'ILT',
    ]);
  });

  // Check that training is completed.
  $is_completed = (int) $this->database
    ->select('opigno_learning_path_achievements', 'a')
    ->fields('a')
    ->condition('uid', $user
    ->id())
    ->condition('gid', $group
    ->id())
    ->condition('status', 'completed')
    ->countQuery()
    ->execute()
    ->fetchField() > 0;
  if ($is_completed) {

    // Load steps from cache table.
    $results = $this->database
      ->select('opigno_learning_path_step_achievements', 'a')
      ->fields('a', [
      'id',
      'typology',
      'entity_id',
      'parent_id',
      'position',
    ])
      ->condition('uid', $user
      ->id())
      ->condition('gid', $group
      ->id())
      ->execute()
      ->fetchAllAssoc('id');
    if (!empty($results)) {

      // Check training structure.
      $is_valid = TRUE;
      $steps_mandatory = array_filter($steps, function ($step) {
        return $step['mandatory'];
      });
      foreach ($steps_mandatory as $step) {
        $filtered = array_filter($results, function ($result) use ($results, $step) {
          if (isset($step['parent'])) {
            $step_parent = $step['parent'];
            $result_parent = isset($results[$result->parent_id]) ? $results[$result->parent_id] : NULL;
            if (!isset($result_parent) || $result_parent->typology !== $step_parent['typology'] || (int) $result_parent->entity_id !== (int) $step_parent['id'] || (int) $result_parent->position !== (int) $step_parent['position']) {
              return FALSE;
            }
          }
          return $result->typology === $step['typology'] && (int) $result->entity_id === (int) $step['id'] && (int) $result->position === (int) $step['position'];
        });
        if (count($filtered) !== 1) {
          $is_valid = FALSE;
          break;
        }
      }

      // If training is changed.
      if (!$is_valid) {
        $form = $this
          ->formBuilder()
          ->getForm('Drupal\\opigno_learning_path\\Form\\DeleteAchievementsForm', $group);
        if ($is_ajax) {
          $redirect = $this
            ->redirectToHome('', TRUE);
          if ($redirect) {
            return $redirect;
          }
          else {
            return (new AjaxResponse())
              ->addCommand(new OpenModalDialogCommand('', $form));
          }
        }
        else {
          return $form;
        }
      }
    }
  }

  // Get training guided navigation option.
  $freeNavigation = !OpignoGroupManagerController::getGuidedNavigation($group);
  if ($freeNavigation) {
    $content = OpignoGroupManagedContent::getFirstStep($group
      ->id());
    if ($content
      ->getGroupContentTypeId() != 'ContentTypeCourse') {
      $content_type = $this->content_type_manager
        ->createInstance($content
        ->getGroupContentTypeId());
      $step_url = $content_type
        ->getStartContentUrl($content
        ->getEntityId(), $group
        ->id());
      if ($is_ajax) {
        return (new AjaxResponse())
          ->addCommand(new RedirectCommand($step_url
          ->toString()));
      }
      else {
        return $this
          ->redirect($step_url
          ->getRouteName(), $step_url
          ->getRouteParameters(), $step_url
          ->getOptions());
      }
    }
  }

  // Check if there is resumed step. If is - redirect.
  $step_resumed_cid = opigno_learning_path_resumed_step($steps);
  if ($step_resumed_cid) {
    $content = OpignoGroupManagedContent::load($step_resumed_cid);

    // Find and load the content type linked to this content.
    $content_type = $this->content_type_manager
      ->createInstance($content
      ->getGroupContentTypeId());
    $step_url = $content_type
      ->getStartContentUrl($content
      ->getEntityId(), $group
      ->id());

    // Before redirecting, keep the content ID in context.
    OpignoGroupContext::setCurrentContentId($step_resumed_cid);
    OpignoGroupContext::setGroupId($group
      ->id());

    // Finally, redirect the user to the first step.
    if ($is_ajax) {
      return (new AjaxResponse())
        ->addCommand(new RedirectCommand($step_url
        ->toString()));
    }
    else {
      return $this
        ->redirect($step_url
        ->getRouteName(), $step_url
        ->getRouteParameters(), $step_url
        ->getOptions());
    }
  }

  // Get the first step of the learning path. If no steps, show a message.
  $first_step = reset($steps);
  if ($first_step === FALSE) {
    return $this
      ->failedStep('no_first', $is_ajax);
  }

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

  // Find and load the content type linked to this content.
  $content_type = $this->content_type_manager
    ->createInstance($first_step
    ->getGroupContentTypeId());

  // Finally, get the "start" URL
  // If no URL, show a message.
  $step_url = $content_type
    ->getStartContentUrl($first_step
    ->getEntityId(), $group
    ->id());
  if (empty($step_url)) {
    return $this
      ->failedStep('no_url', $is_ajax);
  }

  // Before redirecting, keep the content ID in context.
  OpignoGroupContext::setCurrentContentId($first_step
    ->id());
  OpignoGroupContext::setGroupId($group
    ->id());

  // Finally, redirect the user to the first step.
  if ($is_ajax) {
    return (new AjaxResponse())
      ->addCommand(new RedirectCommand($step_url
      ->toString()));
  }
  else {
    return $this
      ->redirect($step_url
      ->getRouteName(), $step_url
      ->getRouteParameters(), $step_url
      ->getOptions());
  }
}