You are here

abstract class CourseObject in Course 6

Same name and namespace in other branches
  1. 7.2 includes/CourseObject.inc \CourseObject
  2. 7 includes/CourseObject.inc \CourseObject

Parent abstract base class of all course objects.

Represents a course object in the database.

Also holds a fulfillment record if a user is given.

Hierarchy

Expanded class hierarchy of CourseObject

File

includes/course_object.core.inc, line 10

View source
abstract class CourseObject extends CourseHandler {

  // Hold course.
  private $course = NULL;

  // Hold course object from database and the fulfillment object.
  private $courseObjectFulfillment = NULL;

  // Hold a user.
  protected $user = NULL;

  /**
   * Construct a course object from a database record.
   *
   * Use course_get_course_object to load an object when parameters are not
   * already known.
   *
   * @param array $config
   *   An object with object_type, module, and instance
   * @param object $account
   *   (optional) A user account object.
   * @param Course $course
   *   (optional) An instantiated Course object.
   */
  function __construct($config = array(), $account = NULL, Course $course = NULL) {
    $config = (array) $config;
    $this->serializedField = 'data';
    $this->handlerType = 'course_object';
    $this->primaryKey = 'coid';
    $this->table = 'course_outline';

    // Pass configuration to parent.
    parent::__construct($config);
    if (!$account) {
      global $user;
      $account = $user;
    }
    $this->user = $account;
    if ($course) {
      $this->course = $course;
    }
    $this->courseObjectFulfillment = new CourseObjectFulfillment($this, $account);
  }

  /**
   * Override navigation links.
   *
   * @return array
   *   An array of navigation links. Keyed values will override matching items
   *   in Course::getNavigation().
   */
  public function overrideNavigation() {
    return array();
  }

  /**
   * Specify whether fulfillment uses asynchronous polling.
   *
   * @return bool
   *   Whether this object uses polling. Defaults to FALSE.
   */
  public function hasPolling() {
    return FALSE;
  }

  /**
   * Overrides a course outline list item.
   *
   * @param array $item
   *   A course outline list item. The structure mirrors an array element from
   *   the $items param from theme_item_list().
   */
  public function overrideOutlineListItem(&$item) {
  }

  /**
   * 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.
   */
  public function access($op = 'view', $account = NULL) {
    ctools_include('plugins');
    $access = FALSE;
    if (!$account) {
      global $user;
      $account = $user;
    }

    // Stock access: check for completion of previous object.
    switch ($op) {
      case 'see':
        $access = !$this
          ->getOption('hidden') && $this
          ->getOption('enabled');
        break;
      case 'take':
        if (!$account->uid) {
          return FALSE;
        }
      case 'view':

        // 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();
        if ($courseObjects && $courseObjects[0]
          ->getId() == $this
          ->getId()) {

          // This is the first course object. The learner should be able to
          // access it. Also, check for enrollment. Since there are no other
          // checks (as in previous object completions) we do have to check this.
          $access = course_enrolment_check($this
            ->getCourseNid(), $account->uid);
        }
        if ($course
          ->getPrev() && !$course
          ->getPrev()
          ->isRequired()) {

          // Previous step was not required.
          $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 ($check) {
              if ($object
                ->isRequired()) {

                // 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;
            }
          }
        }
        if ($course
          ->getPrev() && $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', 'access') as $key => $plugin) {
      $class = ctools_plugin_get_class($plugin, 'handler');
      $accessPluginDefaults = array();
      if (isset($this->config['plugins']['access'][$key])) {
        $accessPluginDefaults = (array) $this->config['plugins']['access'][$key];
      }
      $accessPlugin = new $class();
      if ($accessPluginDefaults) {
        $accessPlugin
          ->setOptions($accessPluginDefaults);
      }
      $accessPlugin
        ->setCourseObject($this);

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

        // If previous access was granted, revoke it.
        $access = $ret;
      }
    }
    return $access;
  }
  public function isActive() {
    return $this
      ->getCourse()
      ->current()
      ->getId() == $this
      ->getId();
  }

