first commit
This commit is contained in:
297
internal/services/post_service.go
Normal file
297
internal/services/post_service.go
Normal file
@@ -0,0 +1,297 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gauth-central/internal/database"
|
||||
"gauth-central/internal/models"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type PostService struct{}
|
||||
|
||||
func NewPostService() *PostService {
|
||||
return &PostService{}
|
||||
}
|
||||
|
||||
func (s *PostService) CreatePost(
|
||||
title string,
|
||||
content string,
|
||||
keywords string,
|
||||
image string,
|
||||
video string,
|
||||
categoryIDs []string,
|
||||
tagIDs []string,
|
||||
parentID *uuid.UUID,
|
||||
isActive bool,
|
||||
isFront bool,
|
||||
) (*models.Post, error) {
|
||||
slug := s.generateUniqueSlug(slugifyPost(title), "")
|
||||
if slug == "" {
|
||||
return nil, errors.New("slug cannot be empty")
|
||||
}
|
||||
|
||||
post := models.Post{
|
||||
Title: title,
|
||||
Content: content,
|
||||
Keywords: keywords,
|
||||
Image: image,
|
||||
Video: video,
|
||||
Slug: slug,
|
||||
ParentID: parentID,
|
||||
IsActive: isActive,
|
||||
IsFront: isFront,
|
||||
}
|
||||
|
||||
if len(categoryIDs) > 0 {
|
||||
categories, err := s.fetchCategoriesByIDs(categoryIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
post.Categories = categories
|
||||
}
|
||||
|
||||
if len(tagIDs) > 0 {
|
||||
tags, err := s.fetchTagsByIDs(tagIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
post.Tags = tags
|
||||
}
|
||||
|
||||
if err := database.DB.Create(&post).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.GetPostByID(post.ID.String())
|
||||
}
|
||||
|
||||
func (s *PostService) GetAllPosts(onlyActive bool, onlyFront bool, page int, limit int) ([]models.Post, int64, error) {
|
||||
var posts []models.Post
|
||||
var total int64
|
||||
|
||||
query := database.DB.Model(&models.Post{})
|
||||
if onlyActive {
|
||||
query = query.Where("is_active = ?", true)
|
||||
}
|
||||
if onlyFront {
|
||||
query = query.Where("is_front = ?", true)
|
||||
}
|
||||
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
offset := (page - 1) * limit
|
||||
|
||||
if err := query.Preload("Categories").Preload("Tags").
|
||||
Order("created_at desc").
|
||||
Limit(limit).
|
||||
Offset(offset).
|
||||
Find(&posts).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return posts, total, nil
|
||||
}
|
||||
|
||||
func (s *PostService) GetPostByID(id string) (*models.Post, error) {
|
||||
var post models.Post
|
||||
if err := database.DB.Preload("Categories").Preload("Tags").Where("id = ?", id).First(&post).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New("post not found")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &post, nil
|
||||
}
|
||||
|
||||
func (s *PostService) GetPostBySlug(slug string, onlyActive bool) (*models.Post, error) {
|
||||
var post models.Post
|
||||
query := database.DB.Preload("Categories").Preload("Tags").Where("slug = ?", slug)
|
||||
if onlyActive {
|
||||
query = query.Where("is_active = ?", true)
|
||||
}
|
||||
|
||||
if err := query.First(&post).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, errors.New("post not found")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return &post, nil
|
||||
}
|
||||
|
||||
func (s *PostService) UpdatePost(
|
||||
id string,
|
||||
title *string,
|
||||
content *string,
|
||||
keywords *string,
|
||||
image *string,
|
||||
video *string,
|
||||
categoryIDs *[]string,
|
||||
tagIDs *[]string,
|
||||
parentID *uuid.UUID,
|
||||
parentIDSet bool,
|
||||
slug *string,
|
||||
isActive *bool,
|
||||
isFront *bool,
|
||||
) (*models.Post, error) {
|
||||
post, err := s.GetPostByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updates := map[string]interface{}{}
|
||||
if title != nil {
|
||||
updates["title"] = *title
|
||||
}
|
||||
if content != nil {
|
||||
updates["content"] = *content
|
||||
}
|
||||
if keywords != nil {
|
||||
updates["keywords"] = *keywords
|
||||
}
|
||||
if image != nil {
|
||||
updates["image"] = *image
|
||||
}
|
||||
if video != nil {
|
||||
updates["video"] = *video
|
||||
}
|
||||
if parentIDSet {
|
||||
updates["parent_id"] = parentID
|
||||
}
|
||||
if slug != nil {
|
||||
clean := slugifyPost(*slug)
|
||||
if clean == "" {
|
||||
return nil, errors.New("slug cannot be empty")
|
||||
}
|
||||
if s.slugExists(clean, id) {
|
||||
return nil, errors.New("slug already exists")
|
||||
}
|
||||
updates["slug"] = clean
|
||||
}
|
||||
if isActive != nil {
|
||||
updates["is_active"] = *isActive
|
||||
}
|
||||
if isFront != nil {
|
||||
updates["is_front"] = *isFront
|
||||
}
|
||||
|
||||
if len(updates) > 0 {
|
||||
if err := database.DB.Model(post).Updates(updates).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if categoryIDs != nil {
|
||||
categories, err := s.fetchCategoriesByIDs(*categoryIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := database.DB.Model(post).Association("Categories").Replace(categories); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if tagIDs != nil {
|
||||
tags, err := s.fetchTagsByIDs(*tagIDs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := database.DB.Model(post).Association("Tags").Replace(tags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return s.GetPostByID(id)
|
||||
}
|
||||
|
||||
func (s *PostService) DeletePost(id string) error {
|
||||
result := database.DB.Delete(&models.Post{}, "id = ?", id)
|
||||
if result.Error != nil {
|
||||
return result.Error
|
||||
}
|
||||
if result.RowsAffected == 0 {
|
||||
return errors.New("post not found")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *PostService) fetchCategoriesByIDs(categoryIDs []string) ([]models.PostCategory, error) {
|
||||
var categories []models.PostCategory
|
||||
if err := database.DB.Where("id IN ?", categoryIDs).Find(&categories).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(categories) != len(categoryIDs) {
|
||||
return nil, errors.New("one or more categories not found")
|
||||
}
|
||||
return categories, nil
|
||||
}
|
||||
|
||||
func (s *PostService) fetchTagsByIDs(tagIDs []string) ([]models.PostTag, error) {
|
||||
var tags []models.PostTag
|
||||
if err := database.DB.Where("id IN ?", tagIDs).Find(&tags).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(tags) != len(tagIDs) {
|
||||
return nil, errors.New("one or more tags not found")
|
||||
}
|
||||
return tags, nil
|
||||
}
|
||||
|
||||
func (s *PostService) generateUniqueSlug(baseSlug string, excludeID string) string {
|
||||
slug := baseSlug
|
||||
counter := 1
|
||||
for s.slugExists(slug, excludeID) {
|
||||
slug = fmt.Sprintf("%s-%d", baseSlug, counter)
|
||||
counter++
|
||||
}
|
||||
return slug
|
||||
}
|
||||
|
||||
func (s *PostService) slugExists(slug string, excludeID string) bool {
|
||||
var count int64
|
||||
query := database.DB.Model(&models.Post{}).Where("slug = ?", slug)
|
||||
if excludeID != "" {
|
||||
query = query.Where("id <> ?", excludeID)
|
||||
}
|
||||
query.Count(&count)
|
||||
return count > 0
|
||||
}
|
||||
|
||||
func slugifyPost(input string) string {
|
||||
clean := strings.TrimSpace(input)
|
||||
if clean == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
replacer := strings.NewReplacer(
|
||||
"ı", "i",
|
||||
"İ", "i",
|
||||
"ş", "s",
|
||||
"Ş", "s",
|
||||
"ğ", "g",
|
||||
"Ğ", "g",
|
||||
"ç", "c",
|
||||
"Ç", "c",
|
||||
"ö", "o",
|
||||
"Ö", "o",
|
||||
"ü", "u",
|
||||
"Ü", "u",
|
||||
)
|
||||
|
||||
clean = strings.ToLower(replacer.Replace(clean))
|
||||
re := regexp.MustCompile(`[^a-z0-9]+`)
|
||||
clean = re.ReplaceAllString(clean, "-")
|
||||
clean = strings.Trim(clean, "-")
|
||||
if clean == "" {
|
||||
return "post"
|
||||
}
|
||||
return clean
|
||||
}
|
||||
Reference in New Issue
Block a user