Deal with users that are not supposed to be enrolled via this instance
@static
@param stdClass $instance
@param stdClass $ue
@param context_course $context
@param enrol_meta $plugin
@return void
542545
protected static function user_not_supposed_to_be_here($instance, $ue, context_course $context, $plugin) {
        if (!$ue) {
            // Not enrolled yet - simple!
            return;
        }

        $userid = $ue->userid;
        $unenrolaction = $plugin->get_config('unenrolaction', ENROL_EXT_REMOVED_SUSPENDNOROLES);

        if ($unenrolaction == ENROL_EXT_REMOVED_UNENROL) {
            // Purges grades, group membership, preferences, etc. - admins were warned!
            $plugin->unenrol_user($instance, $userid);

        } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPEND) {
            if ($ue->status != ENROL_USER_SUSPENDED) {
                $plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED);
            }

        } else if ($unenrolaction == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
            if ($ue->status != ENROL_USER_SUSPENDED) {
                $plugin->update_user_enrol($instance, $userid, ENROL_USER_SUSPENDED);
            }
            role_unassign_all(array('userid'=>$userid, 'contextid'=>$context->id, 'component'=>'enrol_meta', 'itemid'=>$instance->id));

        } else {
            debugging('Unknown unenrol action '.$unenrolaction);
        }
    }
1070736
public function add_course_navigation($instancesnode, stdClass $instance) {
        if ($this->use_standard_editing_ui()) {
            $context = context_course::instance($instance->courseid);
            $cap = 'enrol/' . $instance->enrol . ':config';
            if (has_capability($cap, $context)) {
                $linkparams = array('courseid' => $instance->courseid, 'id' => $instance->id, 'type' => $instance->enrol);
                $managelink = new moodle_url('/enrol/editinstance.php', $linkparams);
                $instancesnode->add($this->get_instance_name($instance), $managelink, navigation_node::TYPE_SETTING);
            }
        }
    }
1290612
public function update_instance($instance, $data) {
        global $DB;

        parent::update_instance($instance, $data);

        // Remove the fields we don't want to override.
        unset($data->id);
        unset($data->timecreated);
        unset($data->timemodified);

        // Convert to an array we can loop over.
        $fields = (array) $data;

        // Update the data in our table.
        $tool = new stdClass();
        $tool->id = $data->toolid;
        $tool->timemodified = time();
        foreach ($fields as $field => $value) {
            $tool->$field = $value;
        }

        return $DB->update_record('enrol_lti_tools', $tool);
    }
182195
public function user_delete($user) {
        global $DB;

        $sql = "SELECT e.*
                  FROM {enrol} e
                  JOIN {user_enrolments} ue ON (ue.enrolid = e.id)
                 WHERE e.enrol = :name AND ue.userid = :userid";
        $params = array('name'=>$this->get_name(), 'userid'=>$user->id);

        $rs = $DB->get_recordset_sql($sql, $params);
        foreach($rs as $instance) {
            $this->unenrol_user($instance, $user->id);
        }
        $rs->close();
    }
1233181
public function restore_user_enrolment(restore_enrolments_structure_step $step, $data, $instance, $userid, $oldinstancestatus) {
        global $DB;

        if ($this->get_config('unenrolaction') != ENROL_EXT_REMOVED_SUSPENDNOROLES) {
            // Enrolments were already synchronised in restore_instance(), we do not want any suspended leftovers.
            return;
        }

        // ENROL_EXT_REMOVED_SUSPENDNOROLES means all previous enrolments are restored
        // but without roles and suspended.

        if (!$DB->record_exists('user_enrolments', array('enrolid' => $instance->id, 'userid' => $userid))) {
            $this->enrol_user($instance, $userid, null, $data->timestart, $data->timeend, ENROL_USER_SUSPENDED);
            if ($instance->customint2) {
                groups_add_member($instance->customint2, $userid, 'enrol_meta', $instance->id);
            }
        }
    }
535965
public static function user_enrolment_created(\core\event\user_enrolment_created $event) {
        if (!enrol_is_enabled('meta')) {
            // No more enrolments for disabled plugins.
            return true;
        }

        if ($event->other['enrol'] === 'meta') {
            // Prevent circular dependencies - we can not sync meta enrolments recursively.
            return true;
        }

        self::sync_course_instances($event->courseid, $event->relateduserid);
        return true;
    }
