Loads the data required to render the report.

@param int $courseid The course id
@param int $userid The user id
@param int $moduleid The module id
@return \stdClass
965867
public static function data_for_report($courseid, $userid, $moduleid) {
        global $PAGE;

        $params = self::validate_parameters(
            self::data_for_report_parameters(),
            array(
                'courseid' => $courseid,
                'userid' => $userid,
                'moduleid' => $moduleid
            )
        );
        $context = context_course::instance($params['courseid']);
        self::validate_context($context);
        if (!is_enrolled($context, $params['userid'], 'moodle/competency:coursecompetencygradable')) {
            throw new coding_exception('invaliduser');
        }

        $renderable = new output\report($params['courseid'], $params['userid'], $params['moduleid']);
        $renderer = $PAGE->get_renderer('report_competency');

        $data = $renderable->export_for_template($renderer);

        return $data;
    }
1230399
public static function get_contexts_for_userid(int $userid) : contextlist {
        $params = ['modulename' => 'assign',
                   'contextlevel' => CONTEXT_MODULE,
                   'userid' => $userid,
                   'graderid' => $userid,
                   'aouserid' => $userid,
                   'asnuserid' => $userid,
                   'aufuserid' => $userid,
                   'aumuserid' => $userid];

        $sql = "SELECT ctx.id
                  FROM {course_modules} cm
                  JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
                  JOIN {assign} a ON cm.instance = a.id
                  JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
                  JOIN {assign_grades} ag ON a.id = ag.assignment AND (ag.userid = :userid OR ag.grader = :graderid)";

        $contextlist = new contextlist();
        $contextlist->add_from_sql($sql, $params);

        $sql = "SELECT ctx.id
                  FROM {course_modules} cm
                  JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
                  JOIN {assign} a ON cm.instance = a.id
                  JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
                  JOIN {assign_overrides} ao ON a.id = ao.assignid
                 WHERE ao.userid = :aouserid";

        $contextlist->add_from_sql($sql, $params);

        $sql = "SELECT ctx.id
                  FROM {course_modules} cm
                  JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
                  JOIN {assign} a ON cm.instance = a.id
                  JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
                  JOIN {assign_submission} asn ON a.id = asn.assignment
                 WHERE asn.userid = :asnuserid";

        $contextlist->add_from_sql($sql, $params);

        $sql = "SELECT ctx.id
                  FROM {course_modules} cm
                  JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
                  JOIN {assign} a ON cm.instance = a.id
                  JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
                  JOIN {assign_user_flags} auf ON a.id = auf.assignment
                 WHERE auf.userid = :aufuserid";

        $contextlist->add_from_sql($sql, $params);

        $sql = "SELECT ctx.id
                  FROM {course_modules} cm
                  JOIN {modules} m ON cm.module = m.id AND m.name = :modulename
                  JOIN {assign} a ON cm.instance = a.id
                  JOIN {context} ctx ON cm.id = ctx.instanceid AND ctx.contextlevel = :contextlevel
                  JOIN {assign_user_mapping} aum ON a.id = aum.assignment
                 WHERE aum.userid = :aumuserid";

        $contextlist->add_from_sql($sql, $params);

        manager::plugintype_class_callback('assignfeedback', self::ASSIGNFEEDBACK_INTERFACE,
                'get_context_for_userid_within_feedback', [$userid, $contextlist]);
        manager::plugintype_class_callback('assignsubmission', self::ASSIGNSUBMISSION_INTERFACE,
                'get_context_for_userid_within_submission', [$userid, $contextlist]);

        return $contextlist;
    }
