You are here

class CourseController in Course 3.x

Same name and namespace in other branches
  1. 8.3 src/Controller/CourseController.php \Drupal\course\Controller\CourseController
  2. 8.2 src/Controller/CourseController.php \Drupal\course\Controller\CourseController

Hierarchy

Expanded class hierarchy of CourseController

File

src/Controller/CourseController.php, line 17

Namespace

Drupal\course\Controller
View source
class CourseController extends EntityController {

  /**
   * Access callback for completion page.
   */
  function completionAccess(Course $course) {
    $account = \Drupal::currentUser();
    return AccessResult::allowedIf($course
      ->isEnrolled($account));
  }

  /**
   * Render a landing page for course completion.
   *
   * @param Course $course
   *
   * @return array
   *   Render array for the completion landing page.
   */
  function renderComplete(Course $course) {
    $account = \Drupal::currentUser();

    // User's course record.
    $course_enrollment = $course
      ->getEnrollment($account);

    // Render array.
    $page = array();

    // Links.
    $links = array();
    $url = $course
      ->getUrl();
    $url
      ->setOption('title', t('Return to the course to view course details and material.'));
    $links['course'] = Link::fromTextAndUrl(t('Return to course'), $url);
    if ($course_enrollment
      ->isComplete()) {

      // Allow modules to add links to the course completion landing page, such as
      // post-course actions.
      Drupal::moduleHandler()
        ->alter('course_outline_completion_links', $links, $course, $account);
    }
    else {
      Drupal::moduleHandler()
        ->alter('course_outline_incomplete_links', $links, $course, $account);
    }
    $page['#title'] = $course_enrollment
      ->isComplete() ? t('Course complete') : t('Remaining requirements');
    $objects = $course
      ->getObjects();
    $items = array();
    foreach ($objects as $courseObject) {
      if ($courseObject
        ->access('see')) {

        // Find required course objects the user has not yet completed.
        $req = $courseObject
          ->getFulfillment($account);
        $status_css = $req
          ->isComplete() ? 'complete' : 'incomplete';
        $status_img = $req
          ->isComplete() ? 'core/misc/icons/73b355/check.svg' : ($req
          ->getCourseObject()
          ->isRequired() ? 'core/misc/icons/e32700/error.svg' : 'core/misc/icons/e29700/warning.svg');
        $status_class = 'course-complete-item-' . $status_img;
        $status_optional = ' (' . (!$req
          ->getCourseObject()
          ->isRequired() ? t('optional') : t('required')) . ')';
        if ($courseObject
          ->access('take')) {
          $link = Link::fromTextAndUrl($req
            ->getCourseObject()
            ->getTitle(), $courseObject
            ->getUrl())
            ->toString();
        }
        else {
          $link = $req
            ->getCourseObject()
            ->getTitle();
        }
        $items[] = array(
          'data' => array(
            array(
              'data' => [
                '#theme' => 'image',
                '#uri' => $status_img,
                '#alt' => $status_css,
              ],
              'width' => 20,
              'class' => array(
                'course-complete-item-status',
              ),
            ),
            array(
              'data' => [
                '#markup' => $link . $status_optional . '<br/>' . $req
                  ->getCourseObject()
                  ->getStatus(),
              ],
              'class' => array(
                'course-complete-item-title',
              ),
            ),
          ),
          'class' => array(
            $status_class,
          ),
        );
      }
    }
    if ($course_enrollment
      ->isComplete()) {
      $message = t('You have completed the course. Use the links below to review the course content.');
    }
    else {
      $message = t('This course is not complete. Use the links below to access the remaining course content.');
    }
    $page['course_header'] = array(
      '#type' => 'item',
      '#title' => t('Thank you for participating in this course.'),
      '#description' => $message,
      '#description_display' => TRUE,
      '#weight' => 1,
    );
    $page['course_completion_requirements'] = array(
      '#theme' => 'table',
      '#header' => NULL,
      '#rows' => $items,
      '#weight' => 3,
      '#attributes' => array(
        'class' => array(
          'course-complete-items',
        ),
      ),
    );
    foreach ($links as $key => $link) {
      $element = array(
        '#title' => $link
          ->toString(),
        '#description' => $link
          ->getUrl()
          ->getOption('title'),
        '#type' => 'item',
        '#description_display' => TRUE,
      );
      $page['course_links'][$key] = $element;
    }
    $page['course_links']['#weight'] = 2;
    $page['#cache']['max-age'] = 0;
    return $page;
  }

