264 lines
5.4 KiB
Go
264 lines
5.4 KiB
Go
package services
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"regexp"
|
||
"strings"
|
||
|
||
"gauth-central/internal/database"
|
||
"gauth-central/internal/models"
|
||
|
||
"gorm.io/gorm"
|
||
)
|
||
|
||
const defaultHomeVideoURL = "https://www.youtube.com/watch?v=6zM4p_A0ISk"
|
||
|
||
type HomeService struct{}
|
||
|
||
func NewHomeService() *HomeService {
|
||
return &HomeService{}
|
||
}
|
||
|
||
// CreateHome creates a new home entry with optional tag relations.
|
||
func (s *HomeService) CreateHome(
|
||
name string,
|
||
title string,
|
||
button1 string,
|
||
button2 string,
|
||
video string,
|
||
keywords string,
|
||
image string,
|
||
tagIDs []string,
|
||
isActive bool,
|
||
) (*models.Home, error) {
|
||
if strings.TrimSpace(video) == "" {
|
||
video = defaultHomeVideoURL
|
||
}
|
||
|
||
slug := s.generateUniqueSlug(slugify(name), "")
|
||
|
||
home := models.Home{
|
||
Name: name,
|
||
Title: title,
|
||
Button1: button1,
|
||
Button2: button2,
|
||
Video: video,
|
||
Keywords: keywords,
|
||
Image: image,
|
||
Slug: slug,
|
||
IsActive: isActive,
|
||
}
|
||
|
||
if len(tagIDs) > 0 {
|
||
tags, err := s.fetchTagsByIDs(tagIDs)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
home.Tags = tags
|
||
}
|
||
|
||
if err := database.DB.Create(&home).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return s.GetHomeByID(home.ID.String())
|
||
}
|
||
|
||
// GetAllHomes retrieves all homes. Use onlyActive to filter public data.
|
||
func (s *HomeService) GetAllHomes(onlyActive bool) ([]models.Home, error) {
|
||
var homes []models.Home
|
||
query := database.DB.Preload("Tags").Order("created_at desc")
|
||
if onlyActive {
|
||
query = query.Where("is_active = ?", true)
|
||
}
|
||
|
||
if err := query.Find(&homes).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return homes, nil
|
||
}
|
||
|
||
// GetHomeByID retrieves a home by ID.
|
||
func (s *HomeService) GetHomeByID(id string) (*models.Home, error) {
|
||
var home models.Home
|
||
if err := database.DB.Preload("Tags").Where("id = ?", id).First(&home).Error; err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return nil, errors.New("home not found")
|
||
}
|
||
return nil, err
|
||
}
|
||
return &home, nil
|
||
}
|
||
|
||
// GetHomeBySlug retrieves a home by slug. Use onlyActive to limit public access.
|
||
func (s *HomeService) GetHomeBySlug(slug string, onlyActive bool) (*models.Home, error) {
|
||
var home models.Home
|
||
query := database.DB.Preload("Tags").Where("slug = ?", slug)
|
||
if onlyActive {
|
||
query = query.Where("is_active = ?", true)
|
||
}
|
||
|
||
if err := query.First(&home).Error; err != nil {
|
||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||
return nil, errors.New("home not found")
|
||
}
|
||
return nil, err
|
||
}
|
||
|
||
return &home, nil
|
||
}
|
||
|
||
// UpdateHome updates an existing home entry and its tag relations.
|
||
func (s *HomeService) UpdateHome(
|
||
id string,
|
||
name *string,
|
||
title *string,
|
||
button1 *string,
|
||
button2 *string,
|
||
video *string,
|
||
keywords *string,
|
||
image *string,
|
||
slug *string,
|
||
tagIDs *[]string,
|
||
isActive *bool,
|
||
) (*models.Home, error) {
|
||
home, err := s.GetHomeByID(id)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
updates := map[string]interface{}{}
|
||
if name != nil {
|
||
updates["name"] = *name
|
||
}
|
||
if title != nil {
|
||
updates["title"] = *title
|
||
}
|
||
if button1 != nil {
|
||
updates["button1"] = *button1
|
||
}
|
||
if button2 != nil {
|
||
updates["button2"] = *button2
|
||
}
|
||
if video != nil {
|
||
updates["video"] = *video
|
||
}
|
||
if keywords != nil {
|
||
updates["keywords"] = *keywords
|
||
}
|
||
if image != nil {
|
||
updates["image"] = *image
|
||
}
|
||
if slug != nil {
|
||
clean := slugify(*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 len(updates) > 0 {
|
||
if err := database.DB.Model(home).Updates(updates).Error; err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
|
||
if tagIDs != nil {
|
||
tags, err := s.fetchTagsByIDs(*tagIDs)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
if err := database.DB.Model(home).Association("Tags").Replace(tags); err != nil {
|
||
return nil, err
|
||
}
|
||
}
|
||
|
||
return s.GetHomeByID(id)
|
||
}
|
||
|
||
// DeleteHome deletes a home by ID.
|
||
func (s *HomeService) DeleteHome(id string) error {
|
||
result := database.DB.Delete(&models.Home{}, "id = ?", id)
|
||
if result.Error != nil {
|
||
return result.Error
|
||
}
|
||
if result.RowsAffected == 0 {
|
||
return errors.New("home not found")
|
||
}
|
||
return nil
|
||
}
|
||
|
||
func (s *HomeService) fetchTagsByIDs(tagIDs []string) ([]models.Tag, error) {
|
||
var tags []models.Tag
|
||
if len(tagIDs) == 0 {
|
||
return tags, nil
|
||
}
|
||
|
||
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 *HomeService) 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 *HomeService) slugExists(slug string, excludeID string) bool {
|
||
var count int64
|
||
query := database.DB.Model(&models.Home{}).Where("slug = ?", slug)
|
||
if excludeID != "" {
|
||
query = query.Where("id <> ?", excludeID)
|
||
}
|
||
query.Count(&count)
|
||
return count > 0
|
||
}
|
||
|
||
func slugify(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 "home"
|
||
}
|
||
return clean
|
||
}
|