  /**
   * Define configuration elements and their defaults.
   *
   * Extended classes should call parent::optionsDefinition first to get the
   * parent's configuration.
   */
  public function optionsDefinition() {
    $defaults = parent::optionsDefinition();
    $defaults += array(
      'uniqid' => NULL,
      'nid' => NULL,
      'title' => NULL,
      'enabled' => 1,
      'hidden' => 0,
      'required' => 1,
      'delete' => 0,
      'delete_instance' => 0,
      'grade_include' => 0,
      'instance' => NULL,
    );
    return $defaults;
  }

  /**
   * Default options form for all course objects.
   */
  public function optionsForm(&$form, &$form_state) {
    ctools_include('dependent');
    ctools_include('plugins');
    parent::optionsForm($form, $form_state);
    $config = $this
      ->getOptions();
    $form['header']['#value'] = t("<h2>Settings for %t</h2>", array(
      '%t' => $this
        ->getTitle(),
    ));
    $form['uniqid'] = array(
      '#type' => 'hidden',
      '#value' => arg(4),
    );
    $form['nid'] = array(
      '#type' => 'hidden',
      '#value' => arg(1),
    );
    $form['title'] = array(
      '#title' => 'Title',
      '#type' => 'textfield',
      '#size' => 100,
      '#default_value' => check_plain($config['title']),
    );
    $form['enabled'] = array(
      '#title' => 'Enabled',
      '#type' => 'checkbox',
      '#default_value' => $config['enabled'],
    );
    $form['hidden'] = array(
      '#title' => t('Visible in outline'),
      '#type' => 'checkbox',
      //'#description' => t('Hide this course object in the course outline. If this object is required, progress through the course will be blocked until this object is complete.'),
      '#default_value' => !$config['hidden'],
    );
    $form['required'] = array(
      '#title' => t('Completion required'),
      '#type' => 'checkbox',
      '#default_value' => $config['required'],
    );
    $form['delete'] = array(
      '#title' => t('Delete'),
      '#type' => 'checkbox',
      '#default_value' => $config['delete'],
    );

    // Only allow deletion of existing instances.
    if (!empty($config['instance'])) {
      $form['delete_instance'] = array(
        '#title' => t('Also delete related object instance(s)'),
        '#type' => 'checkbox',
        '#default_value' => $config['delete_instance'],
        '#process' => array(
          'ctools_dependent_process',
        ),
        '#dependency' => array(
          'edit-delete' => array(
            1,
          ),
        ),
      );

      // Check for multiple instances.
      $sql = "SELECT count(coid) FROM {course_outline} WHERE module = '%s' AND object_type = '%s' AND instance = '%s'";
      if (db_result(db_query($sql, $config['module'], $config['object_type'], $config['instance'])) > 1) {
        $form['delete_instance']['#description'] = t('<span class="error"><strong>WARNING</strong></span>: multiple course objects link to this instance. Deleting the instance might break the other course objects that use it.');
      }
    }
    if ($this
      ->isGraded()) {
      $form['grading'] = array(
        '#title' => 'Grading',
        '#type' => 'fieldset',
        '#description' => t('Settings for graded objects.'),
      );
      $form['grading']['grade_include'] = array(
        '#title' => 'Include in final course grade',
        '#description' => 'Include this grade result for calculation of the final course grade.<br/>Currently, only the last grade result per Course will be used.',
        '#default_value' => $config['grade_include'],
        '#type' => 'checkbox',
      );
    }

    // Bring in access plugin configuration.
    $form['plugins']['#tree'] = TRUE;
    $form['plugins']['#weight'] = 998;
    $form['plugins']['access']['#title'] = 'Access plugins';
    $form['plugins']['access']['#type'] = 'fieldset';
    foreach (ctools_get_plugins('course', 'access') as $key => $plugin) {
      $form['plugins']['access']['#tree'] = TRUE;
      $form['plugins']['access'][$key] = array(
        '#title' => $plugin['title'],
        '#type' => 'fieldset',
        '#tree' => TRUE,
        '#collapsible' => TRUE,
      );

      // Initialize access class.
      $class = ctools_plugin_get_class($plugin, 'handler');
      $courseAccess = new $class();
      if (!empty($config['plugins']['access'][$key])) {
        $courseAccess
          ->setOptions($config['plugins']['access'][$key]);
      }
      $courseAccess
        ->setCourseObject($this);

      // Add access plugin form to our form.
      $form['plugins']['access'][$key] += $courseAccess
        ->optionsForm();
    }

    // Update settings
    $form['update'] = array(
      '#value' => t('Update'),
      '#weight' => 999,
      '#type' => 'submit',
    );
  }
  public function optionsValidate(&$form, &$form_state) {

    // Pass validation to plugins.
    ctools_include('plugins');
    foreach (ctools_get_plugins('course', 'access') as $key => $plugin) {
      $values =& $form_state['values']['plugins']['access'][$key];
      $class = ctools_plugin_get_class($plugin, 'handler');
      $instance = new $class($values);
      $instance
        ->optionsValidate($form['plugins']['access'][$key], $form_state['values']['plugins']['access'][$key]);
    }
  }

