package useCases import ( "RenewCMS/internal/domain/audit" "RenewCMS/internal/domain/image" "context" "time" ) type UpdateVariantCommand struct { Name string VariantDefinitionCommand GenerateOnUpload *bool Enabled *bool } type UpdateVariantResult struct { VariantSummary PurgedFiles int } type UpdateVariantUseCase struct { variants image.VariantRepository files image.VariantFileRepository cache variantCache renderer image.VariantRenderer now func() time.Time recorder audit.Recorder } func NewUpdateVariantUseCase(variants image.VariantRepository, files image.VariantFileRepository, storage image.Storage, renderer image.VariantRenderer, now func() time.Time, recorder audit.Recorder) *UpdateVariantUseCase { return &UpdateVariantUseCase{variants, files, variantCache{files, storage}, renderer, now, recorder} } func (u *UpdateVariantUseCase) EncodableFormats() []image.VariantFormat { return u.renderer.EncodableFormats() } func (u *UpdateVariantUseCase) Update(ctx context.Context, command UpdateVariantCommand) (UpdateVariantResult, error) { current, err := u.variants.Get(command.Name) if err != nil { return UpdateVariantResult{}, err } settings, err := command.settings(u.renderer.EncodableFormats()) if err != nil { return UpdateVariantResult{}, err } next := withSwitches(current.WithSettings(settings), command) renderingChanged := !settings.IsSameAs(current.Settings()) if !renderingChanged && next.Enabled == current.Enabled && next.GenerateOnUpload == current.GenerateOnUpload { return u.result(current, 0) } event := audit.NewEvent(audit.ActionVariantUpdate, audit.CategoryMedia) event.Target = audit.VariantTarget(current.Name) purged, err := u.purgeIfRendering(renderingChanged, current.Name) if err != nil { recordFailure(ctx, u.recorder, event, err) return UpdateVariantResult{}, err } next.UpdatedAt = u.now() updated, err := u.variants.Update(next) if err != nil { recordFailure(ctx, u.recorder, event, err) return UpdateVariantResult{}, err } u.record(ctx, event, current, updated, renderingChanged, purged) return u.result(updated, purged) } func withSwitches(variant image.Variant, command UpdateVariantCommand) image.Variant { if command.GenerateOnUpload != nil { variant.GenerateOnUpload = *command.GenerateOnUpload } if command.Enabled != nil { variant.Enabled = *command.Enabled } return variant } func (u *UpdateVariantUseCase) purgeIfRendering(renderingChanged bool, name string) (int, error) { if !renderingChanged { return 0, nil } result, err := u.cache.purgeVariant(name) return result.Files, err } func (u *UpdateVariantUseCase) record(ctx context.Context, event audit.Event, before image.Variant, after image.Variant, renderingChanged bool, purged int) { if renderingChanged { event.Changes = audit.VariantChanges(before.Settings(), after.Settings()) event.Params = map[string]any{audit.ParamPurgedFiles: purged} u.recorder.Record(ctx, event) } if before.Enabled != after.Enabled { u.recorder.Record(ctx, enabledEvent(after)) } } func (u *UpdateVariantUseCase) result(variant image.Variant, purged int) (UpdateVariantResult, error) { summary, err := summaryOf(variant, u.files) if err != nil { return UpdateVariantResult{}, err } return UpdateVariantResult{summary, purged}, nil } func enabledEvent(variant image.Variant) audit.Event { action := audit.ActionVariantDisable if variant.Enabled { action = audit.ActionVariantEnable } event := audit.NewEvent(action, audit.CategoryMedia) event.Target = audit.VariantTarget(variant.Name) return event }