Beispiel #1
0
 /**
  * Checks all course-level rule subscriptions and activates/deactivates based on current course access.
  *
  * The ordering of checks within the task is important for optimisation purposes. The aim is to be able to make a decision
  * about whether to activate/deactivate each subscription without making unnecessary checks. The ordering roughly follows the
  * context model, starting with system and user checks and moving down to course and course-module only when necessary.
  *
  * For example, if the user is suspended, then any active subscription is made inactive right away. I.e. there is no need to
  * check site-level, course-level or course-module-level permissions. Likewise, if a subscriptions is site-level, there is no
  * need to check course-level and course-module-level permissions.
  *
  * The task performs the following checks, in this order:
  * 1. Check for a suspended user, breaking if suspended.
  * 2. Check for an incomplete (not set up) user, breaking if not fully set up.
  * 3. Check for the required capability in the relevant context, breaking if the capability is not found.
  * 4. Check whether the subscription is site-context, breaking if true.
  * 5. Check whether the user has course access, breaking only if the subscription is not also course-module-level.
  * 6. Check whether the user has course-module access.
  *
  * @since 3.2.0
  */
 public function execute()
 {
     global $DB;
     if (!get_config('tool_monitor', 'enablemonitor')) {
         return;
         // The tool is disabled. Nothing to do.
     }
     $toactivate = array();
     // Store the ids of subscriptions to be activated upon completion.
     $todeactivate = array();
     // Store the ids of subscriptions to be deactivated upon completion.
     // Resultset rows are ordered by userid and courseid to work nicely with get_fast_modinfo() caching.
     $sql = "SELECT u.id AS userid, u.firstname AS userfirstname, u.lastname AS userlastname, u.suspended AS usersuspended,\n                       u.email AS useremail, c.visible as coursevisible, c.cacherev as coursecacherev, s.courseid AS subcourseid,\n                       s.userid AS subuserid, s.cmid AS subcmid, s.inactivedate AS subinactivedate, s.id AS subid\n                  FROM {user} u\n                  JOIN {tool_monitor_subscriptions} s ON (s.userid = u.id)\n             LEFT JOIN {course} c ON (c.id = s.courseid)\n                 WHERE u.id = s.userid\n              ORDER BY s.userid, s.courseid";
     $rs = $DB->get_recordset_sql($sql);
     foreach ($rs as $row) {
         // Create skeleton records from the result. This should be enough to use in subsequent access calls and avoids DB hits.
         $sub = $this->get_subscription_from_rowdata($row);
         $sub = new subscription($sub);
         if (!isset($user) || $user->id != $sub->userid) {
             $user = $this->get_user_from_rowdata($row);
         }
         if ((!isset($course) || $course->id != $sub->courseid) && !empty($sub->courseid)) {
             $course = $this->get_course_from_rowdata($row);
         }
         // The user is suspended at site level, so deactivate any active subscriptions.
         if ($user->suspended) {
             if (subscription_manager::subscription_is_active($sub)) {
                 $todeactivate[] = $sub->id;
             }
             continue;
         }
         // Is the user fully set up? As per require_login on the subscriptions page.
         if (!$this->is_user_setup($user)) {
             if (subscription_manager::subscription_is_active($sub)) {
                 $todeactivate[] = $sub->id;
             }
             continue;
         }
         // Determine the context, based on the subscription course id.
         $sitelevelsubscription = false;
         if (empty($sub->courseid)) {
             $context = \context_system::instance();
             $sitelevelsubscription = true;
         } else {
             $context = \context_course::instance($sub->courseid);
         }
         // Check capability in the context.
         if (!has_capability('tool/monitor:subscribe', $context, $user)) {
             if (subscription_manager::subscription_is_active($sub)) {
                 $todeactivate[] = $sub->id;
             }
             continue;
         }
         // If the subscription is site-level, then we've run all the checks required to make an access decision.
         if ($sitelevelsubscription) {
             if (!subscription_manager::subscription_is_active($sub)) {
                 $toactivate[] = $sub->id;
             }
             continue;
         }
         // Check course access.
         if (!$this->user_can_access_course($user, $course, 'tool/monitor:subscribe')) {
             if (subscription_manager::subscription_is_active($sub)) {
                 $todeactivate[] = $sub->id;
             }
             continue;
         }
         // If the subscription has no course module relationship.
         if (empty($sub->cmid)) {
             if (!subscription_manager::subscription_is_active($sub)) {
                 $toactivate[] = $sub->id;
             }
             continue;
         }
         // Otherwise, check the course module info. We use the same checks as on the subscription page.
         $modinfo = get_fast_modinfo($course, $sub->userid);
         $cm = $modinfo->get_cm($sub->cmid);
         if (!$cm || !$cm->uservisible || !$cm->available) {
             if (subscription_manager::subscription_is_active($sub)) {
                 $todeactivate[] = $sub->id;
             }
             continue;
         }
         // The course module is available and visible, so make a decision.
         if (!subscription_manager::subscription_is_active($sub)) {
             $toactivate[] = $sub->id;
         }
     }
     $rs->close();
     // Activate/deactivate/delete relevant subscriptions.
     subscription_manager::activate_subscriptions($toactivate);
     subscription_manager::deactivate_subscriptions($todeactivate);
     subscription_manager::delete_stale_subscriptions();
 }