860825
public static function get_course_completion_status($courseid, $userid) {
        global $CFG, $USER;
        require_once($CFG->libdir . '/grouplib.php');

        $warnings = array();
        $arrayparams = array(
            'courseid' => $courseid,
            'userid'   => $userid,
        );
        $params = self::validate_parameters(self::get_course_completion_status_parameters(), $arrayparams);

        $course = get_course($params['courseid']);
        $user = core_user::get_user($params['userid'], '*', MUST_EXIST);
        core_user::require_active_user($user);

        $context = context_course::instance($course->id);
        self::validate_context($context);

        // Can current user see user's course completion status?
        // This check verifies if completion is enabled because $course is mandatory.
        if (!completion_can_view_data($user->id, $course)) {
            throw new moodle_exception('cannotviewreport');
        }

        // The previous function doesn't check groups.
        if ($user->id != $USER->id) {
            if (!groups_user_groups_visible($course, $user->id)) {
                // We are not in the same group!
                throw new moodle_exception('accessdenied', 'admin');
            }
        }

        $info = new completion_info($course);

        // Check this user is enroled.
        if (!$info->is_tracked_user($user->id)) {
            if ($USER->id == $user->id) {
                throw new moodle_exception('notenroled', 'completion');
            } else {
                throw new moodle_exception('usernotenroled', 'completion');
            }
        }

        $completions = $info->get_completions($user->id);
        if (empty($completions)) {
            throw new moodle_exception('nocriteriaset', 'completion');
        }

        // Load course completion.
        $completionparams = array(
            'userid' => $user->id,
            'course' => $course->id,
        );
        $ccompletion = new completion_completion($completionparams);

        $completionrows = array();
        // Loop through course criteria.
        foreach ($completions as $completion) {
            $criteria = $completion->get_criteria();

            $completionrow = array();
            $completionrow['type'] = $criteria->criteriatype;
            $completionrow['title'] = $criteria->get_title();
            $completionrow['status'] = $completion->get_status();
            $completionrow['complete'] = $completion->is_complete();
            $completionrow['timecompleted'] = $completion->timecompleted;
            $completionrow['details'] = $criteria->get_details($completion);
            $completionrows[] = $completionrow;
        }

        $result = array(
                  'completed'   => $info->is_course_complete($user->id),
                  'aggregation' => $info->get_aggregation_method(),
                  'completions' => $completionrows
        );

        $results = array(
            'completionstatus' => $result,
            'warnings' => $warnings
        );
        return $results;

    }
1321732
public static function create_from_ids(int $userfromid, int $usertoid, int $messageid, int $courseid) {
        // We may be sending a message from the 'noreply' address, which means we are not actually sending a
        // message from a valid user. In this case, we will set the userid to 0.
        // Check if the userid is valid.
        if (!\core_user::is_real_user($userfromid)) {
            $userfromid = 0;
        }

        $event = self::create(array(
            'objectid' => $messageid,
            'userid' => $userfromid,
            'context' => \context_system::instance(),
            'relateduserid' => $usertoid,
            'other' => array(
                'courseid' => $courseid
            )
        ));

        return $event;
    }