  /**
   * Save object configs to cache.
   */
  public function optionsSubmit(&$form, &$form_state) {
    ctools_include('plugins');
    $uniqid = $this
      ->getId();
    $nid = $this
      ->getCourseNid();

    // Flip 'visible' so it behaves like 'hidden'.
    $form_state['values']['hidden'] = $form_state['values']['hidden'] != 1;

    // Object-specific settings
    foreach (array_keys($this
      ->getOptions()) as $key) {
      if (!is_null($form_state['values'][$key])) {
        $_SESSION['course'][$nid]['editing'][$uniqid][$key] = $form_state['values'][$key];
      }
    }

    // Save plugin info.
    foreach (ctools_get_plugins('course', 'access') as $key => $plugin) {
      $_SESSION['course'][$nid]['editing'][$uniqid]['plugins']['access'][$key] = $form_state['values']['plugins']['access'][$key];
    }

    // Update the options.
    $this
      ->setOptions($_SESSION['course'][$nid]['editing'][$uniqid]);

    // Perform ajax operations on the overview form, before overview submission.
    if ($form_state['ajax']) {
      $commands = array();

      // Set title.
      $title = '<div id="title-' . $uniqid . '">' . $form_state['values']['title'] . '</div>';
      $commands[] = ctools_ajax_command_replace("#title-{$uniqid}", $title);

      // Set summary.
      $html = '<div id="summary-' . $uniqid . '">' . $this
        ->renderOptionsSummary() . '</div>';
      $commands[] = ctools_ajax_command_replace("#summary-{$uniqid}", $html);

      // Deletion handling.
      if ($form_state['values']['delete']) {

        // Add `deleted` class to the row. An admin stylesheet is loaded from
        // theme_course_outline_overview_form().
        $commands[] = ctools_ajax_command_attr("#row-{$uniqid}", 'class', 'deleted');
      }
      $commands[] = ctools_modal_command_dismiss();
      ctools_ajax_render($commands);
    }
  }

  /**
   * Get core options summary.
   *
   * @return array
   *   An associative array of summary keys and values.
   */
  public function getOptionsSummary() {
    $summary = parent::getOptionsSummary();

    // Get options.
    $options = $this
      ->getOptions();

    // Get form for titles.
    $form = array();
    $this
      ->optionsForm($form, $form_state);

    // Add course object core options to summary individually, because there are
    // options we don't want to display, and others that require special logic.
    $uniqid = $options['uniqid'];

    // Enabled.
    if ($options['enabled']) {
      $summary['enabled'] = $form['enabled']['#title'];
    }
    else {
      $summary['enabled'] = '<span class="warning">' . t('Not enabled') . '</span>';
    }

    // Hidden.
    if (!$options['hidden']) {
      $summary['hidden'] = $form['hidden']['#title'];
    }
    else {
      $summary['hidden'] = '<span class="warning">' . t('Not visible in outline') . '</span>';
    }

    // Required.
    if ($options['required']) {
      $summary['required'] = $form['required']['#title'];
    }
    else {
      $summary['required'] = '<span class="warning">' . t('Completion not required') . '</span>';
    }

    // Instance edit link.
    $editUrl = $this
      ->getEditUrl();
    if (!empty($editUrl)) {
      $text = t('Edit instance');
      $summary['instance'] = l($text, $editUrl, array(
        'external' => TRUE,
        'query' => drupal_get_destination(),
      ));
    }
    elseif ($this
      ->isTemporary()) {
      $summary['instance'] = '<span class="warning">' . t('Save course to edit object') . '</span>';
    }

    // Required.
    if (!empty($options['delete'])) {
      $dest = "node/{$options['nid']}/course-object/nojs/{$uniqid}/restore";
      $text = t('Object will be removed from outline');
      $restore_text = t('Restore this object to the course outline.');
      if ($options['delete_instance']) {
        $text = t('Object will be removed from outline, and related instance(s) will be deleted');
        $restore_text = t('Restore this object and related instance(s) to the course outline.');
      }
      $restore = ctools_ajax_text_button(t('Restore'), $dest, $restore_text);
      $summary['delete'] = '<span class="error">' . $text . '</span>' . ' ' . $restore;
    }
    return $summary;
  }

