~evanj/cms

ref: 4aa45cc85249c542c4d80aed47e25c86145bcc3c cms/internal/s/db/contenttype.go -rw-r--r-- 5.3 KiB
4aa45cc8Evan M Jones Feat(mysql): Moving to mysql. Getting ready for alpha release (just for 8 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package db

import (
	"encoding/json"
	"fmt"

	"git.sr.ht/~evanj/cms/internal/m/contenttype"
	"git.sr.ht/~evanj/cms/internal/m/space"
	"git.sr.ht/~evanj/cms/internal/m/valuetype"
)

type ContentType struct {
	id     string
	name   string
	fields []ContentTypeField
}

type ContentTypeField struct {
	id, name, typ string
}

type ContentTypeNewParam struct {
	Name, Type string
}

var (
	queryCreateContentType           = `INSERT INTO cms_contenttype (NAME, SPACE_ID) VALUES (?, ?);`
	queryFindContentTypeByID         = `SELECT ID, NAME FROM cms_contenttype WHERE ID = ?`
	queryFindContentTypeByIDAndSpace = `SELECT ID, NAME FROM cms_contenttype WHERE ID = ? AND SPACE_ID = ?`
	queryDeleteContentTypeByID       = `DELETE FROM cms_space WHERE ID = ?;`
	queryFindContentTypesBySpace     = `SELECT ID, NAME FROM cms_contenttype WHERE SPACE_ID = ? LIMIT ? OFFSET ?`
	queryCreateContentTypeConnection = `INSERT INTO cms_contenttype_to_valuetype (NAME, CONTENTTYPE_ID, VALUETYPE_ID) VALUES (?, ?, ( SELECT ID FROM cms_valuetype WHERE VALUE = ? ));`
	queryFindValueTypes              = `SELECT cms_contenttype_to_valuetype.ID, NAME, VALUE FROM cms_contenttype_to_valuetype JOIN cms_valuetype ON VALUETYPE_ID = cms_valuetype.ID WHERE CONTENTTYPE_ID = ? ORDER BY cms_contenttype_to_valuetype.ID ASC;`
)

func (db *DB) ContentTypeNew(space space.Space, name string, params []ContentTypeNewParam) (contenttype.ContentType, error) {
	// var eg errgroup.Group

	res, err := db.Exec(queryCreateContentType, name, space.ID())
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to create contenttype")
	}

	id, err := res.LastInsertId()
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to find identifier of contenttype")
	}

	for _, item := range params {
		// func(eg *errgroup.Group, contenttypeID int64, item ContentTypeNewParam) {
		// eg.Go(func() error {
		if _, err := db.Exec(queryCreateContentTypeConnection, item.Name, id, item.Type); err != nil {
			if _, err := db.Exec(queryDeleteContentTypeByID, id); err != nil {
				db.log.Println("huge problem, failed to delete orphan contenttype", err)
				return nil, fmt.Errorf("failed to create field(s) and created orphan contenttype")
			}
			return nil, fmt.Errorf("failed to create field(s)")
		}
		// })
		// }(&eg, id, item)
	}

	// if err := eg.Wait(); err != nil {
	// 	// We've partially created contenttype but have ultimately failed, attempt
	// 	// to cleanup old data.
	// 	if _, err := db.Exec(queryDeleteContentTypeByID, id); err != nil {
	// 		db.log.Println("huge problem, failed to delete orphan contenttype", err)
	// 		return nil, fmt.Errorf("failed to create field(s) and created orphan contenttype")
	// 	}
	// 	return nil, fmt.Errorf("failed to create field(s)")
	// }

	var ct ContentType
	if err := db.QueryRow(queryFindContentTypeByID, id).Scan(&ct.id, &ct.name); err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to find user created")
	}

	rows, err := db.Query(queryFindValueTypes, ct.id)
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to find field(s)")
	}
	for rows.Next() {
		var field ContentTypeField
		if err := rows.Scan(&field.id, &field.name, &field.typ); err != nil {
			return nil, fmt.Errorf("failed to scan field(s)")
		}
		ct.fields = append(ct.fields, field)
	}

	if len(ct.fields) != len(params) {
		return nil, fmt.Errorf("failed to create all fields")
	}

	return &ct, nil
}

func (db *DB) ContentTypesPerSpace(space space.Space, page int) ([]contenttype.ContentType, error) {
	var ret []contenttype.ContentType
	rows, err := db.Query(queryFindContentTypesBySpace, space.ID(), perPage, perPage*page)
	if err != nil {
		db.log.Println(err)
		return ret, err
	}

	for rows.Next() {
		var ct ContentType
		if err := rows.Scan(&ct.id, &ct.name); err != nil {
			return nil, err
		}
		ret = append(ret, &ct)
	}

	return ret, nil
}

func (db *DB) ContentTypeGet(space space.Space, contenttypeID string) (contenttype.ContentType, error) {
	var ct ContentType
	if err := db.QueryRow(queryFindContentTypeByIDAndSpace, contenttypeID, space.ID()).Scan(&ct.id, &ct.name); err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to find contenttype for space")
	}

	rows, err := db.Query(queryFindValueTypes, ct.id)
	if err != nil {
		db.log.Println(err)
		return nil, fmt.Errorf("failed to find field(s)")
	}
	for rows.Next() {
		var field ContentTypeField
		if err := rows.Scan(&field.id, &field.name, &field.typ); err != nil {
			return nil, fmt.Errorf("failed to scan field(s)")
		}
		ct.fields = append(ct.fields, field)
	}

	return &ct, nil
}

func (ct *ContentType) ID() string {
	return ct.id
}

func (ct *ContentType) Name() string {
	return ct.name
}

func (ct *ContentType) Fields() []valuetype.ValueType {
	var ret []valuetype.ValueType
	for _, item := range ct.fields {
		ret = append(ret, &ContentTypeField{
			item.id,
			item.name,
			item.typ,
		})
	}
	return ret
}

func (c *ContentType) MarshalJSON() ([]byte, error) {
	fields := make(map[string]string)
	for _, item := range c.Fields() {
		fields[item.Name()] = item.Type()
	}

	values := make(map[string]interface{})
	values["id"] = c.ID()
	values["fields"] = fields

	return json.Marshal(values)
}

func (f *ContentTypeField) ID() string {
	return f.id
}

func (f *ContentTypeField) Name() string {
	return f.name
}

func (f *ContentTypeField) Type() string {
	return f.typ
}