social_course-8.x-2.11/src/Controller/CoursesController.php

src/Controller/CoursesController.php
<?php

namespace Drupal\social_course\Controller;

use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Routing\TrustedRedirectResponse;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Url;
use Drupal\group\Entity\GroupInterface;
use Drupal\node\NodeInterface;
use Drupal\social_course\Entity\CourseEnrollmentInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Response;

/**
 * Returns responses for Course general routes.
 */
class CoursesController extends ControllerBase {

  /**
   * The course wrapper.
   *
   * @var \Drupal\social_course\CourseWrapperInterface
   */
  protected $courseWrapper;

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    $instance = parent::create($container);
    $instance->courseWrapper = $container->get('social_course.course_wrapper');

    return $instance;
  }

  /**
   * Controller action.
   *
   * @return mixed
   *   Renderable drupal array.
   */
  public function content() {
    $content = [];
    $bundles = $this->courseWrapper->getAvailableBundles();

    foreach ($this->entityTypeManager()->getStorage('group_type')->loadMultiple() as $type) {
      if (in_array($type->id(), $bundles)) {
        $content[$type->id()] = $type;
      }
    }

    if (count($content) == 1) {
      $type = array_shift($content);
      return $this->redirect('entity.group.add_form', ['group_type' => $type->id()]);
    }

    return [
      '#theme' => 'course_add_list',
      '#content' => $content,
    ];
  }

  /**
   * Determines if user has access to course creation page.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Run access checks for this account.
   *
   * @return \Drupal\Core\Access\AccessResultInterface
   *   The access result.
   */
  public function access(AccountInterface $account) {
    $bundles = $this->courseWrapper->getAvailableBundles();

    foreach ($bundles as $bundle) {
      if ($account->hasPermission("create {$bundle} group")) {
        return AccessResult::allowed();
      }
    }

    return AccessResult::forbidden();
  }

  /**
   * Callback of "/group/{group}/section/{node}/start".
   */
  public function startSection(GroupInterface $group, NodeInterface $node) {
    // Get first material.
    $material = $node->get('field_course_section_content')->get(0)->entity;
    $material_redirect = $this->redirect('entity.node.canonical', [
      'node' => $material->id(),
    ]);

    $storage = $this->entityTypeManager()->getStorage('course_enrollment');

    $exists = $storage->getQuery()
      ->accessCheck(TRUE)
      ->condition('uid', $this->currentUser()->id())
      ->condition('sid', $node->id())
      ->execute();

    // If user has already started or finished section, we just redirect them
    // to the material instead of creating a new enrollment.
    if ($exists) {
      return $material_redirect;
    }

    // Join user to course.
    $enrollment = $storage->create([
      'gid' => $group->id(),
      'sid' => $node->id(),
      'mid' => $material->id(),
      'status' => CourseEnrollmentInterface::IN_PROGRESS,
    ]);
    $enrollment->save();

    $this->messenger()->addMessage($this->t('You have successfully enrolled'));

    $tags = $group->getCacheTags();
    $tags = Cache::mergeTags($tags, $node->getCacheTags());
    $tags = Cache::mergeTags($tags, $material->getCacheTags());
    Cache::invalidateTags($tags);

    return $material_redirect;
  }

  /**
   * Access callback function for "/group/{group}/section/{node}/start" page.
   */
  public function startSectionAccess(GroupInterface $group, NodeInterface $node) {
    $this->courseWrapper->setCourse($group);
    return $this->courseWrapper->sectionAccess($node, $this->currentUser(), 'start');
  }

  /**
   * Callback of "/group/{group}/section/{node}/next".
   */
  public function nextMaterial(GroupInterface $group, NodeInterface $node) {
    $storage = $this->entityTypeManager()->getStorage('course_enrollment');
    $field = $node->get('field_course_section_content');
    $this->courseWrapper->setCourse($group);
    $current_material = NULL;
    $next_material = NULL;
    $account = $this->currentUser();

    foreach ($field->getValue() as $key => $value) {
      $exists = $storage->getQuery()
        ->accessCheck(TRUE)
        ->condition('gid', $group->id())
        ->condition('sid', $node->id())
        ->condition('mid', $value['target_id'])
        ->condition('uid', $account->id())
        ->execute();

      if (!$exists) {
        $enrollment = $storage->create([
          'gid' => $group->id(),
          'sid' => $node->id(),
          'mid' => $value['target_id'],
          'status' => CourseEnrollmentInterface::IN_PROGRESS,
        ]);
        $enrollment->save();

        $next_material = $field->get($key)->entity;
        break;
      }
      elseif (!$current_material) {
        /** @var \Drupal\social_course\Entity\CourseEnrollment[] $course_enrollments */
        $course_enrollments = $storage->loadMultiple($exists);

        // For some reasons user can have more than one enrollment. So, here
        // we need to update status for all if the current attempt is finished.
        foreach ($course_enrollments as $enrollment) {
          // Set the correct status for all previous materials.
          if ($enrollment->getStatus() !== CourseEnrollmentInterface::FINISHED) {
            $enrollment->setStatus(CourseEnrollmentInterface::FINISHED);
            $enrollment->save();

            if ($field->get($key + 1)) {
              $current_material = $field->get($key)->entity;
              $next_material = $field->get($key + 1)->entity;
            }
          }
        }
      }
    }

    // Redirect after finishing course.
    if (!$group->get('field_course_redirect_url')->isEmpty()) {
      $uri = $group->get('field_course_redirect_url')->uri;
      $parsed_url = parse_url($uri);

      if (isset($parsed_url['host'])) {
        $response = new TrustedRedirectResponse($uri);
        $response->addCacheableDependency($uri);
      }
      else {
        try {
          $url = Url::fromUri($uri);
        }
        catch (\InvalidArgumentException $exception) {
          $url = Url::fromUserInput($uri);
        }
        $response = new RedirectResponse($url->toString());
      }
    }
    else {
      $response = new RedirectResponse($group->toUrl()->setAbsolute()->toString(), Response::HTTP_FOUND);
    }

    // Check if user has already seen last material.
    if (!$next_material) {
      $next_section = $this->courseWrapper->getSection($node, 1);

      if ($next_section) {
        $course_enrollment = $storage->loadByProperties([
          'gid' => $group->id(),
          'sid' => $next_section->id(),
          'uid' => $account->id(),
        ]);
        $course_enrollment = current($course_enrollment);
        $finish_section = !$course_enrollment || $course_enrollment->getStatus() !== CourseEnrollmentInterface::FINISHED;

        if ($finish_section) {
          $this->messenger()->addStatus($this->t('You have successfully finished the @title section', [
            '@title' => $node->label(),
          ]));
        }

        // Redirect to a specific page which set in section.
        $current_section = $this->courseWrapper->getSection($node, 0);
        if (!$this->courseWrapper->courseIsSequential() && !$current_section->get('field_course_section_redirect')->isEmpty()) {
          $uri = $current_section->get('field_course_section_redirect')->uri;
          $parsed_url = parse_url($uri);

          if (isset($parsed_url['host'])) {
            $response = new TrustedRedirectResponse($uri);
            $response->addCacheableDependency($uri);
          }
          else {
            try {
              $url = Url::fromUri($uri);
            }
            catch (\InvalidArgumentException $exception) {
              $url = Url::fromUserInput($uri);
            }
            $response = new RedirectResponse($url->toString());
          }
        }
        // Redirect to the next section when it exists and not marked as
        // completed.
        elseif ($finish_section) {
          // Cleanup related entity of "next section".
          $course_enrollment = $storage->loadByProperties([
            'gid' => $group->id(),
            'sid' => $next_section->id(),
            'uid' => $account->id(),
          ]);
          if ($course_enrollment) {
            $storage->delete($course_enrollment);
          }
          $response = self::nextMaterial($group, $next_section);
        }
        // Redirect to next step even if the next step was completed but current
        // material does not have a link of specific next material.
        else {
          $response = $this->redirect('entity.node.canonical', [
            'node' => $next_section->id(),
          ]);
        }

      }
    }
    else {
      $response = $this->redirect('entity.node.canonical', [
        'node' => $next_material->id(),
      ]);
    }

    $tags = $group->getCacheTags();
    $tags = Cache::mergeTags($tags, $node->getCacheTags());

    if ($next_material) {
      $tags = Cache::mergeTags($tags, $this->courseWrapper->getMaterial($next_material, -1)->getCacheTags());
    }

    Cache::invalidateTags($tags);

    return $response;
  }

  /**
   * Access callback of "/group/{group}/section/{node}/next" page.
   */
  public function nextMaterialAccess(GroupInterface $group, NodeInterface $node) {
    $bundles = $this->courseWrapper->getAvailableBundles();

    // Forbid if group is not a course.
    if (!in_array($group->bundle(), $bundles)) {
      return AccessResult::forbidden();
    }

    // Forbid if node is not a section.
    if ($node->bundle() != 'course_section') {
      return AccessResult::forbidden();
    }

    // Forbid if section does not contain materials.
    $field = $node->get('field_course_section_content');

    if ($field->isEmpty()) {
      return AccessResult::forbidden();
    }

    return AccessResult::allowed();
  }

  /**
   * Redirects users to their courses page.
   *
   * @return \Symfony\Component\HttpFoundation\RedirectResponse
   *   Returns a redirect to the courses of the currently logged in user.
   */
  public function redirectMyCourses(): RedirectResponse {
    return $this->redirect('view.courses_user.page', [
      'user' => $this->currentUser()->id(),
    ]);
  }

}

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

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