Esempio n. 1
0
/**
 * Get an array of courses (with magic extra bits)
 * where the accessdata and in DB enrolments show
 * that the cap requested is available.
 *
 * The main use is for get_my_courses().
 *
 * Notes
 *
 * - $fields is an array of fieldnames to ADD
 *   so name the fields you really need, which will
 *   be added and uniq'd
 *
 * - the course records have $c->context which is a fully
 *   valid context object. Saves you a query per course!
 *
 * - the course records have $c->categorypath to make
 *   category lookups cheap
 *
 * - current implementation is split in -
 *
 *   - if the user has the cap systemwide, stupidly
 *     grab *every* course for a capcheck. This eats
 *     a TON of bandwidth, specially on large sites
 *     with separate DBs...
 *
 *   - otherwise, fetch "likely" courses with a wide net
 *     that should get us _cheaply_ at least the courses we need, and some
 *     we won't - we get courses that...
 *      - are in a category where user has the cap
 *      - or where use has a role-assignment (any kind)
 *      - or where the course has an override on for this cap
 *
 *   - walk the courses recordset checking the caps oneach one
 *     the checks are all in memory and quite fast
 *     (though we could implement a specialised variant of the
 *     has_capability_in_accessdata() code to speed it up)
 *
 * @param string $capability - name of the capability
 * @param array  $accessdata - accessdata session array
 * @param bool   $doanything - if false, ignore do anything
 * @param string $sort - sorting fields - prefix each fieldname with "c."
 * @param array  $fields - additional fields you are interested in...
 * @param int    $limit  - set if you want to limit the number of courses
 * @return array $courses - ordered array of course objects - see notes above
 *
 */