120635
protected static function export_user_data_in_course_contexts_rated_by_me($userid, $courseids, $path,
            performance_helper $helper) {
        global $DB;

        // Fetch all the records of competency proficiency in the course.
        $ffields = competency_framework::get_sql_fields('f', 'f_');
        $compfields = competency::get_sql_fields('c', 'c_');
        $uccfields = user_competency_course::get_sql_fields('ucc', 'ucc_');
        $ctxfields = context_helper::get_preload_record_columns_sql('ctx');
        list($insql, $inparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
        $sql = "
            SELECT $ffields, $compfields, $uccfields, $ctxfields
              FROM {" . user_competency_course::TABLE . "} ucc
              JOIN {" . competency::TABLE . "} c
                ON c.id = ucc.competencyid
              JOIN {" . competency_framework::TABLE . "} f
                ON f.id = c.competencyframeworkid
              JOIN {context} ctx
                ON ctx.id = f.contextid
             WHERE ucc.usermodified = :userid
               AND ucc.courseid $insql
          ORDER BY ucc.courseid, ucc.id";
        $params = array_merge($inparams, ['userid' => $userid]);

        // Export the data.
        static::recordset_loop_and_export($DB->get_recordset_sql($sql, $params), 'ucc_courseid', [],
            function($carry, $record) use ($helper) {
                context_helper::preload_from_record($record);

                $framework = new competency_framework(null, competency_framework::extract_record($record, 'f_'));
                $competency = new competency(null, competency::extract_record($record, 'c_'));
                $ucc = new user_competency_course(null, user_competency_course::extract_record($record, 'ucc_'));
                $helper->ingest_framework($framework);

                $carry[] = array_merge(static::transform_competency_brief($competency), [
                    'rating' => [
                        'userid' => transform::user($ucc->get('userid')),
                        'rating' => static::transform_competency_grade($competency, $ucc->get('grade'), $helper),
                        'proficient' => static::transform_proficiency($ucc->get('proficiency')),
                        'timemodified' => transform::datetime($ucc->get('timemodified')),
                    ]
                ]);
                return $carry;

            }, function($courseid, $data) use ($path) {
                $context = context_course::instance($courseid);
                writer::with_context($context)->export_related_data($path, 'rated_by_me', (object) [
                    'ratings' => $data
                ]);
            }
        );
    }
303661
public static function can_read_user_in_course($userid, $courseid) {
        $capability = 'moodle/competency:usercompetencyview';
        return has_capability($capability, context_course::instance($courseid))
            || static::can_read_user($userid);
    }
1372133
public static function get_modules_from_sectionid($sectionid) {
        global $DB;

        // Get the course and sequence of the section
        $secrec = $DB->get_record('course_sections', array('id' => $sectionid), 'course, sequence');
        $courseid = $secrec->course;
        $sequence = $secrec->sequence;

        // Get the section->sequence contents (it roots the activities order)
        // Get all course modules belonging to requested section
        $modulesarr = array();
        $modules = $DB->get_records_sql("
            SELECT cm.id, m.name AS modname
              FROM {course_modules} cm
              JOIN {modules} m ON m.id = cm.module
             WHERE cm.course = ?
               AND cm.section = ?
               AND cm.deletioninprogress <> 1", array($courseid, $sectionid));
        foreach (explode(',', $sequence) as $moduleid) {
            if (isset($modules[$moduleid])) {
                $module = array('id' => $modules[$moduleid]->id, 'modname' => $modules[$moduleid]->modname);
                $modulesarr[] = (object)$module;
                unset($modules[$moduleid]);
            }
        }
        if (!empty($modules)) { // This shouldn't happen, but one borked sequence can lead to it. Add the rest
            foreach ($modules as $module) {
                $module = array('id' => $module->id, 'modname' => $module->modname);
                $modulesarr[] = (object)$module;
            }
        }
        return $modulesarr;
    }
279052
protected static function export_user_data_in_course_contexts_associations($userid, $courseids, $path) {
        global $DB;

        // Fetch all the courses with associations we created or modified.
        $compfields = competency::get_sql_fields('c', 'c_');
        $ccfields = course_competency::get_sql_fields('cc', 'cc_');
        $ctxfields = context_helper::get_preload_record_columns_sql('ctx');
        list($insql, $inparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED);
        $sql = "
            SELECT $compfields, $ccfields, $ctxfields
              FROM {" . course_competency::TABLE . "} cc
              JOIN {" . competency::TABLE . "} c
                ON c.id = cc.competencyid
              JOIN {" . competency_framework::TABLE . "} f
                ON f.id = c.competencyframeworkid
              JOIN {context} ctx
                ON ctx.id = f.contextid
             WHERE cc.usermodified = :userid
               AND cc.courseid $insql
          ORDER BY cc.courseid, c.id";
        $params = array_merge($inparams, ['userid' => $userid]);
        $recordset = $DB->get_recordset_sql($sql, $params);

        // Export the data.
        static::recordset_loop_and_export($recordset, 'cc_courseid', [], function($carry, $record) {
            context_helper::preload_from_record($record);
            $competency = new competency(null, competency::extract_record($record, 'c_'));
            $cc = new course_competency(null, course_competency::extract_record($record, 'cc_'));
            $carry[] = array_merge(static::transform_competency_brief($competency), [
                'timemodified' => transform::datetime($cc->get('timemodified')),
                'created_or_modified_by_you' => transform::yesno(true)
            ]);
            return $carry;

        }, function($courseid, $data) use ($path, $userid, $DB) {
            $context = context_course::instance($courseid);
            writer::with_context($context)->export_related_data($path, 'associations', (object) ['competencies' => $data]);
        });
    }
773978
public static function data_for_user_competency_summary($userid, $competencyid) {
        global $PAGE;
        $params = self::validate_parameters(self::data_for_user_competency_summary_parameters(), array(
            'userid' => $userid,
            'competencyid' => $competencyid,
        ));

        $uc = api::get_user_competency($params['userid'], $params['competencyid']);
        self::validate_context($uc->get_context());
        $output = $PAGE->get_renderer('tool_lp');

        $renderable = new \tool_lp\output\user_competency_summary($uc);
        return $renderable->export_for_template($output);
    }
81886
private function loadAssignments($userId)
    {
        if (!isset($this->_assignments[$userId])) {
            $query = (new Query)
                ->select('item_name')
                ->from($this->assignmentTable)
                ->where(['user_id' => $userId]);

            $this->_assignments[$userId] = $query->column($this->db);
        }
    }
859877
public static function get_contexts_for_userid(int $userid) : contextlist {
        global $DB;

        $contextlist = new contextlist();

        $publishstates = [
            NOTES_STATE_PUBLIC,
            NOTES_STATE_SITE
        ];
        list($publishstatesql, $publishstateparams) = $DB->get_in_or_equal($publishstates, SQL_PARAMS_NAMED);

        // Retrieve all the Course contexts associated with notes written by the user, and also written about the user.
        // Only notes written about the user that are public or site wide will be exported.
        $sql = "SELECT c.id
                  FROM {context} c
            INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcoursewrittenby
                 WHERE p.module = 'notes'
                   AND p.usermodified = :usermodified
                 UNION
                SELECT c.id
                  FROM {context} c
            INNER JOIN {post} p ON p.courseid = c.instanceid AND c.contextlevel = :contextcoursewrittenfor
                 WHERE p.module = 'notes'
                   AND p.userid = :userid
                   AND p.publishstate {$publishstatesql}";

        $params = [
            'contextcoursewrittenby'  => CONTEXT_COURSE,
            'usermodified'            => $userid,
            'contextcoursewrittenfor' => CONTEXT_COURSE,
            'userid'                  => $userid
        ];
        $params += $publishstateparams;

        $contextlist->add_from_sql($sql, $params);

        return $contextlist;
    }
1031025
public static function view_course($courseid, $sectionnumber = 0) {
        global $CFG;
        require_once($CFG->dirroot . "/course/lib.php");

        $params = self::validate_parameters(self::view_course_parameters(),
                                            array(
                                                'courseid' => $courseid,
                                                'sectionnumber' => $sectionnumber
                                            ));

        $warnings = array();

        $course = get_course($params['courseid']);
        $context = context_course::instance($course->id);
        self::validate_context($context);

        if (!empty($params['sectionnumber'])) {

            // Get section details and check it exists.
            $modinfo = get_fast_modinfo($course);
            $coursesection = $modinfo->get_section_info($params['sectionnumber'], MUST_EXIST);

            // Check user is allowed to see it.
            if (!$coursesection->uservisible) {
                require_capability('moodle/course:viewhiddensections', $context);
            }
        }

        course_view($context, $params['sectionnumber']);

        $result = array();
        $result['status'] = true;
        $result['warnings'] = $warnings;
        return $result;
    }
1357514
public static function block_user(int $userid, int $blockeduserid) {
        global $CFG, $USER;

        // Check if messaging is enabled.
        if (empty($CFG->messaging)) {
            throw new moodle_exception('disabled', 'message');
        }

        // Validate context.
        $context = context_system::instance();
        self::validate_context($context);

        $params = ['userid' => $userid, 'blockeduserid' => $blockeduserid];
        $params = self::validate_parameters(self::block_user_parameters(), $params);

        $capability = 'moodle/site:manageallmessaging';
        if (($USER->id != $params['userid']) && !has_capability($capability, $context)) {
            throw new required_capability_exception($context, $capability, 'nopermissions', '');
        }

        if (!\core_message\api::is_blocked($params['userid'], $params['blockeduserid'])) {
            \core_message\api::block_user($params['userid'], $params['blockeduserid']);
        }

        return [];
    }
980623
public static function get_module($id, $sectionreturn = null) {
        global $PAGE;
        // Validate and normalize parameters.
        $params = self::validate_parameters(self::get_module_parameters(),
            array('id' => $id, 'sectionreturn' => $sectionreturn));
        $id = $params['id'];
        $sectionreturn = $params['sectionreturn'];

        // Set of permissions an editing user may have.
        $contextarray = [
            'moodle/course:update',
            'moodle/course:manageactivities',
            'moodle/course:activityvisibility',
            'moodle/course:sectionvisibility',
            'moodle/course:movesections',
            'moodle/course:setcurrentsection',
        ];
        $PAGE->set_other_editing_capability($contextarray);

        // Validate access to the course (note, this is html for the course view page, we don't validate access to the module).
        list($course, $cm) = get_course_and_cm_from_cmid($id);
        self::validate_context(context_course::instance($course->id));

        $courserenderer = $PAGE->get_renderer('core', 'course');
        $completioninfo = new completion_info($course);
        return $courserenderer->course_section_cm_list_item($course, $completioninfo, $cm, $sectionreturn);
    }
32380
public static function get_grade_items($courseid, $userid = 0, $groupid = 0) {
        global $CFG, $USER;

        list($params, $course, $context, $user, $groupid) = self::check_report_access($courseid, $userid, $groupid);
        $userid   = $params['userid'];

        // We pass userid because it can be still 0.
        list($gradeitems, $warnings) = self::get_report_data($course, $context, $user, $userid, $groupid, false);

        foreach ($gradeitems as $gradeitem) {
            if (isset($gradeitem['feedback']) and isset($gradeitem['feedbackformat'])) {
                list($gradeitem['feedback'], $gradeitem['feedbackformat']) =
                    external_format_text($gradeitem['feedback'], $gradeitem['feedbackformat'], $context->id);
            }
        }

        $result = array();
        $result['usergrades'] = $gradeitems;
        $result['warnings'] = $warnings;
        return $result;
    }
730434
public static function data_for_plans_page($userid) {
        global $PAGE;

        $params = self::validate_parameters(self::data_for_plans_page_parameters(), array(
            'userid' => $userid,
        ));

        $context = context_user::instance($params['userid']);
        self::validate_context($context);
        $output = $PAGE->get_renderer('tool_lp');

        $renderable = new \tool_lp\output\plans_page($params['userid']);

        return $renderable->export_for_template($output);
    }
1252386
public static function create_subscription($ruleid, $courseid, $cmid, $userid = 0) {
        global $DB, $USER;

        $subscription = new \stdClass();
        $subscription->ruleid = $ruleid;
        $subscription->courseid = $courseid;
        $subscription->cmid = $cmid;
        $subscription->userid = empty($userid) ? $USER->id : $userid;
        if ($DB->record_exists('tool_monitor_subscriptions', (array)$subscription)) {
            // Subscription already exists.
            return false;
        }

        $subscription->timecreated = time();
        $subscription->id = $DB->insert_record('tool_monitor_subscriptions', $subscription);

        // Trigger a subscription created event.
        if ($subscription->id) {
            if (!empty($subscription->courseid)) {
                $courseid = $subscription->courseid;
                $context = \context_course::instance($subscription->courseid);
            } else {
                $courseid = 0;
                $context = \context_system::instance();
            }

            $params = array(
                'objectid' => $subscription->id,
                'courseid' => $courseid,
                'context' => $context
            );
            $event = \tool_monitor\event\subscription_created::create($params);
            $event->trigger();

            // Let's invalidate the cache.
            $cache = \cache::make('tool_monitor', 'eventsubscriptions');
            $cache->delete($courseid);
        }

        return $subscription->id;
    }