  /**
   * Get all course object implementations of getOptionsSummary().
   */
  public function renderOptionsSummary() {
    ctools_include('plugins');
    $summary = $this
      ->getOptionsSummary();

    // Get summaries from plugins, and merge into the summary.
    foreach (ctools_get_plugins('course', 'access') as $key => $plugin) {

      // @todo how do we get these?
    }

    // @todo make this a themeable function.

    //return theme('course_object_summary');
    $rendered_summary = '';
    if (!empty($summary)) {
      $rendered_summary = $html = '<div class="description">' . theme('item_list', $summary) . '</div>';
    }
    return $rendered_summary;
  }

  /**
   * Get options, with session options having precedence.
   */
  public function getOptions() {
    $options = parent::getOptions();
    $sessionDefaults = array();
    if (isset($options['nid']) && isset($options['coid']) && isset($_SESSION['course'][$options['nid']]['editing'][$options['coid']])) {
      $sessionDefaults += array_filter((array) $_SESSION['course'][$options['nid']]['editing'][$options['coid']], array(
        $this,
        'optionFilter',
      ));
    }
    return array_merge($options, (array) $sessionDefaults);
  }
  private function optionFilter($a) {
    return !is_null($a);
  }

  /**
   * Take a course object.
   *
   * - Set the session of this course object being taken. This allows for
   *   non-node objects to be tracked.
   * - Delegate the course object take functionality
   *
   * @return mixed
   *   HTML content or a redirect.
   */
  public final function takeCourseObject() {
    $_SESSION['course']['active'] = $this
      ->getCourseNid();
    $_SESSION['course'][$this
      ->getCourseNid()]['taking']['active'] = $this
      ->getId();

    // Run access checks.
    if ($this
      ->access('take')) {

      // Grant access to external course object.
      $this
        ->grant();

      // Record start date.
      if (!$this
        ->getFulfillment()
        ->getOption('date_started')) {
        $this
          ->getFulfillment()
          ->setOption('date_started', time());
      }
    }
    else {

      // User can't access this object, revoke access.
      $this
        ->revoke();
      return FALSE;
    }

    // Save fulfillment record.
    $this
      ->getFulfillment()
      ->save();

    // If we're not displaying any content but we want to fire take() anyway, to
    // let the course object know we sent the user.
    $out = $this
      ->take();
    $url = $this
      ->getTakeUrl();
    switch ($this
      ->getTakeType()) {
      case 'iframe':
        return course_iframe($url);
      case 'popup':
        return "will popup {$url}";
      case 'content':
        return $out;
      case 'redirect':
      default:

        // This URL should have already been url()'d (it might be external).
        session_write_close();
        header("Location: {$url}");
        exit;
    }
  }

  /**
   * How should this course object be executed?
   *
   * - iframe: display an iframe with getTakeUrl() in it
   * - popup: launch getTakeUrl() in a popup
   * - modal: launch getTakeUrl() in a modal
   * - content: print the value from take() (or do whatever the module wants to
   *   do)
   */
  public function getTakeType() {
    return 'content';
  }

  /**
   *
   */
  public function take() {
    return 'This should be overridden by the module to return course content.';
  }

