package services import ( "errors" "gobeyhan/database" "gobeyhan/database/models" "gorm.io/gorm" ) type PostService struct{} func NewPostService() *PostService { return &PostService{} } // GetAllPosts retrieves all posts with pagination, optionally filtering by active status func (s *PostService) GetAllPosts(page, limit int, activeOnly bool) ([]models.Post, int64, error) { var posts []models.Post var total int64 query := database.DB. Preload("User"). Preload("Categories"). Preload("Tags"). Preload("Parent"). Preload("Children") if activeOnly { query = query.Where("is_active = ?", true) } // Count total query.Model(&models.Post{}).Count(&total) // Get paginated results err := query. Offset((page - 1) * limit). Limit(limit). Order("created_at DESC"). Find(&posts).Error return posts, total, err } // GetPostByID retrieves a post by ID with all relationships func (s *PostService) GetPostByID(id uint64) (*models.Post, error) { var post models.Post err := database.DB. Preload("User"). Preload("Categories"). Preload("Tags"). Preload("Parent"). Preload("Children"). First(&post, id).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &post, nil } // GetPostBySlug retrieves a post by slug func (s *PostService) GetPostBySlug(slug string) (*models.Post, error) { var post models.Post err := database.DB. Preload("User"). Preload("Categories"). Preload("Tags"). Preload("Parent"). Preload("Children"). Where("slug = ? AND is_active = ?", slug, true). First(&post).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return nil, nil } return nil, err } return &post, nil } // CreatePost creates a new post func (s *PostService) CreatePost(post *models.Post) error { return database.DB.Create(post).Error } // UpdatePost updates an existing post func (s *PostService) UpdatePost(id uint64, updates map[string]interface{}) error { // Handle many-to-many relationships separately if they're in updates var categoryIDs []*models.Category var tagIDs []*models.Tag if categories, ok := updates["categories"]; ok { if catSlice, ok := categories.([]*models.Category); ok { categoryIDs = catSlice delete(updates, "categories") } } if tags, ok := updates["tags"]; ok { if tagSlice, ok := tags.([]*models.Tag); ok { tagIDs = tagSlice delete(updates, "tags") } } // Update basic fields result := database.DB.Model(&models.Post{}).Where("id = ?", id).Updates(updates) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return gorm.ErrRecordNotFound } // Update relationships if provided if len(categoryIDs) > 0 || len(tagIDs) > 0 { var post models.Post if err := database.DB.First(&post, id).Error; err != nil { return err } if len(categoryIDs) > 0 { if err := database.DB.Model(&post).Association("Categories").Replace(categoryIDs); err != nil { return err } } if len(tagIDs) > 0 { if err := database.DB.Model(&post).Association("Tags").Replace(tagIDs); err != nil { return err } } } return nil } // DeletePost deletes a post by ID func (s *PostService) DeletePost(id uint64) error { result := database.DB.Delete(&models.Post{}, id) if result.Error != nil { return result.Error } if result.RowsAffected == 0 { return gorm.ErrRecordNotFound } return nil } // GetPostsByCategory retrieves posts by category ID func (s *PostService) GetPostsByCategory(categoryID uint64, page, limit int) ([]models.Post, int64, error) { var posts []models.Post var total int64 query := database.DB. Joins("JOIN post_categories ON post_categories.post_id = posts.id"). Where("post_categories.category_id = ? AND posts.is_active = ?", categoryID, true). Preload("User"). Preload("Categories"). Preload("Tags") query.Model(&models.Post{}).Count(&total) err := query. Offset((page - 1) * limit). Limit(limit). Order("posts.created_at DESC"). Find(&posts).Error return posts, total, err } // GetPostsByTag retrieves posts by tag ID func (s *PostService) GetPostsByTag(tagID uint64, page, limit int) ([]models.Post, int64, error) { var posts []models.Post var total int64 query := database.DB. Joins("JOIN post_tags ON post_tags.post_id = posts.id"). Where("post_tags.tag_id = ? AND posts.is_active = ?", tagID, true). Preload("User"). Preload("Categories"). Preload("Tags") query.Model(&models.Post{}).Count(&total) err := query. Offset((page - 1) * limit). Limit(limit). Order("posts.created_at DESC"). Find(&posts).Error return posts, total, err }