package controllers import ( "context" "git.golem15.com/golem15/sm-faq-plugin/models" translate "git.golem15.com/golem15/sm-translate-plugin/models" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/cabana" "git.golem15.com/golem15/summercms/modules/pact" ) const ( // FAQsControllerID is the cabana controller id of the FAQs screen. FAQsControllerID = "golem15.faq.faqs" // PermissionFAQs is the PHP permission golem15.faq.faqs. PermissionFAQs = "golem15.faq.faqs" ) // faqsAdminController lists and edits FAQs: a name, a slug, the locale, the // active switch, a rich text description and the question repeater. type faqsAdminController struct { app func() *backpack.App } func (faqsAdminController) ID() string { return FAQsControllerID } func (faqsAdminController) ModelName() string { return `Golem15\FAQ\Models\FAQ` } func (faqsAdminController) ConfigDir() string { return "controllers/faqs" } func (faqsAdminController) RequiredPermissions() []string { return []string{PermissionFAQs} } func (faqsAdminController) NewRecord() any { return &models.FAQ{} } // AdminFieldRelations binds the locale field to the translate Locale through // locale_id (PHP belongsTo locale). func (faqsAdminController) AdminFieldRelations() []cabana.FieldRelationContract { return []cabana.FieldRelationContract{{ Field: "locale", Kind: "belongsTo", NewRelated: func() any { return &translate.Locale{} }, ForeignKey: "locale_id", }} } // errLocaleRequired is the field message of a FAQ saved without a locale. const errLocaleRequired = "golem15.faq::lang.errors.locale_required" // siteCacheKind is the kind a FAQ save's site-cache purge carries. const siteCacheKind = "faq" // FormAfterCreate refuses a FAQ without a locale. cabana writes locale_id // from the relation field after the model rules ran, so the check runs here, // inside the save's transaction: the refusal rolls the row back. A FAQ that // passes purges the host site's page caches once the save commits. func (c faqsAdminController) FormAfterCreate(ctx context.Context, model any) error { return c.afterSave(ctx, model) } // FormAfterUpdate applies the same check and purge to an update. func (c faqsAdminController) FormAfterUpdate(ctx context.Context, model any) error { return c.afterSave(ctx, model) } // FormAfterDelete purges the host site's page caches once the delete // commits. func (c faqsAdminController) FormAfterDelete(ctx context.Context, model any) error { if faq, ok := model.(*models.FAQ); ok && faq != nil { purgeSiteCache(ctx, c.app, siteCacheKind, faq.Slug) } return nil } func (c faqsAdminController) afterSave(ctx context.Context, model any) error { if err := requireLocale(model); err != nil { return err } if faq, ok := model.(*models.FAQ); ok && faq != nil { purgeSiteCache(ctx, c.app, siteCacheKind, faq.Slug) } return nil } func requireLocale(model any) error { faq, ok := model.(*models.FAQ) if !ok || faq == nil || faq.LocaleID != 0 { return nil } return &cabana.ValidationError{Details: map[string]any{"locale": []string{errLocaleRequired}}} } var ( _ pact.FormAfterCreate = faqsAdminController{} _ pact.FormAfterUpdate = faqsAdminController{} _ pact.FormAfterDelete = faqsAdminController{} _ pact.AdminController = faqsAdminController{} _ pact.AdminPermissioned = faqsAdminController{} _ pact.AdminRecordSource = faqsAdminController{} _ cabana.FieldRelationProvider = faqsAdminController{} )