86 lines
2.7 KiB
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{})
|
|
}
|