Files
RenewCMS/internal/infrastructure/persistence/repositories/entryRepository.go
T

153 lines
4.6 KiB
Go

package persistence
import (
domain "RenewCMS/internal/domain/entry"
"RenewCMS/internal/infrastructure/persistence/mappers"
entity "RenewCMS/internal/infrastructure/persistence/models"
"gorm.io/gorm"
)
var _ domain.Repository = &EntryRepository{}
type EntryRepository struct {
db *gorm.DB
}
func NewEntryRepository(db *gorm.DB) *EntryRepository {
return &EntryRepository{db}
}
var entrySortColumns = map[domain.SortField]string{
domain.SortByID: "id",
domain.SortByCreatedAt: "created_at",
domain.SortByUpdatedAt: "updated_at",
}
var entrySortDirections = map[domain.SortDirection]string{
domain.SortAsc: "ASC",
domain.SortDesc: "DESC",
}
func EntryOrderClause(sort domain.Sort) (string, error) {
column, columnKnown := entrySortColumns[sort.Field]
direction, directionKnown := entrySortDirections[sort.Direction]
if !columnKnown || !directionKnown || !sort.Valid() {
return "", domain.ErrInvalidSort
}
if sort.Field == domain.SortByID {
return column + " " + direction, nil
}
return column + " " + direction + ", id DESC", nil
}
func (e *EntryRepository) Create(record domain.Entry) (domain.Entry, error) {
model, err := mappers.EntryToModel(record)
if err != nil {
return domain.Entry{}, err
}
if err := e.db.Create(&model).Error; err != nil {
return domain.Entry{}, err
}
return mappers.EntryToDomain(model)
}
func (e *EntryRepository) Get(contentTypeID uint32, id uint32) (domain.Entry, error) {
var model entity.Entry
if err := e.db.Where("content_type_id = ? AND id = ?", contentTypeID, id).First(&model).Error; err != nil {
return domain.Entry{}, mapNotFoundErr(err, domain.ErrEntryNotFound)
}
return mappers.EntryToDomain(model)
}
func (e *EntryRepository) ListPage(filters domain.Filters) (domain.PageResult, error) {
order, err := EntryOrderClause(filters.Sort)
if err != nil {
return domain.PageResult{}, err
}
if err := domain.ValidatePage(filters.Page, filters.Size); err != nil {
return domain.PageResult{}, err
}
filters.Page = max(filters.Page, 1)
filters.Size = max(filters.Size, 0)
scoped := func() *gorm.DB {
return e.db.Model(&entity.Entry{}).Where("content_type_id = ?", filters.ContentTypeID)
}
var total int64
if err := scoped().Count(&total).Error; err != nil {
return domain.PageResult{}, err
}
ordered := scoped().Order(order)
if !filters.Unpaged {
ordered = ordered.Limit(filters.Size).Offset((filters.Page - 1) * filters.Size)
}
var models []entity.Entry
if err := ordered.Find(&models).Error; err != nil {
return domain.PageResult{}, err
}
items, err := entriesToDomain(models)
if err != nil {
return domain.PageResult{}, err
}
return domain.PageResult{Items: items, Total: int(total)}, nil
}
func (e *EntryRepository) Update(record domain.Entry) (domain.Entry, error) {
model, err := mappers.EntryToModel(record)
if err != nil {
return domain.Entry{}, err
}
result := e.db.Model(&entity.Entry{}).Where("id = ?", model.ID).Select("Data", "UpdatedBy", "UpdatedAt").Updates(&model)
if err := deleteOrNotFound(result, domain.ErrEntryNotFound); err != nil {
return domain.Entry{}, err
}
return record, nil
}
func (e *EntryRepository) Delete(contentTypeID uint32, id uint32) error {
result := e.db.Where("content_type_id = ? AND id = ?", contentTypeID, id).Delete(&entity.Entry{})
return deleteOrNotFound(result, domain.ErrEntryNotFound)
}
func (e *EntryRepository) DeleteByContentType(contentTypeID uint32) error {
return e.db.Where("content_type_id = ?", contentTypeID).Delete(&entity.Entry{}).Error
}
func (e *EntryRepository) CountByContentType(contentTypeID uint32) (int, error) {
var total int64
if err := e.db.Model(&entity.Entry{}).Where("content_type_id = ?", contentTypeID).Count(&total).Error; err != nil {
return 0, err
}
return int(total), nil
}
func (e *EntryRepository) FindByFieldValue(contentTypeID uint32, fieldKey string, value any, excludeID uint32) ([]domain.Entry, error) {
var models []entity.Entry
if err := e.db.Where("content_type_id = ? AND id <> ?", contentTypeID, excludeID).Find(&models).Error; err != nil {
return nil, err
}
candidates, err := entriesToDomain(models)
if err != nil {
return nil, err
}
matching := []domain.Entry{}
for _, candidate := range candidates {
if domain.SameValue(candidate.Data[fieldKey], value) {
matching = append(matching, candidate)
}
}
return matching, nil
}
func entriesToDomain(models []entity.Entry) ([]domain.Entry, error) {
items := make([]domain.Entry, 0, len(models))
for _, model := range models {
item, err := mappers.EntryToDomain(model)
if err != nil {
return nil, err
}
items = append(items, item)
}
return items, nil
}