Exemplo n.º 1
0
/**
 * It add to the access ctrl array the data
 * needed by a user for a given context
 *
 * @param $userid  integer - the id of the user
 * @param $context context obj - needs path!
 * @param $accessdata array  accessdata array
 */
function load_subcontext($userid, $context, &$accessdata)
{
    global $CFG, $DB;
    /* Get the additional RAs and relevant rolecaps
     * - role assignments - with role_caps
     * - relevant role caps
     *   - above this user's RAs
     *   - below this user's RAs - limited to course level
     */
    $base = "/" . SYSCONTEXTID;
    //
    // Replace $context with the target context we will
    // load. Normally, this will be a course context, but
    // may be a different top-level context.
    //
    // We have 3 cases
    //
    // - Course
    // - BLOCK/PERSON/USER/COURSE(sitecourse) hanging from SYSTEM
    // - BLOCK/MODULE/GROUP hanging from a course
    //
    // For course contexts, we _already_ have the RAs
    // but the cost of re-fetching is minimal so we don't care.
    //
    if ($context->contextlevel !== CONTEXT_COURSE && $context->path !== "{$base}/{$context->id}") {
        // Case BLOCK/MODULE/GROUP hanging from a course
        // Assumption: the course _must_ be our parent
        // If we ever see stuff nested further this needs to
        // change to do 1 query over the exploded path to
        // find out which one is the course
        $courses = explode('/', get_course_from_path($context->path));
        $targetid = array_pop($courses);
        $context = get_context_instance_by_id($targetid);
    }
    //
    // Role assignments in the context and below
    //
    $sql = "SELECT ctx.path, ra.roleid\n              FROM {role_assignments} ra\n              JOIN {context} ctx\n                   ON ra.contextid=ctx.id\n             WHERE ra.userid = ?\n                   AND (ctx.path = ? OR ctx.path LIKE ?)\n          ORDER BY ctx.depth, ctx.path, ra.roleid";
    $params = array($userid, $context->path, $context->path . "/%");
    $rs = $DB->get_recordset_sql($sql, $params);
    //
    // Read in the RAs, preventing duplicates
    //
    if ($rs) {
        $localroles = array();
        $lastseen = '';
        foreach ($rs as $ra) {
            if (!isset($accessdata['ra'][$ra->path])) {
                $accessdata['ra'][$ra->path] = array();
            }
            // only add if is not a repeat caused
            // by capability join...
            // (this check is cheaper than in_array())
            if ($lastseen !== $ra->path . ':' . $ra->roleid) {
                $lastseen = $ra->path . ':' . $ra->roleid;
                array_push($accessdata['ra'][$ra->path], $ra->roleid);
                array_push($localroles, $ra->roleid);
            }
        }
        $rs->close();
    }
    //
    // Walk up and down the tree to grab all the roledefs
    // of interest to our user...
    //
    // NOTES
    // - we use IN() but the number of roles is very limited.
    //
    $courseroles = aggregate_roles_from_accessdata($context, $accessdata);
    // Do we have any interesting "local" roles?
    $localroles = array_diff($localroles, $courseroles);
    // only "new" local roles
    $wherelocalroles = '';
    if (count($localroles)) {
        // Role defs for local roles in 'higher' contexts...
        $contexts = substr($context->path, 1);
        // kill leading slash
        $contexts = str_replace('/', ',', $contexts);
        $localroleids = implode(',', $localroles);
        $wherelocalroles = "OR (rc.roleid IN ({$localroleids})\n                              AND ctx.id IN ({$contexts}))";
    }
    // We will want overrides for all of them
    $whereroles = '';
    if ($roleids = implode(',', array_merge($courseroles, $localroles))) {
        $whereroles = "rc.roleid IN ({$roleids}) AND";
    }
    $sql = "SELECT ctx.path, rc.roleid, rc.capability, rc.permission\n              FROM {role_capabilities} rc\n              JOIN {context} ctx\n                   ON rc.contextid=ctx.id\n             WHERE ({$whereroles}\n                    (ctx.id=? OR ctx.path LIKE ?))\n                   {$wherelocalroles}\n          ORDER BY ctx.depth ASC, ctx.path DESC, rc.roleid ASC ";
    $params = array($context->id, $context->path . "/%");
    $newrdefs = array();
    if ($rs = $DB->get_recordset_sql($sql, $params)) {
        foreach ($rs as $rd) {
            $k = "{$rd->path}:{$rd->roleid}";
            if (!array_key_exists($k, $newrdefs)) {
                $newrdefs[$k] = array();
            }
            $newrdefs[$k][$rd->capability] = $rd->permission;
        }
        $rs->close();
    } else {
        debugging('Bad SQL encountered!');
    }
    compact_rdefs($newrdefs);
    foreach ($newrdefs as $key => $value) {
        $accessdata['rdef'][$key] =& $newrdefs[$key];
    }
    // error_log("loaded {$context->path}");
    $accessdata['loaded'][] = $context->path;
}
Exemplo n.º 2
0
/**
 * It add to the access ctrl array the data
 * needed by a user for a given context
 *
 * @param $userid  integer - the id of the user
 * @param $context context obj - needs path!
 * @param $accessdata array  accessdata array
 *
 */