  /**
   * Take a course.
   *
   * If allowed to enroll:
   *  - If the user hasn't answered enrollment questions, make them fill it out.
   *
   * If enrolled:
   *  - If the user hasn't answered enrollment questions, make them fill it out.
   *  - Enroll the user.
   *  - Fire the outline handler.
   *
   * If not enrolled:
   * - Show access blocker.
   */
  public function renderTake(Course $course) {
    $account = Drupal::currentUser();
    $enroll_access = $course
      ->access('enroll', $account, TRUE);
    $enrollment = $course
      ->getEnrollment($account);

    /* @var $enrollment Drupal\course\Entity\CourseEnrollment */
    if ($enroll_access
      ->isAllowed() && (!$enrollment || $enrollment
      ->get('timestamp')
      ->isEmpty())) {

      // User can enroll in this course and user is not enrolled. Check for
      // enrollment fields or enroll the user.
      $instances = Drupal::service('entity_field.manager')
        ->getFieldDefinitions('course_enrollment', $course
        ->get('enrollment_type')
        ->getString());
      foreach ($instances as $field_name => $field) {
        if (is_a($field, FieldConfig::class)) {

          /* @var $field Drupal\field\Entity\FieldConfig */
          if ($field
            ->getThirdPartySetting('course', 'show_field')) {

            // At least one field must be shown when enrolling. Display the user
            // enrollment form.
            if (!$enrollment) {

              // Create a new enrollment, show them the form.
              $enrollment = CourseEnrollment::create([
                'cid' => $course
                  ->id(),
                'uid' => $account
                  ->id(),
                'type' => $course
                  ->get('enrollment_type')
                  ->getString(),
                'timestamp' => \Drupal::time()
                  ->getRequestTime(),
                'enrollmenttype' => 'self',
              ]);
            }
            $redirect_url = Url::fromRoute('course.take', [
              'course' => $course
                ->id(),
            ]);
            $form = \Drupal::service('entity.form_builder')
              ->getForm($enrollment, 'default', [
              'redirect' => $redirect_url,
            ]);
            return $form;
          }
        }
      }

      // No fields to show. Check for enrollment. If it does not exist, create it.
      if (empty($enrollment)) {
        $enrollment = CourseEnrollment::create(array(
          'cid' => $course
            ->id(),
          'uid' => $account
            ->id(),
          'type' => $course->enrollment_type
            ->getString(),
          'enrollmenttype' => 'self',
        ));
        $enrollment
          ->save();
      }
    }
    $take_access = $course
      ->access('take', $account, TRUE);
    if ($take_access
      ->isAllowed()) {

      // User has access to take this course.
      if ($enrollment
        ->get('timestamp')
        ->isEmpty()) {

        // If user hasn't started course, mark start of enrollment.
        $enrollment
          ->set('timestamp', \Drupal::time()
          ->getRequestTime())
          ->save();
        \Drupal::messenger()
          ->addStatus(t('Your enrollment in this course has been recorded.'));
      }

      // Display the configured outline handler output.

      /* @var $pluginManager CourseOutlinePluginManager */
      $pluginManager = Drupal::service('plugin.manager.course.outline');

      /* @var $outlinePlugin CourseOutlinePluginBase */
      $outlinePlugin = $pluginManager
        ->createInstance($course
        ->get('outline')
        ->getString());
      $outline = $outlinePlugin
        ->render($course, $account);
      if (!$outline) {
        $outline['#markup'] = t('No learning objects are available this time.');
      }

      // Set page title to title of this course.
      $outline['#title'] = $course
        ->get('title')
        ->getString();
      $outline['#cache']['max-age'] = 0;
      return $outline;
    }
    else {
      $message = $take_access
        ->getReason();
      if (!$message) {
        $message = t('Sorry, you do not have access to take this course.');
      }
      return [
        '#markup' => '<h2>Access denied</h2>' . $take_access
          ->getReason(),
      ];
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CourseController::completionAccess function Access callback for completion page.
CourseController::renderComplete function Render a landing page for course completion.
CourseController::renderTake public function Take a course.
EntityController::$entityRepository protected property The entity repository.
EntityController::$entityTypeBundleInfo protected property The entity type bundle info.
EntityController::$entityTypeManager protected property The entity type manager.
EntityController::$renderer protected property The renderer.
EntityController::addBundleTitle public function Provides a generic add title callback for entities with bundles.
EntityController::addPage public function Displays add links for the available bundles.
EntityController::addTitle public function Provides a generic add title callback for an entity type.
EntityController::create public static function Instantiates a new instance of this class. Overrides ContainerInjectionInterface::create
EntityController::deleteTitle public function Provides a generic delete title callback.
EntityController::doGetEntity protected function Determines the entity.
EntityController::editTitle public function Provides a generic edit title callback.
EntityController::loadBundleDescriptions protected function Expands the bundle information with descriptions, if known.
EntityController::redirect protected function Returns a redirect response object for the specified route.
EntityController::title public function Provides a generic title callback for a single entity.
EntityController::__construct public function Constructs a new EntityController.
StringTranslationTrait::$stringTranslation protected property The string translation service. 4
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.