  /**
   * Return the URL to the course object router.
   */
  public function getUrl() {
    return 'node/' . $this
      ->getCourseNid() . '/course-object/' . $this
      ->getId();
  }

  /**
   * Get the URL to take this course object, if any.
   *
   * Outline handlers or subclasses should use getUrl().
   *
   * @return string
   */
  protected function getTakeUrl() {
  }

  /**
   * Get the URL to edit this course object, if any.
   *
   * @return string
   */
  public function getEditUrl() {
  }

  /**
   * Is this course object required for course completion?
   *
   * @return bool
   */
  public function isRequired() {
    return (bool) $this
      ->getOption('required');
  }

  /**
   * Is this object graded?
   *
   * Returning TRUE here will cause some more configurations to show on the
   * object's form.
   *
   * @return bool
   */
  function isGraded() {
    return FALSE;
  }

  /**
   * Get the user's status in this course object.
   *
   * This is how an object would notify the user why they cannot proceed to the
   * next step from the course outline. For example, if this was a quiz and
   * they failed, this should let them know.
   */
  public function getStatus() {
  }

  /**
   * Get this course object's fulfillment object.
   *
   * @return CourseObjectFulfillment
   */
  public function getFulfillment() {
    return $this->courseObjectFulfillment;
  }

  /**
   * Get the instance ID. This could be the external component ID, a Node ID...
   *
   * @return int
   */
  function getInstanceId() {
    return $this
      ->getOption('instance');
  }

  /**
   * Set this object's instance ID.
   *
   * @param mixed $id The external ID of this course object.
   */
  function setInstanceId($id) {
    return $this
      ->setOption('instance', $id);
  }

  /**
   * Get the course node ID this CourseObject belongs to.
   *
   * @return int
   */
  function getCourseNid() {
    return intval($this
      ->getOption('nid'));
  }

  /**
   * Set the Course for this CourseObject.
   *
   * @param Course|int $course
   *   A Course or node ID.
   *
   * @return CourseObject
   */
  public function setCourse($course) {
    if (is_numeric($course)) {
      $this
        ->setOption('nid', $course);
      $courseNode = node_load($course);
      $this->course = course_get_course($courseNode);
    }
    else {
      $this->course = $course;
      $this
        ->setOption('nid', $course
        ->getNode()->nid);
    }
    return $this;
  }

  /**
   * Get the Course that contains this CourseObject.
   *
   * @return Course
   */
  function getCourse() {
    if (!$this->course) {
      $nid = $this
        ->getCourseNid();
      if ($nid) {
        $this->course = new Course(node_load($nid), $this->user);
      }
    }
    return $this->course;
  }

  /**
   * Get the module that provides this course object.
   *
   * @return string
   */
  function getModule() {
    return $this
      ->getOption('module');
  }

  /**
   * Get the object component for this course object.
   *
   * @return string
   */
  function getComponent() {
    return $this
      ->getOption('object_type');
  }

  /**
   * Set the module that provides this course object.
   *
   * @return CourseObject
   */
  function setModule($module) {
    return $this
      ->setOption('module', $module);
  }

  /**
   * Set the object component for this course object.
   *
   * @return CourseObject
   */
  function setComponent($component) {
    return $this
      ->setOption('object_type', $component);
  }

  /**
   * Set the internal course object ID.
   *
   * @param int $coid
   *   ID of the course object.
   */
  function setId($coid) {
    return $this
      ->setOption('coid', $coid);
  }

  /**
   * Set the user fulfilling/creating this course object.
   */
  function setUser($user) {
    $this->user = $user;
  }

  /**
   * Creates a course object.
   *
   * For example, this would create the new node and return the node ID if this
   * was a CourseObjectNode.
   *
   * Do not confuse this with save(), which saves the course outline record for
   * tracking.
   *
   * Course objects should call setInstanceId() if this is a course object
   * that creates external resources.
   */
  public function create() {

    //$this->setInstanceId($id);
  }

