/**
  * registers/queues a user in a certain active-group
  *
  * @param int $agrpid active-group-id to register/queue user to
  * @param int $userid user to register/queue
  * @param bool $previewonly optional don't act, just return a preview
  * @param bool $movefromqueue optional whether or not the move is from the queue
  * @return array ($error, $message)
  */
 private function register_in_agrp($agrpid = 0, $userid = 0, $previewonly = false, $movefromqueue = false)
 {
     global $USER, $PAGE, $DB, $SESSION;
     $grouptool = $this->grouptool;
     if (empty($agrpid)) {
         print_error('missing_param', null, $PAGE->url);
     }
     if (empty($userid)) {
         $userid = $USER->id;
         require_capability('mod/grouptool:register', $this->context);
     }
     $regopen = $this->grouptool->allow_reg && ($this->grouptool->timedue == 0 || time() < $this->grouptool->timedue) && $this->grouptool->timeavailable < time();
     if (!$regopen && !has_capability('mod/grouptool:register_students', $this->context)) {
         return array(true, get_string('reg_not_open', 'grouptool'));
     }
     $message = new stdClass();
     if ($userid != $USER->id) {
         $userdata = $DB->get_record('user', array('id' => $userid));
         $message->username = fullname($userdata);
     }
     $groupdata = $this->get_active_groups(true, true, $agrpid);
     if (count($groupdata) == 1) {
         $groupdata = current($groupdata);
         $message->groupname = $groupdata->name;
         // We have to filter only active groups to ensure no problems counting userregs and -queues.
         $agrpids = $DB->get_fieldset_select('grouptool_agrps', 'id', "grouptoolid = ? AND active = 1", array($grouptool->id));
         list($agrpsql, $params) = $DB->get_in_or_equal($agrpids);
         array_unshift($params, $userid);
         $userregs = $DB->count_records_select('grouptool_registered', "modified_by >= 0 AND userid = ? AND agrpid " . $agrpsql, $params);
         $userqueues = $DB->count_records_select('grouptool_queued', "userid = ? AND agrpid " . $agrpsql, $params);
         $max = $grouptool->allow_multiple ? $grouptool->choose_max : 1;
         $min = $grouptool->allow_multiple ? $grouptool->choose_min : 0;
         if (!empty($groupdata->registered) && $this->get_rank_in_queue($groupdata->registered, $userid) != false) {
             // We're sorry, but user's already registered in this group!
             if ($userid != $USER->id) {
                 return array(true, get_string('already_registered', 'grouptool', $message));
             } else {
                 return array(true, get_string('you_are_already_registered', 'grouptool', $message));
             }
         }
         if (empty($movefromqueue) && !empty($groupdata->queued) && $this->get_rank_in_queue($groupdata->queued, $userid) != false) {
             // We're sorry, but user's already queued in this group!
             if ($userid != $USER->id) {
                 return array(true, get_string('already_queued', 'grouptool', $message));
             } else {
                 return array(true, get_string('you_are_aleady_queued', 'grouptol', $message));
             }
         }
         if ($this->grpmarked($groupdata->agrpid, $userid)) {
             // Allready marked for registration?
             if ($userid != $USER->id) {
                 return array(true, get_string('already_marked', 'grouptool', $message));
             } else {
                 return array(true, get_string('you_are_already_marked', 'grouptool', $message));
             }
         }
         if (empty($movefromqueue) && ($userqueues == 1 && $userregs == $max - 1) || $userqueues + $userregs == 1 && $max == 1) {
             // Groupchange!
             if (empty($grouptool->allow_unreg)) {
                 return array(true, get_string('unreg_not_allowed', 'grouptool'));
             }
             if ($previewonly) {
                 if (!$this->grouptool->use_size || count($groupdata->registered) < $groupdata->grpsize || $this->grouptool->use_queue && $userqueues < $this->grouptool->queues_max) {
                     return array(-1, get_string('change_group_to', 'grouptool', $message));
                 } else {
                     if (!$this->grouptool->use_queue) {
                         // Group is full!
                         if ($userid != $USER->id) {
                             return array(1, get_string('reg_in_full_group', 'grouptool', $message));
                         } else {
                             return array(1, get_string('reg_you_in_full_group', 'grouptool', $message));
                         }
                     } else {
                         if ($userqueues >= $this->grouptool->queues_max) {
                             if ($userid != $USER->id) {
                                 return array(1, get_string('too_many_queue_places', 'grouptool'));
                             } else {
                                 return array(1, get_string('you_have_too_many_queue_places', 'grouptool'));
                             }
                         }
                     }
                 }
             } else {
                 if (!$this->grouptool->use_size || count($groupdata->registered) < $groupdata->grpsize || $this->grouptool->use_queue && $userqueues - 1 < $this->grouptool->queues_max) {
                     $record = new stdClass();
                     $record->agrpid = $agrpid;
                     $record->userid = $userid;
                     $record->timestamp = time();
                     $record->modified_by = $USER->id;
                     if ($userqueues == 1) {
                         // Delete his queue!
                         $queues = $DB->get_records_sql("SELECT queued.*, agrp.groupid\n                                                          FROM {grouptool_queued} queued\n                                                          JOIN {grouptool_agrps} agrp ON agrp.id = queued.agrpid\n                                                          WHERE userid = ? AND agrpid " . $agrpsql, $params);
                         $DB->delete_records_select('grouptool_queued', "userid = ? AND agrpid " . $agrpsql, $params);
                         foreach ($queues as $cur) {
                             // Trigger the event!
                             \mod_grouptool\event\queue_entry_deleted::create_direct($this->cm, $cur);
                         }
                     } else {
                         if ($userregs == 1) {
                             $oldgrp = $DB->get_field_sql("SELECT agrp.groupid\n                                                        FROM {grouptool_registered} reg\n                                                        JOIN {grouptool_agrps} agrp ON agrp.id = reg.agrpid\n                                                       WHERE reg.userid = ? AND reg.agrpid " . $agrpsql, $params, MUST_EXIST);
                             $regs = $DB->get_records_select('grouptool_registered', "userid = ? AND agrpid " . $agrpsql, $params);
                             $DB->delete_records_select('grouptool_registered', "userid = ? AND agrpid " . $agrpsql, $params);
                             if (!empty($oldgrp) && !empty($this->grouptool->immediate_reg)) {
                                 groups_remove_member($oldgrp, $userid);
                             }
                             foreach ($regs as $cur) {
                                 // Trigger the event!
                                 $cur->groupid = $oldgrp;
                                 \mod_grouptool\event\registration_deleted::create_direct($this->cm, $cur);
                             }
                         }
                     }
                     if (!$this->grouptool->use_size || count($groupdata->registered) < $groupdata->grpsize) {
                         $record->id = $DB->insert_record('grouptool_registered', $record);
                         if ($this->grouptool->immediate_reg) {
                             groups_add_member($groupdata->id, $userid);
                         }
                         // Trigger the event!
                         $record->groupid = $groupdata->id;
                         \mod_grouptool\event\registration_created::create_direct($this->cm, $record)->trigger();
                     } else {
                         if ($this->grouptool->use_queue && $userqueues - 1 < $this->grouptool->queues_max) {
                             $record->id = $DB->insert_record('grouptool_queued', $record);
                             // Trigger the Event!
                             $record->groupid = $groupdata->id;
                             \mod_grouptool\event\queue_entry_created::create_direct($this->cm, $record)->trigger();
                         } else {
                             if (!$this->grouptool->use_queue) {
                                 // Group is full!
                                 if ($userid != $USER->id) {
                                     return array(1, get_string('reg_in_full_group', 'grouptool', $message));
                                 } else {
                                     return array(1, get_string('reg_you_in_full_group', 'grouptool', $message));
                                 }
                             } else {
                                 if ($userqueues - 1 >= $this->grouptool->queues_max) {
                                     if ($userid != $USER->id) {
                                         return array(1, get_string('too_many_queue_places', 'grouptool'));
                                     } else {
                                         return array(1, get_string('you_have_too_many_queue_places', 'grouptool'));
                                     }
                                 }
                             }
                         }
                     }
                     if ($userid != $USER->id) {
                         return array(-1, get_string('change_group_to_success', 'grouptool', $message));
                     } else {
                         return array(-1, get_string('you_change_group_to_success', 'grouptool', $message));
                     }
                 }
             }
         }
         if (empty($movefromqueue) && $userregs + $userqueues >= $max || !empty($movefromqueue) && $userregs + $userqueues - 1 >= $max) {
             return array(1, get_string('too_many_regs', 'grouptool'));
         }
         // Get users marks!
         $marks = $this->count_user_marks($userid);
         if ($grouptool->use_size) {
             if (count($groupdata->registered) < $groupdata->grpsize) {
                 // Register!
                 if ($previewonly) {
                     if ($userid != $USER->id) {
                         return array(false, get_string('register_in_group', 'grouptool', $message));
                     } else {
                         return array(false, get_string('register_you_in_group', 'grouptool', $message));
                     }
                 } else {
                     if (empty($movefromqueue) && $this->grouptool->allow_multiple && $this->grouptool->choose_min > $marks + $userregs + $userqueues + 1) {
                         // Cache data until enough registrations are made!
                         $record = new stdClass();
                         $record->agrpid = $agrpid;
                         $record->userid = $userid;
                         $record->timestamp = time();
                         $record->modified_by = -1;
                         $DB->insert_record('grouptool_registered', $record);
                         if ($userid != $USER->id) {
                             return array(false, get_string('place_allocated_in_group_success', 'grouptool', $message));
                         } else {
                             return array(false, get_string('your_place_allocated_in_group_success', 'grouptool', $message));
                         }
                     } else {
                         if ($this->grouptool->allow_multiple) {
                             // Enough registrations have been made, save them!
                             if (!empty($marks)) {
                                 $usermarks = $this->get_user_marks($userid);
                                 foreach ($usermarks as $cur) {
                                     if ($cur->type == 'reg') {
                                         unset($cur->type);
                                         $cur->modified_by = $USER->id;
                                         $DB->update_record('grouptool_registered', $cur);
                                         if ($this->grouptool->immediate_reg) {
                                             groups_add_member($cur->groupid, $cur->userid);
                                         }
                                     } else {
                                         unset($cur->type);
                                         $DB->insert_record('grouptool_queued', $cur);
                                     }
                                 }
                                 $this->delete_user_marks($userid);
                             }
                         }
                         $record = new stdClass();
                         $record->agrpid = $agrpid;
                         $record->userid = $userid;
                         $record->timestamp = time();
                         $record->modified_by = $USER->id;
                         $record->id = $DB->insert_record('grouptool_registered', $record);
                         if ($this->grouptool->immediate_reg) {
                             groups_add_member($groupdata->id, $userid);
                         }
                         $record->groupid = $groupdata->id;
                         \mod_grouptool\event\registration_created::create_direct($this->cm, $record)->trigger();
                         $regcnt = $this->get_user_reg_count(0, $userid);
                         if ($this->grouptool->allow_multiple && $regcnt >= $this->grouptool->choose_max || !$this->grouptool->allow_multiple) {
                             $agrps = $this->get_active_groups(false, false, 0, 0, 0, false);
                             if (count($agrps) > 0) {
                                 $agrpids = array_keys($agrps);
                                 list($sql, $params) = $DB->get_in_or_equal($agrpids);
                                 $queues = $DB->get_records_sql('SELECT queued.*, agrp.groupid
                                                               FROM {grouptool_queued} queued
                                                               JOIN {grouptool_agrps} agrp ON agrp.id = queued.agrpid
                                                              WHERE  userid = ? AND agrpid ' . $sql, array_merge(array($userid), $params));
                                 $DB->delete_records_select('grouptool_queued', ' userid = ? AND agrpid ' . $sql, array_merge(array($userid), $params));
                                 foreach ($queues as $cur) {
                                     // Trigger the event!
                                     \mod_grouptool\event\queue_entry_deleted::create_limit_violation($this->cm, $cur)->trigger();
                                 }
                             }
                         }
                         if ($userid != $USER->id) {
                             return array(false, get_string('register_in_group_success', 'grouptool', $message));
                         } else {
                             return array(false, get_string('register_you_in_group_success', 'grouptool', $message));
                         }
                     }
                 }
             } else {
                 if ($grouptool->use_queue) {
                     // Try to queue!
                     if ($userqueues >= $grouptool->queues_max) {
                         if ($userid != $USER->id) {
                             return array(1, get_string('too_many_queue_places', 'grouptool'));
                         } else {
                             return array(1, get_string('you_have_too_many_queue_places', 'grouptool'));
                         }
                     }
                     $marks = $this->count_user_marks($userid);
                     if ($previewonly) {
                         if ($userid != $USER->id) {
                             return array(-1, get_string('queue_in_group', 'grouptool', $message));
                         } else {
                             return array(-1, get_string('queue_you_in_group', 'grouptool', $message));
                         }
                     } else {
                         if ($this->grouptool->allow_multiple && $this->grouptool->choose_min > $marks + $userregs + $userqueues + 1) {
                             // Cache data until enough registrations are made!
                             // TODO events for place allocation?
                             $record = new stdClass();
                             $record->agrpid = $agrpid;
                             $record->grp_id = $groupdata->id;
                             $record->userid = $userid;
                             $record->timestamp = time();
                             $record->modified_by = -1;
                             $DB->insert_record('grouptool_registered', $record);
                             if ($userid != $USER->id) {
                                 return array(false, get_string('place_allocated_in_group_success', 'grouptool', $message));
                             } else {
                                 return array(false, get_string('your_place_allocated_in_group_success', 'grouptool', $message));
                             }
                         } else {
                             if ($this->grouptool->allow_multiple) {
                                 if (!empty($marks)) {
                                     // Enough registrations have been made, save them!
                                     $usermarks = $this->get_user_marks($userid);
                                     foreach ($usermarks as $cur) {
                                         if ($cur->type == 'reg') {
                                             unset($cur->type);
                                             if ($this->grouptool->immediate_reg) {
                                                 groups_add_member($cur->groupid, $cur->userid);
                                             }
                                             // Premature triggering because of unsetting $cur->groupid afterwards.
                                             \mod_grouptool\event\registration_created::create_direct($this->cm, $cur)->trigger();
                                             unset($cur->groupid);
                                             $cur->modified_by = $USER->id;
                                             $DB->update_record('grouptool_registered', $cur);
                                         } else {
                                             unset($cur->type);
                                             // Trigger the event!
                                             \mod_grouptool\event\queue_entry_created::create_direct($this->cm, $cur)->trigger();
                                             unset($cur->groupid);
                                             $cur->id = $DB->insert_record('grouptool_queued', $cur);
                                         }
                                     }
                                     // TODO: Event for marks deletion?
                                     $this->delete_user_marks($userid);
                                 }
                             }
                             $record = new stdClass();
                             $record->agrpid = $agrpid;
                             $record->userid = $userid;
                             $record->timestamp = time();
                             $record->id = $DB->insert_record('grouptool_queued', $record);
                             // Trigger the event!
                             $record->groupid = $groupdata->id;
                             \mod_grouptool\event\queue_entry_created::create_direct($this->cm, $record)->trigger();
                             if ($userid != $USER->id) {
                                 return array(-1, get_string('queue_in_group_success', 'grouptool', $message));
                             } else {
                                 return array(-1, get_string('queue_you_in_group_success', 'grouptool', $message));
                             }
                         }
                     }
                 } else {
                     // Group is full!
                     if ($userid != $USER->id) {
                         return array(1, get_string('reg_in_full_group', 'grouptool', $message));
                     } else {
                         return array(1, get_string('reg_you_in_full_group', 'grouptool', $message));
                     }
                 }
             }
         } else {
             // Register him!
             if ($previewonly) {
                 if ($userid != $USER->id) {
                     return array(false, get_string('register_in_group', 'grouptool', $message));
                 } else {
                     return array(false, get_string('register_you_in_group', 'grouptool', $message));
                 }
             } else {
                 if ($this->grouptool->allow_multiple && $this->grouptool->choose_min > $marks + $userregs + $userqueues + 1) {
                     // TODO Place allocation event!
                     // Cache data until enough registrations are made!
                     $record = new stdClass();
                     $record->agrpid = $agrpid;
                     $record->grp_id = $groupdata->id;
                     $record->userid = $userid;
                     $record->timestamp = time();
                     $record->modified_by = -1;
                     $DB->insert_record('grouptool_registered', $record);
                     if ($userid != $USER->id) {
                         return array(false, get_string('place_allocated_in_group_success', 'grouptool', $message));
                     } else {
                         return array(false, get_string('your_place_allocated_in_group_success', 'grouptool', $message));
                     }
                 } else {
                     if ($this->grouptool->allow_multiple) {
                         // Enough registrations have been made, save them!
                         if ($marks) {
                             $usermarks = $this->get_user_marks($userid);
                             foreach ($usermarks as $cur) {
                                 if ($cur->type == 'reg') {
                                     unset($cur->type);
                                     $cur->modified_by = $USER->id;
                                     if ($this->grouptool->immediate_reg) {
                                         groups_add_member($cur->groupid, $cur->userid);
                                     }
                                     // Premature triggering because of unsetting $cur->groupid afterwards!
                                     \mod_grouptool\event\registration_created::create_direct($this->cm, $cur)->trigger();
                                     unset($cur->groupid);
                                     $DB->update_record('grouptool_registered', $cur);
                                 } else {
                                     unset($cur->type);
                                     $DB->insert_record('grouptool_queued', $cur);
                                     // Trigger the event!
                                     \mod_grouptool\event\queue_entry_created::create_direct($this->cm, $cur)->trigger();
                                 }
                             }
                             // TODO event for deletion of users marks?
                             $this->delete_user_marks($userid);
                         }
                     }
                     $record = new stdClass();
                     $record->agrpid = $agrpid;
                     $record->userid = $userid;
                     $record->timestamp = time();
                     $record->modified_by = $USER->id;
                     $record->id = $DB->insert_record('grouptool_registered', $record);
                     if ($this->grouptool->immediate_reg) {
                         groups_add_member($groupdata->id, $userid);
                     }
                     // Trigger the event!
                     $record->groupid = $groupdata->id;
                     \mod_grouptool\event\registration_created::create_direct($this->cm, $record)->trigger();
                     $regcnt = $this->get_user_reg_count(0, $userid);
                     if ($this->grouptool->allow_multiple && $regcnt >= $this->grouptool->choose_max || !$this->grouptool->allow_multiple) {
                         $agrps = $this->get_active_groups(false, false, 0, 0, 0, false);
                         if (count($agrps) > 0) {
                             $agrpids = array_keys($agrps);
                             list($sql, $params) = $DB->get_in_or_equal($agrpids);
                             $queues = $DB->get_records_sql('SELECT queued.*, agrp.groupid
                                                           FROM {grouptool_queued} queued
                                                           JOIN {grouptool_agrps} agrp ON queued.agrpid = agrp.id
                                                          WHERE queued.userid = ? AND queued.agrpid ' . $sql, array_merge(array($userid), $params));
                             $DB->delete_records_select('grouptool_queued', ' userid = ? AND agrpid ' . $sql, array_merge(array($userid), $params));
                             foreach ($queues as $cur) {
                                 // Trigger the event!
                                 \mod_grouptool\event\queue_entry_deleted::create_limit_violation($this->cm, $cur)->trigger();
                             }
                         }
                     }
                     if ($userid != $USER->id) {
                         return array(false, get_string('register_in_group_success', 'grouptool', $message));
                     } else {
                         return array(false, get_string('register_you_in_group_success', 'grouptool', $message));
                     }
                 }
             }
         }
     } else {
         return array(true, get_string('error_getting_data', 'grouptool'));
     }
 }
 /**
  * group_deleted
  *
  * @param \core\event\group_deleted $event Event object containing useful data
  * @return bool true if success
  */
 public static function group_deleted(\core\event\group_deleted $event)
 {
     global $CFG, $DB;
     $data = $event->get_record_snapshot('groups', $event->objectid);
     $course = $DB->get_record('course', array('id' => $data->courseid), '*', MUST_EXIST);
     if (!($grouptools = get_all_instances_in_course('grouptool', $course))) {
         return true;
     }
     $grouprecreated = false;
     $agrpids = array();
     foreach ($grouptools as $grouptool) {
         $cmid = $grouptool->coursemodule;
         switch ($grouptool->ifgroupdeleted) {
             default:
             case GROUPTOOL_RECREATE_GROUP:
                 if (!$grouprecreated) {
                     $newid = $DB->insert_record('groups', $data, true);
                     if ($newid !== false) {
                         // Delete auto-inserted agrp.
                         if ($DB->record_exists('grouptool_agrps', array('groupid' => $newid))) {
                             $DB->delete_records('grouptool_agrps', array('groupid' => $newid));
                         }
                         // Update reference.
                         if ($DB->record_exists('grouptool_agrps', array('groupid' => $data->id))) {
                             $DB->set_field('grouptool_agrps', 'groupid', $newid, array('groupid' => $data->id));
                         }
                         // Trigger event!
                         $logdata = array('cmid' => $cmid, 'groupid' => $data->id, 'newid' => $newid, 'courseid' => $data->courseid);
                         \mod_grouptool\event\group_recreated::create_from_object($logdata)->trigger();
                         if ($grouptool->immediate_reg) {
                             require_once $CFG->dirroot . '/mod/grouptool/locallib.php';
                             $instance = new mod_grouptool($cmid, $grouptool);
                             $instance->push_registrations();
                         }
                         $grouprecreated = true;
                     } else {
                         print_error('error', 'moodle');
                         return false;
                     }
                 } else {
                     if ($grouptool->immediate_reg) {
                         require_once $CFG->dirroot . '/mod/grouptool/locallib.php';
                         $instance = new mod_grouptool($cmid, $grouptool);
                         $instance->push_registrations();
                     }
                 }
                 break;
             case GROUPTOOL_DELETE_REF:
                 if ($agrpid = $DB->get_field('grouptool_agrps', 'id', array('groupid' => $data->id, 'grouptoolid' => $grouptool->id))) {
                     $agrpids[] = $agrpid;
                 }
                 break;
         }
     }
     if (count($agrpids) > 0) {
         $agrps = $DB->get_records_list('grouptool_agrps', 'id', $agrpids);
         $cms = array();
         $regs = $DB->get_records_list('grouptool_registered', 'agrpid', $agrpids);
         $DB->delete_records_list('grouptool_registered', 'agrpid', $agrpids);
         foreach ($regs as $cur) {
             if (empty($cms[$agrps[$cur->agrpid]->grouptoolid])) {
                 $cms[$agrps[$cur->agrpid]->grouptoolid] = get_coursemodule_from_instance('grouptool', $agrps[$cur->agrpid]->grouptoolid);
             }
             $cur->groupid = $agrps[$cur->agrpid]->groupid;
             \mod_grouptool\event\registration_deleted::create_via_eventhandler($cms[$agrps[$cur->agrpid]->grouptoolid], $cur);
         }
         $queues = $DB->get_records_list('grouptool_queued', 'agrpid', $agrpids);
         $DB->delete_records_list('grouptool_queued', 'agrpid', $agrpids);
         foreach ($queues as $cur) {
             if (empty($cms[$agrps[$cur->agrpid]->grouptoolid])) {
                 $cms[$agrps[$cur->agrpid]->grouptoolid] = get_coursemodule_from_instance('grouptool', $agrps[$cur->agrpid]->grouptoolid);
             }
             // Trigger event!
             $cur->groupid = $agrps[$cur->agrpid]->groupid;
             \mod_grouptool\event\queue_entry_deleted::create_via_eventhandler($cms[$agrps[$cur->agrpid]->grouptoolid], $cur);
         }
         $DB->delete_records_list('grouptool_agrps', 'id', $agrpids);
         foreach ($agrps as $cur) {
             if (empty($cms[$cur->grouptoolid])) {
                 $cms[$cur->grouptoolid] = get_coursemodule_from_instance('grouptool', $cur->grouptoolid);
             }
             // Trigger event!
             $logdata = new stdClass();
             $logdata->id = $cur->id;
             $logdata->cmid = $cms[$cur->grouptoolid]->id;
             $logdata->groupid = $cur->groupid;
             $logdata->agrpid = $cur->id;
             $logdata->courseid = $data->courseid;
             \mod_grouptool\event\agrp_deleted::create_from_object($logdata);
         }
     }
     return true;
 }