712006
private static function set( $instance = false ) {
		// Make sure the plugin hasn't already been instantiated before.
		global $wp_plugins;
		if ( ! isset( $wp_plugins ) ) {
			$wp_plugins = new \stdClass();
		}
		// Get the fully qualified parent class name and instantiate an instance of it.
		$called_class = get_called_class();
		$plugin_name  = strtolower( $called_class );
		if ( empty( $instance ) || ! is_a( $instance, $called_class ) ) {
			$wp_plugins->$plugin_name = new $called_class();
		} else {
			$wp_plugins->$plugin_name = $instance;
		}
	}
284695
public static function is_context_expired_or_unprotected_for_user(\context $context, \stdClass $user) : bool {
        // User/course contexts can't expire if no purpose is set in the system context.
        if (!data_registry::defaults_set()) {
            return false;
        }

        $parents = $context->get_parent_contexts(true);
        foreach ($parents as $parent) {
            if ($parent instanceof \context_course) {
                // This is a context within a course. Check whether _this context_ is expired as a function of a course.
                return self::is_course_context_expired_or_unprotected_for_user($context, $user);
            }

            if ($parent instanceof \context_user) {
                // This is a context within a user. Check whether the _user_ has expired.
                return self::are_user_context_dependencies_expired($parent);
            }
        }

        return false;
    }
1089213
public function restore_role_assignment($instance, $roleid, $userid, $contextid) {
        global $DB;

        if ($this->get_config('unenrolaction') == ENROL_EXT_REMOVED_UNENROL or $this->get_config('unenrolaction') == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
            // Skip any roles restore, they should be already synced automatically.
            return;
        }

        // Just restore every role.
        if ($DB->record_exists('user_enrolments', array('enrolid'=>$instance->id, 'userid'=>$userid))) {
            role_assign($roleid, $userid, $contextid, 'enrol_'.$instance->enrol, $instance->id);
        }
    }
33715
public function enrol_user(stdClass $instance, $userid, $roleid = null, $timestart = 0, $timeend = 0, $status = null, $recovergrades = null) {
        // no real enrolments here!
        return;
    }
1064391
public static function unenrol_user_enrolment($ueid) {
        global $CFG, $DB, $PAGE;

        $params = self::validate_parameters(self::unenrol_user_enrolment_parameters(), [
            'ueid' => $ueid
        ]);

        $result = false;
        $errors = [];

        $userenrolment = $DB->get_record('user_enrolments', ['id' => $params['ueid']], '*');
        if ($userenrolment) {
            $userid = $userenrolment->userid;
            $enrolid = $userenrolment->enrolid;
            $enrol = $DB->get_record('enrol', ['id' => $enrolid], '*', MUST_EXIST);
            $courseid = $enrol->courseid;
            $course = get_course($courseid);
            $context = context_course::instance($course->id);
            self::validate_context($context);
        } else {
            $validationerrors['invalidrequest'] = get_string('invalidrequest', 'enrol');
        }

        // If the userenrolment exists, unenrol the user.
        if (!isset($validationerrors)) {
            require_once($CFG->dirroot . '/enrol/locallib.php');
            $manager = new course_enrolment_manager($PAGE, $course);
            $result = $manager->unenrol_user($userenrolment);
        } else {
            foreach ($validationerrors as $key => $errormessage) {
                $errors[] = (object)[
                    'key' => $key,
                    'message' => $errormessage
                ];
            }
        }

        return [
            'result' => $result,
            'errors' => $errors,
        ];
    }
458321
public function restore_role_assignment($instance, $roleid, $userid, $contextid) {
        role_assign($roleid, $userid, $contextid, 'enrol_'.$instance->enrol, $instance->id);
    }
1308914
public static function enrol_instance_updated(\core\event\enrol_instance_updated $event) {
        global $DB;

        if (!enrol_is_enabled('meta')) {
            // This is slow, let enrol_meta_sync() deal with disabled plugin.
            return true;
        }

        // Does anything want to sync with this parent?
        $affectedcourses = $DB->get_fieldset_sql('SELECT DISTINCT courseid FROM {enrol} '.
                'WHERE customint1 = ? AND enrol = ?',
                array($event->courseid, 'meta'));

        foreach ($affectedcourses as $courseid) {
            enrol_meta_sync($courseid);
        }

        return true;
    }