  /**
   * Deletes a course object's external resources.
   *
   * For example, this would delete the associated node (if this was a
   * CourseObjectNode) and delete all other associated data.
   */
  public function delete() {

    //something_delete($this->getInstanceId());
  }
  function getTitle() {
    $object_info = course_get_handlers('object');

    // If title is not specified, set title from component.
    if (!$this
      ->getOption('title')) {

      // Get the component name from object info.
      $title = $object_info[$this
        ->getOption('module')][$this
        ->getOption('object_type')]['name'];
      $this
        ->setOption('title', $title);
    }
    return $this
      ->getOption('title');
  }

  /**
   * Give the course object a chance do asynchronous polling and set completion
   * on demand.
   *
   * Useful for external objects.
   */
  function poll() {
  }

  /**
   * Grant access to the external course object.
   *
   * For example, adding a user to an access control list.
   *
   * @see CourseObjectNode::grant()
   */
  function grant() {
  }

  /**
   * Revoke access to the external course object.
   *
   * For example, removing a user to an access control list.
   *
   * @todo This isn't called anywhere useful, yet.
   * @see CourseObjectNode::revoke()
   */
  function revoke() {
  }

  /**
   * Let the course object provide its own reports.
   *
   * @return array
   *   An array indexed by report key, containing 'title' which is the menu link
   *   in the course object reports.
   *
   * @see CourseObjectQuiz::getReports()
   */
  function getReports() {
    return array();
  }

  /**
   * Let the course object provide its own reports.
   *
   * @return array
   *   An array containing:
   *     - title: The title of this report as show on the page
   *     - content: Content to be displayed.
   *     - url: URL to be loaded in an iframe.
   *   Reports should return either 'content' or 'url'.
   *
   * @see CourseObjectQuiz::getReports()
   */
  function getReport($key) {
    return array();
  }
  function freeze() {
  }
  function thaw() {
  }

  /**
   * Returns an translated error message if this object has issues with cloning.
   *
   * @return mixed
   *   TRUE if cloning is supported, FALSE if cloning is not supported. A string
   *   if the object can clone but with caveats.
   */
  function getCloneAbility() {
    return t('The course object %object cannot be cloned. A new instance will be created.', array(
      '%object' => $this
        ->getTitle(),
    ));
  }

  /**
   * Let objects create their instances before saving the course object.
   */
  public function save() {

    // If there is no title, set it.
    $this
      ->getTitle();
    if ($ice = $this
      ->getOption('freeze')) {

      // Found frozen data.
      $this
        ->setInstanceId($this
        ->thaw($ice));
      $this
        ->setOption('freeze', NULL);
    }

    // If there is no instance ID, create one.
    if (!$this
      ->getInstanceId()) {
      $this
        ->create();
    }

    // Set the ID to NULL because this is a temporary course object being
    // created for the first time.
    if (strpos($this
      ->getId(), 'course_object_') !== FALSE) {
      $this
        ->setId(NULL);
    }
    return parent::save();
  }

  /**
   * Remove any records associated with this course object for the user.
   *
   * For example, deleting quiz results when a user is removed from the course.
   */
  function unEnroll() {
  }

  /**
   * Checks the temporary status of a course object.
   */
  function isTemporary() {
    return strpos($this
      ->getId(), 'course_object_') === 0;
  }

  /**
   * Return the number of occurances that can be in a course at the same time.
   * For example, the design of the Certificate module can only have 1 set of
   * mappings per node. The same goes for Course Credit. We may also want a
   * course object that can only be added twice (for example, a before/after
   * comparison).
   *
   * This method is static because we might have to call it without an object
   * being instantiated.
   */
  public static function getMaxOccurences() {
    return FALSE;
  }

}

Members

