// Package classes holds the SEO plugin's logic: the service every writer // goes through, the entry store and the effective-SEO resolver. package classes import ( "context" "errors" "git.golem15.com/golem15/summercms/modules/backpack" "git.golem15.com/golem15/summercms/modules/cabana" "git.golem15.com/golem15/summercms/modules/compass" "git.golem15.com/golem15/summercms/modules/signpost" "gorm.io/gorm" ) // ErrNotBooted is returned when the service has no booted application. var ErrNotBooted = errors.New("golem15.seo: app is not booted") // Service is the plugin's single entry point for reads and writes of SEO // data. The admin extension, the admin controllers, the listeners, the job // and the API all call it, so every write goes through the same checks and // history. type Service struct { app *backpack.App } // NewService returns the service of a booted application. It needs the // application's database; the signpost registry is optional (without it no // content type takes part). func NewService(app *backpack.App) (*Service, error) { if app == nil { return nil, ErrNotBooted } if db, ok := app.Lookup[*gorm.DB](); !ok || db == nil { return nil, errors.New("database is not configured") } return &Service{app: app}, nil } // App returns the booted application. func (s *Service) App() *backpack.App { if s == nil { return nil } return s.app } // DB returns the write transaction carried by ctx (cabana.TxFromContext), // else the application's database bound to ctx. func (s *Service) DB(ctx context.Context) (*gorm.DB, error) { if tx, ok := cabana.TxFromContext(ctx); ok && tx != nil { return tx, nil } if s == nil || s.app == nil { return nil, ErrNotBooted } db, ok := s.app.Lookup[*gorm.DB]() if !ok || db == nil { return nil, errors.New("golem15.seo: database is not configured") } return db.WithContext(ctx), nil } // Registry returns the menu item type registry, nil when none is published. func (s *Service) Registry() *signpost.Registry { if s == nil || s.app == nil { return nil } reg, _ := s.app.Lookup[*signpost.Registry]() return reg } // Config returns the application config, nil when there is none. func (s *Service) Config() *compass.Config { if s == nil || s.app == nil { return nil } return s.app.Config }