package seo import ( "context" "git.golem15.com/golem15/sm-seo-plugin/classes" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/lagoon" "git.golem15.com/golem15/summercms/modules/pact" "gorm.io/gorm" ) // listen subscribes to the framework's record events (D-92): a deleted // record of a content type loses its SEO entries (kept in history), a // created one gets its address snapshot, and an updated one whose address // changed gets its 301 after commit (D-18), whoever wrote it: Journal's // API, MCP, an import, or an admin form whose SEO tab the administrator // does not see. Listener errors are logged by the bus and never fail the // write that fired them. func (p *Plugin) listen(app *backpack.App) { if app == nil || app.Events == nil { return } app.Events.Listen("golem15.seo", func(ctx context.Context, ev *pact.RecordDeleted) error { svc := p.Service() if svc == nil { return nil } return svc.RecordDeleted(ctx, ev) }) app.Events.Listen("golem15.seo", func(ctx context.Context, ev *pact.RecordSaved) error { svc := p.Service() if svc == nil || ev == nil { return nil } if ev.Created { return svc.RecordCreated(ctx, ev) } return p.addressesAfterSave(ctx, svc, ev.Model, ev.ID) }) } // addressesAfterSave re-describes a saved record of a content type in a // transaction of its own and applies AddressChanged to every locale whose // address differs from its entry's URL. After an admin save whose SEO tab // already did this, nothing differs and nothing happens. func (p *Plugin) addressesAfterSave(ctx context.Context, svc *classes.Service, model, id string) error { reg := svc.Registry() if reg == nil { return nil } typ, ok := reg.ContentTypeForModel(model) if !ok || typ.Content == nil { return nil } db, err := svc.DB(ctx) if err != nil { return err } // A lagoon transaction, so the history the 301 records purges the site // cache after the commit. return lagoon.Transaction(ctx, db, func(ctx context.Context, tx *gorm.DB) error { changes, err := svc.AddressChanges(ctx, tx, typ, id) if err != nil { return err } for _, change := range changes { if _, err := svc.AddressChanged(ctx, tx, change); err != nil { return err } } return nil }) }