protected static function create_sql($parent) {
        global $DB;

        $sql = '';
        $params = [];
        if ($parent->path !== null) {
            // Except for the root element, create the condition that it applies to the context of
            // this element (or anything within it).
            $sql = ' (x.path = ? OR ' . $DB->sql_like('x.path', '?') .')';
            $params[] = $parent->path;
            $params[] = $parent->path . '/%';
            if ($parent->children) {
                // When there are children, these are assumed to have the opposite sign i.e. if we
                // are allowing the parent, we are not allowing the children, and vice versa. So
                // the 'OR' clause for children will be inside this 'AND NOT'.
                $sql .= ' AND NOT (';
            }
        } else if (count($parent->children) > 1) {
            // Place brackets in the query when it is going to be an OR of multiple conditions.
            $sql .= ' (';
        }
        if ($parent->children) {
            $first = true;
            foreach ($parent->children as $child) {
                if ($first) {
                    $first = false;
                } else {
                    $sql  .= ' OR';
                }

                // Recuse to get the child requirements - this will be the check that the context
                // is within the child, plus possibly and 'AND NOT' for any different contexts
                // within the child.
                list ($childsql, $childparams) = self::create_sql($child);
                $sql .= $childsql;
                $params = array_merge($params, $childparams);
            }
            // Close brackets if opened above.
            if ($parent->path !== null || count($parent->children) > 1) {
                $sql .= ')';
            }
        }
        return [$sql, $params];
    }
protected static function create_sql($parent) {
        global $DB;

        $sql = '';
        $params = [];
        if ($parent->path !== null) {
            // Except for the root element, create the condition that it applies to the context of
            // this element (or anything within it).
            $sql = ' (x.path = ? OR ' . $DB->sql_like('x.path', '?') .')';
            $params[] = $parent->path;
            $params[] = $parent->path . '/%';
            if ($parent->children) {
                // When there are children, these are assumed to have the opposite sign i.e. if we
                // are allowing the parent, we are not allowing the children, and vice versa. So
                // the 'OR' clause for children will be inside this 'AND NOT'.
                $sql .= ' AND NOT (';
            }
        } else if (count($parent->children) > 1) {
            // Place brackets in the query when it is going to be an OR of multiple conditions.
            $sql .= ' (';
        }
        if ($parent->children) {
            $first = true;
            foreach ($parent->children as $child) {
                if ($first) {
                    $first = false;
                } else {
                    $sql  .= ' OR';
                }

                // Recuse to get the child requirements - this will be the check that the context
                // is within the child, plus possibly and 'AND NOT' for any different contexts
                // within the child.
                list ($childsql, $childparams) = self::create_sql($child);
                $sql .= $childsql;
                $params = array_merge($params, $childparams);
            }
            // Close brackets if opened above.
            if ($parent->path !== null || count($parent->children) > 1) {
                $sql .= ')';
            }
        }
        return [$sql, $params];
    }
protected static function create_sql ( $ parent ) { global $ DB ; $ sql = '' ; $ params = [ ] ; if ( $ parent -> path !== null ) { // Except for the root element, create the condition that it applies to the context of // this element (or anything within it). $ sql = ' (x.path = ? OR ' . $ DB -> sql_like ( 'x.path' , '?' ) . ')' ; $ params [ ] = $ parent -> path ; $ params [ ] = $ parent -> path . '/%' ; if ( $ parent -> children ) { // When there are children, these are assumed to have the opposite sign i.e. if we // are allowing the parent, we are not allowing the children, and vice versa. So // the 'OR' clause for children will be inside this 'AND NOT'. $ sql .= ' AND NOT (' ; } } else if ( count ( $ parent -> children ) > 1 ) { // Place brackets in the query when it is going to be an OR of multiple conditions. $ sql .= ' (' ; } if ( $ parent -> children ) { $ first = true ; foreach ( $ parent -> children as $ child ) { if ( $ first ) { $ first = false ; } else { $ sql .= ' OR' ; } // Recuse to get the child requirements - this will be the check that the context // is within the child, plus possibly and 'AND NOT' for any different contexts // within the child. list ( $ childsql , $ childparams ) = self :: create_sql ( $ child ) ; $ sql .= $ childsql ; $ params = array_merge ( $ params , $ childparams ) ; } // Close brackets if opened above. if ( $ parent -> path !== null || count ( $ parent -> children ) > 1 ) { $ sql .= ')' ; } } return [ $ sql , $ params ] ; }
Creates SQL suitable for restricting by contexts listed in the given permission tree.

This function relies on the permission tree being in the format created by get_tree.
Specifically, all the children of the root element must be set to 'allow' permission,
children of those children must be 'not allow', children of those grandchildren 'allow', etc.

@param \stdClass $parent Root node of permission tree
@return array Two-element array of SQL (containing ? placeholders) and then a params array
Creates SQL suitable for restricting by contexts listed in the given permission tree .