You are here

public function CourseObject::access in Course 7

Same name and namespace in other branches
  1. 6 includes/course_object.core.inc \CourseObject::access()
  2. 7.2 includes/CourseObject.inc \CourseObject::access()

Access functionality for course objects.

Possible values for $op are 'see', 'view', 'take'.

"see" means see it in a course outline. For example, a conditional survey should not be seen in the course outline. A quiz at the end of the course, should show up, but the user must not be able to take it.

"view" means view and interact with the object, but nothing would be recorded. For example, accessing a quiz but not being able to submit responses.

"take" means interact with the object in a way that records data.

Subclasses may override this functionality.

3 calls to CourseObject::access()
CourseObject::buildContent in includes/CourseObject.inc
Builds a structured array representing the entity's content.
CourseObject::takeCourseObject in includes/CourseObject.inc
Take a course object.
CourseObjectNode::access in includes/CourseObjectNode.inc
Deny access to objects without content.
1 method overrides CourseObject::access()
CourseObjectNode::access in includes/CourseObjectNode.inc
Deny access to objects without content.

File

includes/CourseObject.inc, line 63

Class

CourseObject
Parent abstract base class of all course objects.

Code

public function access($op = 'view', $account = NULL) {
  ctools_include('plugins');
  $access = FALSE;
  if (!$account) {
    global $user;
    $account = $user;
  }
  if (!$this
    ->getOption('enabled') || $this
    ->getOption('hidden')) {

    // Object is disabled or hidden so it should never be visible.
    return FALSE;
  }
  switch ($op) {
    case 'see':

      // User can see this object in the outline.
      $access = TRUE;
      break;
    case 'take':
    case 'view':
      if (!$account->uid) {

        // Not logged in. Should never be accessible.
        return FALSE;
      }

      // Stock access: check for completion of previous object.
      // Get a copy of the course, so we can run setActive() without changing
      // the global course.
      $course = clone $this
        ->getCourse();
      $course
        ->setActive($this
        ->getId());
      $courseObjects = $course
        ->getObjects();

      // Deny object access to non-enrolled users or users who cannot take
      // this course.
      $result = course_access_course('take', $this
        ->getCourse()
        ->getNode(), $account);
      if (!course_enrollment_check($this
        ->getCourseNid(), $account->uid) || !$result['success']) {
        return FALSE;
      }
      else {
        if (reset($courseObjects)
          ->getId() == $this
          ->getId()) {

          // User is enrolled. Grant access if first object.
          $access = TRUE;
        }
      }
      if (!$course
        ->getPrev()) {

        // There wasn't a previous object.
        $access = TRUE;
      }
      elseif (!$course
        ->getPrev()
        ->isRequired() || $course
        ->getPrev()
        ->isSkippable()) {

        // Previous step was not required, or was skippable.
        $access = TRUE;

        // But we need to see if at least one required step was completed (or the start of the course).
        $objects = array_reverse($course
          ->getObjects());
        $check = FALSE;
        foreach ($objects as $object) {
          if (!$object
            ->getOption('enabled')) {

            // Do not check this object.
            // Note that hidden objects are still counted when doing
            // fulfillment checks.
            continue;
          }
          if ($check) {
            if ($object
              ->isRequired() && !$object
              ->isSkippable()) {

              // Object is required.
              if (!$object
                ->getFulfillment()
                ->isComplete()) {

                // Found a required object that was not complete.
                $access = FALSE;
                break;
              }
              else {

                // The last required object was completed.
                $access = TRUE;
                break;
              }
            }
          }
          if ($object
            ->getId() == $this
            ->getId()) {

            // We found the object we are trying to check access on.
            // Now we want to go backwards.
            $check = 1;
          }
        }
      }
      elseif ($course
        ->getPrev()
        ->getFulfillment()
        ->isComplete()) {

        // If last object was complete, and we are on the current object,
        // grant access.
        $access = TRUE;
      }
  }

  // Plugin access.
  foreach (ctools_get_plugins('course', 'course_object_access') as $key => $plugin) {
    $class = ctools_plugin_get_class($plugin, 'handler');
    $accessPlugin = new $class();
    $accessPlugin
      ->setCourseObject($this);
    $accessPlugin
      ->setType($key);

    // Run access check.
    $ret = $accessPlugin
      ->{$op}();
    if ($ret === FALSE) {

      // If previous access was granted, revoke it.
      $access = $ret;
    }
  }
  return $access;
}