public static function getGroupedOptionArray(
        $db,
        $table,
        $title_field,
        $id_field,
        $group_table,
        $group_title_field,
        $group_id_field,
        $group_field,
        $order_by_clause = null,
        $where_clause = null,
        $tree = null
    ) {
        $title_field = new SwatDBField($title_field, 'text');
        $id_field = new SwatDBField($id_field, 'integer');
        $group_title_field = new SwatDBField($group_title_field, 'text');
        $group_id_field = new SwatDBField($group_id_field, 'integer');
        $group_field = new SwatDBField($group_field, 'text');

        $sql = 'select %s as id, %s as title, %s as group_title, %s as group_id
			from %s';

        $sql = sprintf(
            $sql,
            "{$table}.{$id_field->name}",
            "{$table}.{$title_field->name}",
            "{$group_table}.{$group_title_field->name}",
            "{$group_table}.{$group_id_field->name}",
            $table
        );

        $sql .= ' inner join %s on %s = %s';
        $sql = sprintf(
            $sql,
            $group_table,
            "{$group_table}.{$group_id_field->name}",
            "{$table}.{$group_field->name}"
        );

        if ($where_clause != null) {
            $sql .= ' where ' . $where_clause;
        }

        if ($order_by_clause != null) {
            $sql .= ' order by ' . $order_by_clause;
        }

        $rs = self::query($db, $sql, null);

        $options = array();

        if ($tree !== null && $tree instanceof SwatDataTreeNode) {
            $base_parent = $tree;
        } else {
            $base_parent = new SwatDataTreeNode(null, Swat::_('Root'));
        }

        $current_group = null;

        $row = $rs->fetchRow(MDB2_FETCHMODE_OBJECT);
        while ($row) {
            if ($current_group !== $row->group_id) {
                $current_parent = new SwatDataTreeNode(null, $row->group_title);
                $base_parent->addChild($current_parent);
                $current_group = $row->group_id;
            }

            $current_parent->addChild(
                new SwatDataTreeNode($row->id, $row->title)
            );

            $row = $rs->fetchRow(MDB2_FETCHMODE_OBJECT);
        }

        return $base_parent;
    }