Namesort descending Modifiers Type Description Overrides
CourseHandler::$accessMessages private property
CourseHandler::$config protected property
CourseHandler::$handlerType public property
CourseHandler::$primaryKey public property
CourseHandler::$serializedField public property
CourseHandler::$table public property
CourseHandler::addOptions final public function Merge an array of options onto the existing options.
CourseHandler::getAccessMessages public function Get an array of access messages.
CourseHandler::getDatabaseFields protected function Return an array of database fields. This determines what fields should be serialized instead of stored.
CourseHandler::getId function
CourseHandler::getOption final public function Get an option stored in this CourseObject.
CourseHandler::getWarnings public function Return a list of warning strings about this handler. 1
CourseHandler::optionsMerge private function Merge arrays with replace, not append.
CourseHandler::setAccessMessage public function Set an access message to be displayed along with the course object when it is in the outline. For example, "This activity will open on XYZ" or "Please complete Step 1 to take this activity."
CourseHandler::setOption final public function Set an option for this handler.
CourseHandler::setOptions final public function Set this entire handler's options.
CourseObject::$course private property
CourseObject::$courseObjectFulfillment private property
CourseObject::$user protected property
CourseObject::access public function Access functionality for course objects.
CourseObject::create public function Creates a course object. 1
CourseObject::delete public function Deletes a course object's external resources. 1
CourseObject::freeze function 1
CourseObject::getCloneAbility function Returns an translated error message if this object has issues with cloning. 2
CourseObject::getComponent function Get the object component for this course object.
CourseObject::getCourse function Get the Course that contains this CourseObject.
CourseObject::getCourseNid function Get the course node ID this CourseObject belongs to.
CourseObject::getEditUrl public function Get the URL to edit this course object, if any. 1
CourseObject::getFulfillment public function Get this course object's fulfillment object.
CourseObject::getInstanceId function Get the instance ID. This could be the external component ID, a Node ID...
CourseObject::getMaxOccurences public static function Return the number of occurances that can be in a course at the same time. For example, the design of the Certificate module can only have 1 set of mappings per node. The same goes for Course Credit. We may also want a course object that can only be… 2
CourseObject::getModule function Get the module that provides this course object.
CourseObject::getOptions public function Get options, with session options having precedence. Overrides CourseHandler::getOptions
CourseObject::getOptionsSummary public function Get core options summary. Overrides CourseHandler::getOptionsSummary 2
CourseObject::getReport function Let the course object provide its own reports. 4
CourseObject::getReports function Let the course object provide its own reports. 4
CourseObject::getStatus public function Get the user's status in this course object. 1
CourseObject::getTakeType public function How should this course object be executed? 2
CourseObject::getTakeUrl protected function Get the URL to take this course object, if any. 1
CourseObject::getTitle function
CourseObject::getUrl public function Return the URL to the course object router.
CourseObject::grant function Grant access to the external course object. 1
CourseObject::hasPolling public function Specify whether fulfillment uses asynchronous polling. 2
CourseObject::isActive public function
CourseObject::isGraded function Is this object graded? 2
CourseObject::isRequired public function Is this course object required for course completion?
CourseObject::isTemporary function Checks the temporary status of a course object.
CourseObject::optionFilter private function
CourseObject::optionsDefinition public function Define configuration elements and their defaults. Overrides CourseHandler::optionsDefinition 3
CourseObject::optionsForm public function Default options form for all course objects. Overrides CourseHandler::optionsForm 3
CourseObject::optionsSubmit public function Save object configs to cache. Overrides CourseHandler::optionsSubmit 1
CourseObject::optionsValidate public function Validate? Overrides CourseHandler::optionsValidate 1
CourseObject::overrideNavigation public function Override navigation links. 1
CourseObject::overrideOutlineListItem public function Overrides a course outline list item. 1
CourseObject::poll function Give the course object a chance do asynchronous polling and set completion on demand.
CourseObject::renderOptionsSummary public function Get all course object implementations of getOptionsSummary().
CourseObject::revoke function Revoke access to the external course object. 1
CourseObject::save public function Let objects create their instances before saving the course object. Overrides CourseHandler::save 1
CourseObject::setComponent function Set the object component for this course object.
CourseObject::setCourse public function Set the Course for this CourseObject.
CourseObject::setId function Set the internal course object ID.
CourseObject::setInstanceId function Set this object's instance ID.
CourseObject::setModule function Set the module that provides this course object.
CourseObject::setUser function Set the user fulfilling/creating this course object.
CourseObject::take public function 5
CourseObject::takeCourseObject final public function Take a course object.
CourseObject::thaw function 1
CourseObject::unEnroll function Remove any records associated with this course object for the user. 1
CourseObject::__construct function Construct a course object from a database record. Overrides CourseHandler::__construct 1