package pact import ( "context" "time" ) // ContentDescriptor describes the records behind a menu item type, for // consumers that work on every content type at once: sitemaps, search // indexers, audit tools, metadata editors. A type sets it in // MenuItemType.Content; a type without one takes no part and behaves as // before. // // Controller is the ID of the admin controller whose form edits the // records, "" when none does. Model is the records' morph type, the value // RecordSaved and RecordDeleted carry (lagoon.MorphType), so an event maps to // its content type with one lookup; it is required. Describe is required and // describes one record by id. Records pages through the records and Match // maps a public path to a record; both are optional. // // The functions read through cabana.TxFromContext(ctx) when ctx carries a // write transaction, so code running inside a save (a form extension's Save, // for example) sees the values the save has just written. type ContentDescriptor struct { Controller string Model string Records func(ctx context.Context, in ContentList) (ContentPage, error) `json:"-"` Describe func(ctx context.Context, in ContentDescribe) (*ContentRecord, error) `json:"-"` Match func(ctx context.Context, in ContentMatch) (*ContentMatchResult, error) `json:"-"` } // ContentList is what ContentDescriptor.Records receives. Pattern is the URL // pattern already layered by the registry (the host's override, else the // type's default). After is the ID of the last record of the previous page, // "" for the first page; Limit is the page size the caller wants (the type // may cap it). UnprefixedLocale names the locale whose URLs carry no locale // prefix; "" leaves the choice to the type. type ContentList struct { Pattern string After string Limit int UnprefixedLocale string } // ContentPage is one page of records in a stable order. Next is the After of // the following page, "" on the last page. type ContentPage struct { Records []ContentRecord Next string } // ContentDescribe is what ContentDescriptor.Describe receives: the record's // ID, the layered URL pattern and the unprefixed locale, as in ContentList. type ContentDescribe struct { ID string Pattern string UnprefixedLocale string } // ContentRecord describes one record. ID is its primary key as text, // Published whether visitors can see it, LastMod its last change (nil when // unknown). Locales lists the record per locale in the site's locale order. type ContentRecord struct { ID string Published bool LastMod *time.Time Locales []ContentLocale } // ContentLocale is a record in one locale. URL is its public path, "" when // the locale or the host has no public page for it. Title, Description and // Image (a URL) are the record's own defaults for page metadata; Words is the // body's word count, nil when the type has no body. type ContentLocale struct { Locale string URL string Title string Description string Image string Words *int } // ContentMatch is what ContentDescriptor.Match receives: a public path (no // query, no host), the layered URL pattern and the unprefixed locale. type ContentMatch struct { Path string Pattern string UnprefixedLocale string } // ContentMatchResult names the record a path belongs to and the locale the // path addresses. Exact is false when the path names the record but a // segment does not match it (another category, a stale locale prefix, a // slug of another locale): the caller may then redirect to the record's URL. // Match answers nil when the path names no record visitors can see. type ContentMatchResult struct { ID string Locale string Exact bool }