165 lines
5.6 KiB
Go
165 lines
5.6 KiB
Go
package language
|
|
|
|
import (
|
|
"RenewCMS/api/pkg/apperr"
|
|
validator "RenewCMS/api/pkg/validator"
|
|
domainLanguage "RenewCMS/internal/domain/language"
|
|
"RenewCMS/internal/domain/localization"
|
|
"RenewCMS/internal/domain/site"
|
|
"RenewCMS/internal/infrastructure/useCases"
|
|
"encoding/json"
|
|
"errors"
|
|
"log"
|
|
"net/http"
|
|
|
|
"github.com/go-chi/chi/v5"
|
|
)
|
|
|
|
type SiteLanguagesHandler struct {
|
|
GetUseCase *useCases.GetSiteLanguagesUseCase
|
|
UpdateUseCase *useCases.UpdateSiteLanguagesUseCase
|
|
}
|
|
|
|
func NewSiteLanguagesHandler(get *useCases.GetSiteLanguagesUseCase, update *useCases.UpdateSiteLanguagesUseCase) *SiteLanguagesHandler {
|
|
return &SiteLanguagesHandler{GetUseCase: get, UpdateUseCase: update}
|
|
}
|
|
|
|
type PutLanguage struct {
|
|
Lang string `json:"lang"`
|
|
Enabled *bool `json:"enabled" validate:"required"`
|
|
SocialLocale *string `json:"social_locale"`
|
|
}
|
|
|
|
type PutSiteLanguages struct {
|
|
Revision *string `json:"revision" validate:"required"`
|
|
Default *string `json:"default" validate:"required"`
|
|
Languages []PutLanguage `json:"languages" validate:"required,dive"`
|
|
}
|
|
|
|
func (p PutSiteLanguages) command(key string) useCases.UpdateSiteLanguagesCommand {
|
|
entries := make([]useCases.SiteLanguageEntry, 0, len(p.Languages))
|
|
for _, entry := range p.Languages {
|
|
entries = append(entries, useCases.SiteLanguageEntry{Lang: entry.Lang, Enabled: *entry.Enabled, SocialLocale: entry.SocialLocale})
|
|
}
|
|
return useCases.UpdateSiteLanguagesCommand{Key: key, Revision: *p.Revision, Default: *p.Default, Languages: entries}
|
|
}
|
|
|
|
func (h *SiteLanguagesHandler) Get(w http.ResponseWriter, r *http.Request) {
|
|
view, err := h.GetUseCase.Get(chi.URLParam(r, "key"))
|
|
if err != nil {
|
|
writeLocalizationError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, view)
|
|
}
|
|
|
|
func (h *SiteLanguagesHandler) Update(w http.ResponseWriter, r *http.Request) {
|
|
var request PutSiteLanguages
|
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
|
http.Error(w, apperr.BodyErrorMessage, http.StatusBadRequest)
|
|
return
|
|
}
|
|
if err := validator.Validate.Struct(request); err != nil {
|
|
http.Error(w, apperr.BodyErrorMessage, http.StatusBadRequest)
|
|
return
|
|
}
|
|
view, err := h.UpdateUseCase.Update(r.Context(), request.command(chi.URLParam(r, "key")))
|
|
if err != nil {
|
|
writeLocalizationError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, view)
|
|
}
|
|
|
|
type SetupHandler struct {
|
|
GetUseCase *useCases.GetLanguageSetupUseCase
|
|
ApplyUseCase *useCases.ApplyLanguageSetupUseCase
|
|
}
|
|
|
|
func NewSetupHandler(get *useCases.GetLanguageSetupUseCase, apply *useCases.ApplyLanguageSetupUseCase) *SetupHandler {
|
|
return &SetupHandler{GetUseCase: get, ApplyUseCase: apply}
|
|
}
|
|
|
|
type PostSetupSite struct {
|
|
Key string `json:"key" validate:"required"`
|
|
Lang string `json:"lang"`
|
|
}
|
|
|
|
type PostSetup struct {
|
|
Sites []PostSetupSite `json:"sites" validate:"required,dive"`
|
|
}
|
|
|
|
func (h *SetupHandler) Get(w http.ResponseWriter, r *http.Request) {
|
|
view, err := h.GetUseCase.Get()
|
|
if err != nil {
|
|
writeLocalizationError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, view)
|
|
}
|
|
|
|
func (h *SetupHandler) Apply(w http.ResponseWriter, r *http.Request) {
|
|
var request PostSetup
|
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
|
http.Error(w, apperr.BodyErrorMessage, http.StatusBadRequest)
|
|
return
|
|
}
|
|
if err := validator.Validate.Struct(request); err != nil {
|
|
http.Error(w, apperr.BodyErrorMessage, http.StatusBadRequest)
|
|
return
|
|
}
|
|
choices := make([]localization.SetupChoice, 0, len(request.Sites))
|
|
for _, entry := range request.Sites {
|
|
choices = append(choices, localization.SetupChoice{Key: entry.Key, Lang: entry.Lang})
|
|
}
|
|
result, err := h.ApplyUseCase.Apply(r.Context(), choices)
|
|
if err != nil {
|
|
writeLocalizationError(w, err)
|
|
return
|
|
}
|
|
writeJSON(w, result)
|
|
}
|
|
|
|
func writeJSON(w http.ResponseWriter, value any) {
|
|
body, err := json.Marshal(value)
|
|
if err != nil {
|
|
http.Error(w, "Failed to encode response", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
if _, err := w.Write(body); err != nil {
|
|
log.Printf("Failed to write response: %v", err)
|
|
}
|
|
}
|
|
|
|
type localizationFailure struct {
|
|
sentinel error
|
|
status int
|
|
body string
|
|
}
|
|
|
|
var localizationFailures = []localizationFailure{
|
|
{site.ErrSiteNotFound, http.StatusNotFound, apperr.SiteNotFoundErrorMessage},
|
|
{localization.ErrSetupRequired, http.StatusConflict, apperr.SetupRequiredErrorMessage},
|
|
{localization.ErrLanguagesChanged, http.StatusConflict, apperr.LanguagesChangedErrorMessage},
|
|
{localization.ErrLanguageInUse, http.StatusConflict, apperr.LanguageInUseErrorMessage},
|
|
{localization.ErrSetupInProgress, http.StatusConflict, apperr.SetupInProgressErrorMessage},
|
|
{localization.ErrDefaultNotEnabled, http.StatusUnprocessableEntity, apperr.DefaultNotEnabledErrorMessage},
|
|
{localization.ErrNoEnabledLanguage, http.StatusUnprocessableEntity, apperr.NoEnabledLanguageErrorMessage},
|
|
{localization.ErrDuplicateLanguage, http.StatusUnprocessableEntity, apperr.DuplicateLanguageErrorMessage},
|
|
{localization.ErrInvalidSocialLocale, http.StatusUnprocessableEntity, apperr.InvalidSocialLocaleErrorMessage},
|
|
{localization.ErrSetupIncomplete, http.StatusUnprocessableEntity, apperr.SetupIncompleteErrorMessage},
|
|
{localization.ErrDuplicateSite, http.StatusUnprocessableEntity, apperr.DuplicateSiteErrorMessage},
|
|
{domainLanguage.ErrInvalidLanguage, http.StatusUnprocessableEntity, apperr.InvalidLanguageErrorMessage},
|
|
{domainLanguage.ErrUnsupportedLanguage, http.StatusUnprocessableEntity, apperr.UnsupportedLanguageErrorMessage},
|
|
}
|
|
|
|
func writeLocalizationError(w http.ResponseWriter, err error) {
|
|
for _, failure := range localizationFailures {
|
|
if errors.Is(err, failure.sentinel) {
|
|
http.Error(w, failure.body, failure.status)
|
|
return
|
|
}
|
|
}
|
|
http.Error(w, "Internal server error", http.StatusInternalServerError)
|
|
}
|