Files
sm-seo-plugin/models/entry.go

86 lines
2.7 KiB
Go

package models
import (
"database/sql/driver"
"encoding/json"
"errors"
"time"
)
// Entry is the SEO of one record in one locale on golem15_seo_entries
// (D-01): the values an editor set in the record's SEO tab, keyed by the
// record's morph type (ModelType, the content descriptor's Model), its id as
// text and the locale. TypeKey is the record's content type (signpost key)
// and URL the record's public path in that locale when the entry was last
// written. An empty value means "inherit": the resolver falls back to the
// type template, the global settings and the content. EffectiveTitle and
// EffectiveDescription cache the resolved values for duplicate checks. Data
// holds values of later fields (schema type, custom JSON-LD) without a
// migration per field.
type Entry struct {
ID uint `gorm:"column:id;primaryKey"`
ModelType string `gorm:"column:model_type"`
RecordID string `gorm:"column:record_id"`
Locale string `gorm:"column:locale"`
TypeKey string `gorm:"column:type_key"`
URL string `gorm:"column:url"`
Title string `gorm:"column:title"`
Description string `gorm:"column:description"`
Keyphrase string `gorm:"column:keyphrase"`
Canonical string `gorm:"column:canonical"`
Robots string `gorm:"column:robots"`
OGTitle string `gorm:"column:og_title"`
OGDescription string `gorm:"column:og_description"`
OGImage string `gorm:"column:og_image"`
EffectiveTitle string `gorm:"column:effective_title"`
EffectiveDescription string `gorm:"column:effective_description"`
Data JSONMap `gorm:"column:data"`
CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"`
}
func (Entry) TableName() string { return "golem15_seo_entries" }
// JSONMap is a jsonb object column. A nil map is stored as {}.
type JSONMap map[string]any
// Value encodes the map as JSON.
func (m JSONMap) Value() (driver.Value, error) {
if m == nil {
return "{}", nil
}
raw, err := json.Marshal(map[string]any(m))
if err != nil {
return nil, err
}
return string(raw), nil
}
// Scan decodes a jsonb object; NULL reads as an empty map.
func (m *JSONMap) Scan(src any) error {
var raw []byte
switch v := src.(type) {
case nil:
*m = JSONMap{}
return nil
case []byte:
raw = v
case string:
raw = []byte(v)
default:
return errors.New("models: unsupported jsonb value")
}
out := map[string]any{}
if len(raw) > 0 {
if err := json.Unmarshal(raw, &out); err != nil {
return err
}
}
*m = out
return nil
}
func init() {
Register(Entry{})
}