function get_user_courses_bycap($userid, $cap, $accessdata, $doanything, $sort = 'c.sortorder ASC', $fields = NULL, $limit = 0)
{
    global $CFG, $DB;
    // Slim base fields, let callers ask for what they need...
    $basefields = array('id', 'sortorder', 'shortname', 'idnumber');
    if (!is_null($fields)) {
        $fields = array_merge($basefields, $fields);
        $fields = array_unique($fields);
    } else {
        $fields = $basefields;
    }
    // If any of the fields is '*', leave it alone, discarding the rest
    // to avoid ambiguous columns under some silly DBs. See MDL-18746 :-D
    if (in_array('*', $fields)) {
        $fields = array('*');
    }
    $coursefields = 'c.' . implode(',c.', $fields);
    $sort = trim($sort);
    if ($sort !== '') {
        $sort = "ORDER BY {$sort}";
    }
    $sysctx = get_context_instance(CONTEXT_SYSTEM);
    if (has_capability_in_accessdata($cap, $sysctx, $accessdata, $doanything)) {
        //
        // Apparently the user has the cap sitewide, so walk *every* course
        // (the cap checks are moderately fast, but this moves massive bandwidth w the db)
        // Yuck.
        //
        $sql = "SELECT {$coursefields},\n                       ctx.id AS ctxid, ctx.path AS ctxpath,\n                       ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel,\n                       cc.path AS categorypath\n                  FROM {course} c\n                  JOIN {course_categories} cc\n                       ON c.category=cc.id\n                  JOIN {context} ctx\n                       ON (c.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSE . ")\n                 {$sort} ";
        $rs = $DB->get_recordset_sql($sql);
    } else {
        //
        // narrow down where we have the caps to a few contexts
        // this will be a combination of
        // - courses    where user has an explicit enrolment
        // - courses    that have an override (any status) on that capability
        // - categories where user has the rights (granted status) on that capability
        //
        $sql = "SELECT ctx.*\n                  FROM {context} ctx\n                 WHERE ctx.contextlevel=" . CONTEXT_COURSECAT . "\n              ORDER BY ctx.depth";
        $rs = $DB->get_recordset_sql($sql);
        $catpaths = array();
        foreach ($rs as $catctx) {
            if ($catctx->path != '' && has_capability_in_accessdata($cap, $catctx, $accessdata, $doanything)) {
                $catpaths[] = $catctx->path;
            }
        }
        $rs->close();
        $catclause = '';
        $params = array();
        if (count($catpaths)) {
            $cc = count($catpaths);
            for ($n = 0; $n < $cc; $n++) {
                $catpaths[$n] = "ctx.path LIKE '{$catpaths[$n]}/%'";
            }
            $catclause = 'WHERE (' . implode(' OR ', $catpaths) . ')';
        }
        unset($catpaths);
        $capany = '';
        if ($doanything) {
            $capany = " OR rc.capability=:doany";
            $params['doany'] = 'moodle/site:doanything';
        }
        /// UNION 3 queries:
        /// - user role assignments in courses
        /// - user capability (override - any status) in courses
        /// - user right (granted status) in categories (optionally executed)
        /// Enclosing the 3-UNION into an inline_view to avoid column names conflict and making the ORDER BY cross-db
        /// and to allow selection of TEXT columns in the query (MSSQL and Oracle limitation). MDL-16209
        $sql = "\n            SELECT {$coursefields}, ctxid, ctxpath, ctxdepth, ctxlevel, categorypath\n              FROM (\n                    SELECT c.id,\n                           ctx.id AS ctxid, ctx.path AS ctxpath,\n                           ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel,\n                           cc.path AS categorypath\n                    FROM {course} c\n                    JOIN {course_categories} cc\n                      ON c.category=cc.id\n                    JOIN {context} ctx\n                      ON (c.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSE . ")\n                    JOIN {role_assignments} ra\n                      ON (ra.contextid=ctx.id AND ra.userid=:userid)\n                    UNION\n                    SELECT c.id,\n                           ctx.id AS ctxid, ctx.path AS ctxpath,\n                           ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel,\n                           cc.path AS categorypath\n                    FROM {course} c\n                    JOIN {course_categories} cc\n                      ON c.category=cc.id\n                    JOIN {context} ctx\n                      ON (c.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSE . ")\n                    JOIN {role_capabilities} rc\n                      ON (rc.contextid=ctx.id AND (rc.capability=:cap {$capany})) ";
        if (!empty($catclause)) {
            /// If we have found the right in categories, add child courses here too
            $sql .= "\n                    UNION\n                    SELECT c.id,\n                           ctx.id AS ctxid, ctx.path AS ctxpath,\n                           ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel,\n                           cc.path AS categorypath\n                    FROM {course} c\n                    JOIN {course_categories} cc\n                      ON c.category=cc.id\n                    JOIN {context} ctx\n                      ON (c.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSE . ")\n                    {$catclause}";
        }
        /// Close the inline_view and join with courses table to get requested $coursefields
        $sql .= "\n                ) inline_view\n                INNER JOIN {course} c\n                    ON inline_view.id = c.id";
        /// To keep cross-db we need to strip any prefix in the ORDER BY clause for queries using UNION
        $sql .= "\n                " . preg_replace('/[a-z]+\\./i', '', $sort);
        /// Add ORDER BY clause
        $params['userid'] = $userid;
        $params['cap'] = $cap;
        $rs = $DB->get_recordset_sql($sql, $params);
    }
    /// Confirm rights (granted capability) for each course returned
    $courses = array();
    $cc = 0;
    // keep count
    if ($rs) {
        foreach ($rs as $c) {
            // build the context obj
            $c = make_context_subobj($c);
            if (has_capability_in_accessdata($cap, $c->context, $accessdata, $doanything)) {
                $courses[] = $c;
                if ($limit > 0 && $cc++ > $limit) {
                    break;
                }
            }
        }
        $rs->close();
    }
    return $courses;
}
Esempio n. 2
0
 // only show the plugin if multiple enrolment plugins
 // are enabled...
 if (strpos($CFG->enrol_plugins_enabled, ',') === false) {
     $showenrolplugin = true;
 } else {
     $showenrolplugin = false;
 }
 $usersprinted = array();
 foreach ($userlist as $user) {
     if (in_array($user->id, $usersprinted)) {
         /// Prevent duplicates by r.hidden - MDL-13935
         continue;
     }
     $usersprinted[] = $user->id;
     /// Add new user to the array of users printed
     $user = make_context_subobj($user);
     if (!empty($user->hidden)) {
         // if the assignment is hidden, display icon
         $hidden = " <img src=\"{$CFG->pixpath}/t/show.gif\" title=\"" . get_string('userhashiddenassignments', 'role') . "\" alt=\"" . get_string('hiddenassign') . "\" class=\"hide-show-image\"/>";
     } else {
         $hidden = '';
     }
     if ($user->lastaccess) {
         $lastaccess = format_time(time() - $user->lastaccess, $datestring);
     } else {
         $lastaccess = $strnever;
     }
     if (empty($user->country)) {
         $country = '';
     } else {
         if ($countrysort) {
Esempio n. 3
0
/**
 * Returns a sorted list of categories. Each category object has a context
 * property that is a context object.
 *
 * When asking for $parent='none' it will return all the categories, regardless
 * of depth. Wheen asking for a specific parent, the default is to return
 * a "shallow" resultset. Pass false to $shallow and it will return all
 * the child categories as well.
 *
 *
 * @param string $parent The parent category if any
 * @param string $sort the sortorder
 * @param bool   $shallow - set to false to get the children too
 * @return array of categories
 */
function get_categories($parent = 'none', $sort = NULL, $shallow = true)
{
    global $DB;
    if ($sort === NULL) {
        $sort = 'ORDER BY cc.sortorder ASC';
    } elseif ($sort === '') {
        // leave it as empty
    } else {
        $sort = "ORDER BY {$sort}";
    }
    if ($parent === 'none') {
        $sql = "SELECT cc.*,\n                       ctx.id AS ctxid, ctx.path AS ctxpath,\n                       ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel\n                  FROM {course_categories} cc\n                  JOIN {context} ctx\n                       ON cc.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSECAT . "\n                {$sort}";
        $params = array();
    } elseif ($shallow) {
        $sql = "SELECT cc.*,\n                       ctx.id AS ctxid, ctx.path AS ctxpath,\n                       ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel\n                  FROM {course_categories} cc\n                  JOIN {context} ctx\n                       ON cc.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSECAT . "\n                 WHERE cc.parent=?\n                {$sort}";
        $params = array($parent);
    } else {
        $sql = "SELECT cc.*,\n                       ctx.id AS ctxid, ctx.path AS ctxpath,\n                       ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel\n                  FROM {course_categories} cc\n                  JOIN {context} ctx\n                       ON cc.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSECAT . "\n                  JOIN {course_categories} ccp\n                       ON (cc.path LIKE " . $DB->sql_concat('ccp.path', "'%'") . ")\n                 WHERE ccp.id=?\n                {$sort}";
        $params = array($parent);
    }
    $categories = array();
    if ($rs = $DB->get_recordset_sql($sql, $params)) {
        foreach ($rs as $cat) {
            $cat = make_context_subobj($cat);
            if ($cat->visible || has_capability('moodle/category:viewhiddencategories', $cat->context)) {
                $categories[$cat->id] = $cat;
            }
        }
        $rs->close();
    }
    return $categories;
}
Esempio n. 4
0
/**
 * Returns a sorted list of categories. Each category object has a context
 * property that is a context object.
 *
 * When asking for $parent='none' it will return all the categories, regardless
 * of depth. Wheen asking for a specific parent, the default is to return
 * a "shallow" resultset. Pass false to $shallow and it will return all
 * the child categories as well.
 *
 *
 * @param string $parent The parent category if any
 * @param string $sort the sortorder
 * @param bool   $shallow - set to false to get the children too
 * @return array of categories
 */
function get_categories($parent = 'none', $sort = NULL, $shallow = true)
{
    global $CFG;
    if ($sort === NULL) {
        $sort = 'ORDER BY cc.sortorder ASC';
    } elseif ($sort === '') {
        // leave it as empty
    } else {
        $sort = "ORDER BY {$sort}";
    }
    if ($parent === 'none') {
        $sql = "SELECT cc.*,\n                      ctx.id AS ctxid, ctx.path AS ctxpath,\n                      ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel\n                FROM {$CFG->prefix}course_categories cc\n                JOIN {$CFG->prefix}context ctx\n                  ON cc.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSECAT . "\n                {$sort}";
    } elseif ($shallow) {
        $parent = (int) $parent;
        $sql = "SELECT cc.*,\n                       ctx.id AS ctxid, ctx.path AS ctxpath,\n                       ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel\n                FROM {$CFG->prefix}course_categories cc\n                JOIN {$CFG->prefix}context ctx\n                  ON cc.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSECAT . "\n                WHERE cc.parent={$parent}\n                {$sort}";
    } else {
        $parent = (int) $parent;
        $sql = "SELECT cc.*,\n                       ctx.id AS ctxid, ctx.path AS ctxpath,\n                       ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel\n                FROM {$CFG->prefix}course_categories cc\n                JOIN {$CFG->prefix}context ctx\n                  ON cc.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSECAT . "\n                JOIN {$CFG->prefix}course_categories ccp\n                     ON (cc.path LIKE " . sql_concat('ccp.path', "'%'") . ")\n                WHERE ccp.id={$parent}\n                {$sort}";
    }
    $categories = array();
    if ($rs = get_recordset_sql($sql)) {
        while ($cat = rs_fetch_next_record($rs)) {
            $cat = make_context_subobj($cat);
            if ($cat->visible || has_capability('moodle/category:visibility', $cat->context)) {
                $categories[$cat->id] = $cat;
            }
        }
    }
    return $categories;
}
Esempio n. 5
0
function get_context_users_bycap($context, $capability = 'moodle/course:view', $fields = NULL, $where = NULL, $sort = NULL, $limit = 0)
{
    global $CFG;
    // Plan
    //
    // - Get all the *interesting* roles -- those that
    //   have some rolecap entry in our ctx.path contexts
    //
    // - Get all RAs for any of those roles in any of our
    //   interesting contexts, with userid & perm data
    //   in a nice (per user?) order
    //
    // - Walk the resultset, computing the permissions
    //   - actually - this is all a SQL subselect
    //
    // - Fetch user records against the subselect
    //
    // Slim base fields, let callers ask for what they need...
    $basefields = array('id', 'username');
    if (!is_null($fields)) {
        $fields = array_merge($basefields, $fields);
        $fields = array_unique($fields);
    } else {
        $fields = $basefields;
    }
    $userfields = 'u.' . implode(',u.', $fields);
    $contexts = substr($context->path, 1);
    // kill leading slash
    $contexts = str_replace('/', ',', $contexts);
    $roles = array();
    $sql = "SELECT DISTINCT rc.roleid\n            FROM {$CFG->prefix}role_capabilities rc\n            WHERE rc.capability = '{$capability}'\n                  AND rc.contextid IN ({$contexts})";
    $rs = get_recordset_sql($sql);
    if ($rs->RecordCount()) {
        while ($u = rs_fetch_next_record($rs)) {
            $roles[] = $u->roleid;
        }
    }
    rs_close($rs);
    $roles = implode(',', $roles);
    //
    // User permissions subselect SQL
    //
    // - the open join condition to
    //   role_capabilities
    //
    // - because both rc and ra entries are
    //   _at or above_ our context, we don't care
    //   about their depth, we just need to sum them
    //
    $sql = "SELECT ra.userid, SUM(rc.permission) AS permission\n            FROM {$CFG->prefix}role_assignments ra\n            JOIN {$CFG->prefix}role_capabilities rc\n              ON (ra.roleid = rc.roleid AND rc.contextid IN ({$contexts}))\n            WHERE     ra.contextid  IN ({$contexts})\n                  AND ra.roleid IN ({$roles})\n            GROUP BY ra.userid";
    // Get users
    $sql = "SELECT {$userfields},\n                   ctx.id AS ctxid, ctx.path AS ctxpath,\n                   ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel\n            FROM {$CFG->prefix}user u\n            JOIN {$CFG->prefix}context ctx \n              ON (u.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_USER . ")\n            JOIN ({$sql}) up\n              ON u.id = up.userid\n            WHERE up.permission > 0 AND u.username != 'guest'";
    $rs = get_recordset_sql($sql);
    $users = array();
    $cc = 0;
    // keep count
    if ($rs->RecordCount()) {
        while ($u = rs_fetch_next_record($rs)) {
            // build the context obj
            $u = make_context_subobj($u);
            $users[] = $u;
            if ($limit > 0 && $cc++ > $limit) {
                break;
            }
        }
    }
    rs_close($rs);
    return $users;
}
Esempio n. 6
0
/**
 * Get an array of courses (with magic extra bits)
 * where the accessdata and in DB enrolments show
 * that the cap requested is available.
 *
 * The main use is for get_my_courses().
 *
 * Notes
 *
 * - $fields is an array of fieldnames to ADD
 *   so name the fields you really need, which will
 *   be added and uniq'd
 *
 * - the course records have $c->context which is a fully
 *   valid context object. Saves you a query per course!
 *
 * - the course records have $c->categorypath to make
 *   category lookups cheap
 *
 * - current implementation is split in -
 *
 *   - if the user has the cap systemwide, stupidly
 *     grab *every* course for a capcheck. This eats
 *     a TON of bandwidth, specially on large sites 
 *     with separate DBs...
 *
 *   - otherwise, fetch "likely" courses with a wide net
 *     that should get us _cheaply_ at least the courses we need, and some
 *     we won't - we get courses that...
 *      - are in a category where user has the cap
 *      - or where use has a role-assignment (any kind)
 *      - or where the course has an override on for this cap
 *
 *   - walk the courses recordset checking the caps oneach one
 *     the checks are all in memory and quite fast
 *     (though we could implement a specialised variant of the
 *     has_capability_in_accessdata() code to speed it up)
 *
 * @param string $capability - name of the capability
 * @param array  $accessdata - accessdata session array
 * @param bool   $doanything - if false, ignore do anything
 * @param string $sort - sorting fields - prefix each fieldname with "c."
 * @param array  $fields - additional fields you are interested in...
 * @param int    $limit  - set if you want to limit the number of courses
 * @return array $courses - ordered array of course objects - see notes above
 *
 */
function get_user_courses_bycap($userid, $cap, $accessdata, $doanything, $sort = 'c.sortorder ASC', $fields = NULL, $limit = 0)
{
    global $CFG;
    // Slim base fields, let callers ask for what they need...
    $basefields = array('id', 'sortorder', 'shortname', 'idnumber');
    if (!is_null($fields)) {
        $fields = array_merge($basefields, $fields);
        $fields = array_unique($fields);
    } else {
        $fields = $basefields;
    }
    $coursefields = 'c.' . implode(',c.', $fields);
    $sort = trim($sort);
    if ($sort !== '') {
        $sort = "ORDER BY {$sort}";
    }
    $sysctx = get_context_instance(CONTEXT_SYSTEM);
    if (has_capability_in_accessdata($cap, $sysctx, $accessdata, $doanything)) {
        //
        // Apparently the user has the cap sitewide, so walk *every* course
        // (the cap checks are moderately fast, but this moves massive bandwidth w the db)
        // Yuck.
        //
        $sql = "SELECT {$coursefields},\n                       ctx.id AS ctxid, ctx.path AS ctxpath,\n                       ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel,\n                       cc.path AS categorypath\n                FROM {$CFG->prefix}course c\n                JOIN {$CFG->prefix}course_categories cc\n                  ON c.category=cc.id\n                JOIN {$CFG->prefix}context ctx \n                  ON (c.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSE . ")\n                {$sort} ";
        $rs = get_recordset_sql($sql);
    } else {
        //
        // narrow down where we have the caps to a few contexts
        // this will be a combination of
        // - categories where we have the rights
        // - courses    where we have an explicit enrolment OR that have an override
        //
        $sql = "SELECT ctx.*\n                FROM   {$CFG->prefix}context ctx\n                WHERE  ctx.contextlevel=" . CONTEXT_COURSECAT . "\n                ORDER BY ctx.depth";
        $rs = get_recordset_sql($sql);
        $catpaths = array();
        while ($catctx = rs_fetch_next_record($rs)) {
            if ($catctx->path != '' && has_capability_in_accessdata($cap, $catctx, $accessdata, $doanything)) {
                $catpaths[] = $catctx->path;
            }
        }
        rs_close($rs);
        $catclause = '';
        if (count($catpaths)) {
            $cc = count($catpaths);
            for ($n = 0; $n < $cc; $n++) {
                $catpaths[$n] = "ctx.path LIKE '{$catpaths[$n]}/%'";
            }
            $catclause = 'OR (' . implode(' OR ', $catpaths) . ')';
        }
        unset($catpaths);
        $capany = '';
        if ($doanything) {
            $capany = " OR rc.capability='moodle/site:doanything'";
        }
        //
        // Note here that we *have* to have the compound clauses
        // in the LEFT OUTER JOIN condition for them to return NULL
        // appropriately and narrow things down...
        //
        $sql = "SELECT {$coursefields},\n                       ctx.id AS ctxid, ctx.path AS ctxpath,\n                       ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel,\n                       cc.path AS categorypath\n                FROM {$CFG->prefix}course c\n                JOIN {$CFG->prefix}course_categories cc\n                  ON c.category=cc.id\n                JOIN {$CFG->prefix}context ctx \n                  ON (c.id=ctx.instanceid AND ctx.contextlevel=" . CONTEXT_COURSE . ")\n                LEFT OUTER JOIN {$CFG->prefix}role_assignments ra\n                  ON (ra.contextid=ctx.id AND ra.userid={$userid})\n                LEFT OUTER JOIN {$CFG->prefix}role_capabilities rc\n                  ON (rc.contextid=ctx.id AND (rc.capability='{$cap}' {$capany}))\n                WHERE    ra.id IS NOT NULL\n                      OR rc.id IS NOT NULL\n                      {$catclause}\n                {$sort} ";
        $rs = get_recordset_sql($sql);
    }
    $courses = array();
    $cc = 0;
    // keep count
    while ($c = rs_fetch_next_record($rs)) {
        // build the context obj
        $c = make_context_subobj($c);
        if (has_capability_in_accessdata($cap, $c->context, $accessdata, $doanything)) {
            $courses[] = $c;
            if ($limit > 0 && $cc++ > $limit) {
                break;
            }
        }
    }
    rs_close($rs);
    return $courses;
}
Esempio n. 7
0
 /**
  * This method actually loads the blocks for our page from the database.
  *
  * @param boolean|null $includeinvisible
  *      null (default) - load hidden blocks if $this->page->user_is_editing();
  *      true - load hidden blocks.
  *      false - don't load hidden blocks.
  */
 public function load_blocks($includeinvisible = null)
 {
     global $DB, $CFG;
     if (!is_null($this->birecordsbyregion)) {
         // Already done.
         return;
     }
     if ($CFG->version < 2009050619) {
         // Upgrade/install not complete. Don't try too show any blocks.
         $this->birecordsbyregion = array();
         return;
     }
     // Ensure we have been initialised.
     if (!isset($this->defaultregion)) {
         $this->page->initialise_theme_and_output();
         // If there are still no block regions, then there are no blocks on this page.
         if (empty($this->regions)) {
             $this->birecordsbyregion = array();
             return;
         }
     }
     if (is_null($includeinvisible)) {
         $includeinvisible = $this->page->user_is_editing();
     }
     if ($includeinvisible) {
         $visiblecheck = '';
     } else {
         $visiblecheck = 'AND (bp.visible = 1 OR bp.visible IS NULL)';
     }
     $context = $this->page->context;
     $contexttest = 'bi.parentcontextid = :contextid2';
     $parentcontextparams = array();
     $parentcontextids = get_parent_contexts($context);
     if ($parentcontextids) {
         list($parentcontexttest, $parentcontextparams) = $DB->get_in_or_equal($parentcontextids, SQL_PARAMS_NAMED, 'parentcontext0000');
         $contexttest = "({$contexttest} OR (bi.showinsubcontexts = 1 AND bi.parentcontextid {$parentcontexttest}))";
     }
     $pagetypepatterns = matching_page_type_patterns($this->page->pagetype);
     list($pagetypepatterntest, $pagetypepatternparams) = $DB->get_in_or_equal($pagetypepatterns, SQL_PARAMS_NAMED, 'pagetypepatterntest0000');
     $params = array('subpage1' => $this->page->subpage, 'subpage2' => $this->page->subpage, 'contextid1' => $context->id, 'contextid2' => $context->id, 'pagetype' => $this->page->pagetype, 'contextblock' => CONTEXT_BLOCK);
     $sql = "SELECT\n                    bi.id,\n                    bp.id AS blockpositionid,\n                    bi.blockname,\n                    bi.parentcontextid,\n                    bi.showinsubcontexts,\n                    bi.pagetypepattern,\n                    bi.subpagepattern,\n                    bi.defaultregion,\n                    bi.defaultweight,\n                    COALESCE(bp.visible, 1) AS visible,\n                    COALESCE(bp.region, bi.defaultregion) AS region,\n                    COALESCE(bp.weight, bi.defaultweight) AS weight,\n                    bi.configdata,\n                    ctx.id AS ctxid,\n                    ctx.path AS ctxpath,\n                    ctx.depth AS ctxdepth,\n                    ctx.contextlevel AS ctxlevel\n\n                FROM {block_instances} bi\n                JOIN {block} b ON bi.blockname = b.name\n                LEFT JOIN {block_positions} bp ON bp.blockinstanceid = bi.id\n                                                  AND bp.contextid = :contextid1\n                                                  AND bp.pagetype = :pagetype\n                                                  AND bp.subpage = :subpage1\n                JOIN {context} ctx ON ctx.contextlevel = :contextblock\n                                      AND ctx.instanceid = bi.id\n\n                WHERE\n                {$contexttest}\n                AND bi.pagetypepattern {$pagetypepatterntest}\n                AND (bi.subpagepattern IS NULL OR bi.subpagepattern = :subpage2)\n                {$visiblecheck}\n                AND b.visible = 1\n\n                ORDER BY\n                    COALESCE(bp.region, bi.defaultregion),\n                    COALESCE(bp.weight, bi.defaultweight),\n                    bi.id";
     $blockinstances = $DB->get_recordset_sql($sql, $params + $parentcontextparams + $pagetypepatternparams);
     $this->birecordsbyregion = $this->prepare_per_region_arrays();
     $unknown = array();
     foreach ($blockinstances as $bi) {
         $bi = make_context_subobj($bi);
         if ($this->is_known_region($bi->region)) {
             $this->birecordsbyregion[$bi->region][] = $bi;
         } else {
             $unknown[] = $bi;
         }
     }
     // Pages don't necessarily have a defaultregion. The  one time this can
     // happen is when there are no theme block regions, but the script itself
     // has a block region in the main content area.
     if (!empty($this->defaultregion)) {
         $this->birecordsbyregion[$this->defaultregion] = array_merge($this->birecordsbyregion[$this->defaultregion], $unknown);
     }
 }