feat: editor write path

This commit is contained in:
Florian Sylvain committed 2026-11-02 03:24:30 +01:00
1 parent d9158025d4
commit a0b3c58c52
88 files changed
+5738 -263

No files matched your search

@@ -5,6 +5,8 @@ import (
"RenewCMS/internal/domain/audit"
"RenewCMS/internal/domain/author"
"RenewCMS/internal/domain/builtintype"
"RenewCMS/internal/domain/language"
"RenewCMS/internal/domain/localization"
"RenewCMS/internal/domain/role"
"RenewCMS/internal/domain/site"
"RenewCMS/internal/domain/transaction"
@@ -24,6 +26,7 @@ type CreateArticleCommand struct {
Title string
Body string
Format article.BodyFormat
Lang string
Caller ContentCaller
}
@@ -59,6 +62,11 @@ func (g *CreateArticleUseCase) CreateArticle(ctx context.Context, createArticle
recordFailure(ctx, g.recorder, event, err)
return article.Article{}, err
}
requested, err := requestedLanguage(createArticle.Lang)
if err != nil {
recordFailure(ctx, g.recorder, event, err)
return article.Article{}, err
}
siteID, err := g.defaultSiteID()
if err != nil {
@@ -72,7 +80,7 @@ func (g *CreateArticleUseCase) CreateArticle(ctx context.Context, createArticle
return article.Article{}, err
}
created, err := g.createWithFreeSlug(ctx, article.Article{
created, err := g.createWithFreeSlug(ctx, requested, article.Article{
Title: createArticle.Title,
Body: createArticle.Body,
IsOnline: false,
@@ -86,14 +94,21 @@ func (g *CreateArticleUseCase) CreateArticle(ctx context.Context, createArticle
return article.Article{}, err
}
event.Target = articleTarget(created)
event = articleEvent(audit.ActionArticleCreate, created)
g.recorder.Record(ctx, event)
return renderArticle(g.bodyRenderer, created, createArticle.Format)
}
func (g *CreateArticleUseCase) createWithFreeSlug(ctx context.Context, draft article.Article) (article.Article, error) {
func requestedLanguage(raw string) (string, error) {
if raw == "" {
return language.Unassigned, nil
}
return language.Normalize(raw)
}
func (g *CreateArticleUseCase) createWithFreeSlug(ctx context.Context, requested string, draft article.Article) (article.Article, error) {
for attempt := 0; attempt < maxCreateSlugAttempts; attempt++ {
created, err := g.createInTransaction(ctx, draft)
created, err := g.createInTransaction(ctx, requested, draft)
if !isSlugTakenError(err) {
return created, err
}
@@ -101,13 +116,19 @@ func (g *CreateArticleUseCase) createWithFreeSlug(ctx context.Context, draft art
return article.Article{}, article.ErrSlugTaken
}
func (g *CreateArticleUseCase) createInTransaction(ctx context.Context, draft article.Article) (article.Article, error) {
func (g *CreateArticleUseCase) createInTransaction(ctx context.Context, requested string, draft article.Article) (article.Article, error) {
var created article.Article
err := g.transactor.Run(ctx, func(tx transaction.Repositories) error {
lang, err := tx.Languages.LockStartingLanguage(draft.SiteID)
if err != nil {
return err
}
if requested != language.Unassigned {
lang, err = chooseLanguage(tx.Localization, draft.SiteID, requested)
if err != nil {
return err
}
}
draft.Lang = lang
draft.Slug, err = freeSlug(tx.Articles, draft.SiteID, draft.Lang, article.GenerateSlug(draft.Title), 0, firstSlugAttempt)
if err != nil {
@@ -119,6 +140,23 @@ func (g *CreateArticleUseCase) createInTransaction(ctx context.Context, draft ar
return created, err
}
func chooseLanguage(repository localization.Repository, siteID uint32, requested string) (string, error) {
rows, err := repository.Rows(siteID)
if err != nil {
return "", err
}
if localization.NeedsSetup(rows) {
return "", localization.ErrSetupRequired
}
if !localization.HasRow(rows, requested) {
return "", &article.LanguageNotEnabledError{}
}
if !localization.EnabledTag(rows, requested) {
return "", article.ErrLanguageUnavailable
}
return requested, nil
}
func articleTarget(a article.Article) audit.Target {
return audit.NewTarget(audit.TargetArticle, a.ID, a.Title)
}