Files
sm-quizzes-plugin/models/quiz.go

105 lines
3.3 KiB
Go

// Code generated by summer make. DO NOT EDIT.
package models
import (
"strings"
"time"
"unicode"
"gorm.io/gorm"
)
// Quiz is a set of questions a signed-in user can attempt. Context is a
// free-form link to a record of another plugin, such as "acme.shop:course:12".
type Quiz struct {
ID uint `gorm:"column:id;primaryKey"`
Title string `gorm:"column:title"`
Slug string `gorm:"column:slug"`
Description *string `gorm:"column:description"`
Context *string `gorm:"column:context"`
IsPublished bool `gorm:"column:is_published"`
TimeLimitSeconds *int `gorm:"column:time_limit_seconds"`
PassingScore int `gorm:"column:passing_score"`
ShuffleQuestions bool `gorm:"column:shuffle_questions"`
RoundSize *int `gorm:"column:round_size"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
Questions []Question `gorm:"foreignKey:QuizID"`
}
// TableName is the plugin-prefixed table.
func (Quiz) TableName() string { return "golem15_quizzes_quizzes" }
// Fillable lists the columns mass assignment may set.
func (Quiz) Fillable() []string {
return []string{
"title", "slug", "description", "context", "is_published",
"time_limit_seconds", "passing_score", "shuffle_questions", "round_size",
}
}
// Rules are checked by the admin API on every save; unique ignores the quiz
// being updated.
func (Quiz) Rules() map[string]string {
return map[string]string{
"title": "required|max:255",
"slug": "required|max:255|unique:golem15_quizzes_quizzes",
"context": "nullable|max:255",
"passing_score": "required|integer|between:0,100",
"time_limit_seconds": "nullable|integer|min:1",
"round_size": "nullable|integer|min:1",
}
}
// BeforeValidate fills the slug from the title before the admin form
// validates, so the unique rule sees the final slug.
func (q *Quiz) BeforeValidate(*gorm.DB) error {
q.fillSlug()
return nil
}
// BeforeSave fills the slug from the title on every other write path.
func (q *Quiz) BeforeSave(*gorm.DB) error {
q.fillSlug()
return nil
}
func (q *Quiz) fillSlug() {
if strings.TrimSpace(q.Slug) == "" {
q.Slug = Slugify(q.Title)
} else {
q.Slug = Slugify(q.Slug)
}
}
var transliterations = map[rune]string{
'ą': "a", 'ć': "c", 'ę': "e", 'ł': "l", 'ń': "n", 'ó': "o", 'ś': "s", 'ź': "z", 'ż': "z",
'ä': "a", 'ö': "o", 'ü': "u", 'ß': "ss", 'á': "a", 'é': "e", 'í': "i", 'ú': "u",
'č': "c", 'ř': "r", 'š': "s", 'ž': "z", 'ě': "e", 'ý': "y", 'à': "a", 'è': "e",
}
// Slugify lowercases s, transliterates common Latin diacritics and joins the
// remaining letters and digits with single hyphens.
func Slugify(s string) string {
var b strings.Builder
dash := false
for _, r := range strings.ToLower(strings.TrimSpace(s)) {
if t, ok := transliterations[r]; ok {
b.WriteString(t)
dash = false
continue
}
if (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') {
b.WriteRune(r)
dash = false
continue
}
if (unicode.IsSpace(r) || unicode.IsPunct(r) || unicode.IsSymbol(r)) && b.Len() > 0 && !dash {
b.WriteByte('-')
dash = true
}
}
return strings.TrimSuffix(b.String(), "-")
}