public function tree($column, $field = null, $value = null, $having = null)
    {
        $tree = array();
        if (func_num_args() >= 3) {
            $depth = (is_string($having) && strpos($having, 'depth') !== false) ? ' HAVING '.$having : null;
            $stmt = $this->db->query(array(
                'SELECT node.'.$this->id.', '.$this->fields('node', (array) $column).', node.parent, (COUNT(parent.'.$this->id.') - (sub_tree.sub_depth + 1)) AS depth',
                'FROM '.$this->table.' AS node',
                'INNER JOIN '.$this->table.' AS parent',
                'INNER JOIN '.$this->table.' AS sub_parent',
                'INNER JOIN (',
                '    SELECT node.'.$this->id.', (COUNT(parent.'.$this->id.') - 1) AS sub_depth',
                '    FROM '.$this->table.' AS node',
                '    INNER JOIN '.$this->table.' AS parent',
                '    WHERE node.lft BETWEEN parent.lft AND parent.rgt',
                '    AND node.'.$field.' = ?',
                '    GROUP BY node.'.$this->id,
                '    ORDER BY node.lft',
                ') AS sub_tree',
                'WHERE node.lft BETWEEN parent.lft AND parent.rgt',
                '    AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt',
                '    AND sub_parent.'.$this->id.' = sub_tree.'.$this->id,
                'GROUP BY node.'.$this->id.$depth,
                'ORDER BY node.lft',
            ), $value, 'assoc');
        } else {
            $depth = (is_string($field) && strpos($field, 'depth') !== false) ? ' HAVING '.$field : null;
            $stmt = $this->db->query(array(
                'SELECT node.'.$this->id.', '.$this->fields('node', (array) $column).', node.parent, (COUNT(parent.'.$this->id.') - 1) AS depth',
                'FROM '.$this->table.' AS node',
                'INNER JOIN '.$this->table.' AS parent',
                'WHERE node.lft BETWEEN parent.lft AND parent.rgt',
                'GROUP BY node.'.$this->id.$depth,
                'ORDER BY node.lft',
            ), '', 'assoc');
        }
        while ($row = $this->db->fetch($stmt)) {
            $tree[array_shift($row)] = $row;
        }
        $this->db->close($stmt);

        return $tree;
    }