324391
public function restore_role_assignment($instance, $roleid, $userid, $contextid) {
        if ($this->get_config('unenrolaction') == ENROL_EXT_REMOVED_UNENROL or $this->get_config('unenrolaction') == ENROL_EXT_REMOVED_SUSPENDNOROLES) {
            // Role assignments were already synchronised in restore_instance(), we do not want any leftovers.
            return;
        }
        role_assign($roleid, $userid, $contextid, 'enrol_'.$this->get_name(), $instance->id);
    }
1135978
public static function delete_data_for_all_users_in_context(\context $context) {
        if ($context->contextlevel != CONTEXT_COURSE) {
            return;
        }
        global $DB;
        $DB->delete_records('enrol_flatfile', ['courseid' => $context->instanceid]);
    }
1197381
public function get_enrol_info(stdClass $instance) {

        $instanceinfo = new stdClass();
        $instanceinfo->id = $instance->id;
        $instanceinfo->courseid = $instance->courseid;
        $instanceinfo->type = $this->get_name();
        $instanceinfo->name = $this->get_instance_name($instance);
        $instanceinfo->status = $this->can_self_enrol($instance);

        if ($instance->password) {
            $instanceinfo->requiredparam = new stdClass();
            $instanceinfo->requiredparam->enrolpassword = get_string('password', 'enrol_self');
        }

        // If enrolment is possible and password is required then return ws function name to get more information.
        if ((true === $instanceinfo->status) && $instance->password) {
            $instanceinfo->wsfunction = 'enrol_self_get_instance_info';
        }
        return $instanceinfo;
    }
811317
public function process(course_enrolment_manager $manager, array $users, stdClass $properties) {
        global $DB, $USER;

        if (!has_capability("enrol/manual:manage", $manager->get_context())) {
            return false;
        }

        // Get all of the user enrolment id's.
        $ueids = array();
        $instances = array();
        foreach ($users as $user) {
            foreach ($user->enrolments as $enrolment) {
                $ueids[] = $enrolment->id;
                if (!array_key_exists($enrolment->id, $instances)) {
                    $instances[$enrolment->id] = $enrolment;
                }
            }
        }

        // Check that each instance is manageable by the current user.
        foreach ($instances as $instance) {
            if (!$this->plugin->allow_manage($instance)) {
                return false;
            }
        }

        // Collect the known properties.
        $status = $properties->status;
        $timestart = $properties->timestart;
        $timeend = $properties->timeend;

        list($ueidsql, $params) = $DB->get_in_or_equal($ueids, SQL_PARAMS_NAMED);

        $updatesql = array();
        if ($status == ENROL_USER_ACTIVE || $status == ENROL_USER_SUSPENDED) {
            $updatesql[] = 'status = :status';
            $params['status'] = (int)$status;
        }
        if (!empty($timestart)) {
            $updatesql[] = 'timestart = :timestart';
            $params['timestart'] = (int)$timestart;
        }
        if (!empty($timeend)) {
            $updatesql[] = 'timeend = :timeend';
            $params['timeend'] = (int)$timeend;
        }
        if (empty($updatesql)) {
            return true;
        }

        // Update the modifierid.
        $updatesql[] = 'modifierid = :modifierid';
        $params['modifierid'] = (int)$USER->id;

        // Update the time modified.
        $updatesql[] = 'timemodified = :timemodified';
        $params['timemodified'] = time();

        // Build the SQL statement.
        $updatesql = join(', ', $updatesql);
        $sql = "UPDATE {user_enrolments}
                   SET $updatesql
                 WHERE id $ueidsql";

        if ($DB->execute($sql, $params)) {
            foreach ($users as $user) {
                foreach ($user->enrolments as $enrolment) {
                    $enrolment->courseid  = $enrolment->enrolmentinstance->courseid;
                    $enrolment->enrol     = 'manual';
                    // Trigger event.
                    $event = \core\event\user_enrolment_updated::create(
                            array(
                                'objectid' => $enrolment->id,
                                'courseid' => $enrolment->courseid,
                                'context' => context_course::instance($enrolment->courseid),
                                'relateduserid' => $user->id,
                                'other' => array('enrol' => 'manual')
                                )
                            );
                    $event->trigger();
                }
            }
            // Delete cached course contacts for this course because they may be affected.
            cache::make('core', 'coursecontacts')->delete($manager->get_context()->instanceid);
            return true;
        }

        return false;
    }