function get_user_access_bycontext($userid, $context, $accessdata = NULL)
{
    global $CFG;
    /* Get the additional RAs and relevant rolecaps
     * - role assignments - with role_caps
     * - relevant role caps
     *   - above this user's RAs
     *   - below this user's RAs - limited to course level
     */
    // Roles already in use in this context
    if (is_null($accessdata)) {
        $accessdata = array();
        // named list
        $accessdata['ra'] = array();
        $accessdata['rdef'] = array();
        $accessdata['loaded'] = array();
    }
    $base = "/" . SYSCONTEXTID;
    //
    // Replace $context with the target context we will
    // load. Normally, this will be a course context, but
    // may be a different top-level context.
    //
    // We have 3 cases
    //
    // - Course
    // - BLOCK/PERSON/USER/COURSE(sitecourse) hanging from SYSTEM
    // - BLOCK/MODULE/GROUP hanging from a course
    //
    // For course contexts, we _already_ have the RAs
    // but the cost of re-fetching is minimal so we don't care.
    //
    if ($context->contextlevel !== CONTEXT_COURSE && $context->path !== "{$base}/{$context->id}") {
        // Case BLOCK/MODULE/GROUP hanging from a course
        // Assumption: the course _must_ be our parent
        // If we ever see stuff nested further this needs to
        // change to do 1 query over the exploded path to
        // find out which one is the course
        $targetid = array_pop(explode('/', get_course_from_path($context->path)));
        $context = get_context_instance_by_id($targetid);
    }
    //
    // Role assignments in the context and below
    //
    $sql = "SELECT ctx.path, ra.roleid\n            FROM {$CFG->prefix}role_assignments ra\n            JOIN {$CFG->prefix}context ctx\n               ON ra.contextid=ctx.id\n            WHERE ra.userid = {$userid}\n                  AND (ctx.path = '{$context->path}' OR ctx.path LIKE '{$context->path}/%')\n            ORDER BY ctx.depth, ctx.path";
    $rs = get_recordset_sql($sql);
    //
    // Read in the RAs
    //
    $localroles = array();
    if ($rs->RecordCount()) {
        while ($ra = rs_fetch_next_record($rs)) {
            if (!isset($accessdata['ra'][$ra->path])) {
                $accessdata['ra'][$ra->path] = array();
            }
            array_push($accessdata['ra'][$ra->path], $ra->roleid);
            array_push($localroles, $ra->roleid);
        }
    }
    rs_close($rs);
    //
    // Walk up and down the tree to grab all the roledefs
    // of interest to our user...
    //
    // NOTES
    // - we use IN() but the number of roles is very limited.
    //
    $courseroles = aggregate_roles_from_accessdata($context, $accessdata);
    // Do we have any interesting "local" roles?
    $localroles = array_diff($localroles, $courseroles);
    // only "new" local roles
    $wherelocalroles = '';
    if (count($localroles)) {
        // Role defs for local roles in 'higher' contexts...
        $contexts = substr($context->path, 1);
        // kill leading slash
        $contexts = str_replace('/', ',', $contexts);
        $localroleids = implode(',', $localroles);
        $wherelocalroles = "OR (rc.roleid IN ({$localroleids}) \n                              AND ctx.id IN ({$contexts}))";
    }
    // We will want overrides for all of them
    $whereroles = '';
    if ($roleids = implode(',', array_merge($courseroles, $localroles))) {
        $whereroles = "rc.roleid IN ({$roleids}) AND";
    }
    $sql = "SELECT ctx.path, rc.roleid, rc.capability, rc.permission\n            FROM {$CFG->prefix}role_capabilities rc\n            JOIN {$CFG->prefix}context ctx\n             ON rc.contextid=ctx.id\n            WHERE ({$whereroles}\n                    (ctx.id={$context->id} OR ctx.path LIKE '{$context->path}/%'))\n                    {$wherelocalroles}\n            ORDER BY ctx.depth ASC, ctx.path DESC, rc.roleid ASC ";
    if ($rs = get_recordset_sql($sql)) {
        if ($rs->RecordCount()) {
            while ($rd = rs_fetch_next_record($rs)) {
                $k = "{$rd->path}:{$rd->roleid}";
                $accessdata['rdef'][$k][$rd->capability] = $rd->permission;
            }
        }
        rs_close($rs);
    } else {
        debugging('Bad SQL encountered!');
    }
    // TODO: compact capsets?
    error_log("loaded {$context->path}");
    $accessdata['loaded'][] = $context->path;
    return $accessdata;
}