mirror of
https://github.com/Dvorinka/MyClubServer.git
synced 2026-06-03 18:22:57 +00:00
244 lines
7.4 KiB
Go
244 lines
7.4 KiB
Go
package services
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fotbal-club/internal/models"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
// FileTracker provides utilities for tracking file usage
|
|
type FileTracker struct {
|
|
DB *gorm.DB
|
|
}
|
|
|
|
// NewFileTracker creates a new file tracker instance
|
|
func NewFileTracker(db *gorm.DB) *FileTracker {
|
|
return &FileTracker{DB: db}
|
|
}
|
|
|
|
// TrackFileUpload records a new uploaded file
|
|
func (ft *FileTracker) TrackFileUpload(filePath, fileURL, filename, mimeType string, fileSize int64, uploadedByID *uint) error {
|
|
file := models.UploadedFile{
|
|
Filename: filename,
|
|
FilePath: filePath,
|
|
FileURL: fileURL,
|
|
FileSize: fileSize,
|
|
MimeType: mimeType,
|
|
UploadedByID: uploadedByID,
|
|
}
|
|
|
|
return ft.DB.Create(&file).Error
|
|
}
|
|
|
|
// TrackFileUsage records or updates file usage for an entity
|
|
func (ft *FileTracker) TrackFileUsage(fileURL, entityType string, entityID uint, fieldName string) error {
|
|
if fileURL == "" {
|
|
return nil
|
|
}
|
|
|
|
// Find the file by URL
|
|
var file models.UploadedFile
|
|
if err := ft.DB.Where("file_url = ?", fileURL).First(&file).Error; err != nil {
|
|
// File not found in database - skip tracking
|
|
return nil
|
|
}
|
|
|
|
// Check if usage already exists
|
|
var existingUsage models.FileUsage
|
|
err := ft.DB.Where("file_id = ? AND entity_type = ? AND entity_id = ? AND field_name = ?",
|
|
file.ID, entityType, entityID, fieldName).First(&existingUsage).Error
|
|
|
|
if err == gorm.ErrRecordNotFound {
|
|
// Create new usage record
|
|
usage := models.FileUsage{
|
|
FileID: file.ID,
|
|
EntityType: entityType,
|
|
EntityID: entityID,
|
|
FieldName: fieldName,
|
|
}
|
|
return ft.DB.Create(&usage).Error
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// RemoveFileUsage removes a file usage record
|
|
func (ft *FileTracker) RemoveFileUsage(fileURL, entityType string, entityID uint, fieldName string) error {
|
|
if fileURL == "" {
|
|
return nil
|
|
}
|
|
|
|
// Find the file by URL
|
|
var file models.UploadedFile
|
|
if err := ft.DB.Where("file_url = ?", fileURL).First(&file).Error; err != nil {
|
|
return nil
|
|
}
|
|
|
|
return ft.DB.Where("file_id = ? AND entity_type = ? AND entity_id = ? AND field_name = ?",
|
|
file.ID, entityType, entityID, fieldName).Delete(&models.FileUsage{}).Error
|
|
}
|
|
|
|
// UpdateFileUsages updates all file usages for an entity (removes old, adds new)
|
|
func (ft *FileTracker) UpdateFileUsages(entityType string, entityID uint, fieldURLMap map[string]string) error {
|
|
// Get all current usages for this entity
|
|
var currentUsages []models.FileUsage
|
|
ft.DB.Where("entity_type = ? AND entity_id = ?", entityType, entityID).Find(¤tUsages)
|
|
|
|
// Create a map of current usages
|
|
currentMap := make(map[string]models.FileUsage)
|
|
for _, usage := range currentUsages {
|
|
key := usage.FieldName
|
|
currentMap[key] = usage
|
|
}
|
|
|
|
// Track new usages
|
|
for fieldName, fileURL := range fieldURLMap {
|
|
if fileURL != "" {
|
|
// Check if already tracked
|
|
if _, exists := currentMap[fieldName]; !exists {
|
|
ft.TrackFileUsage(fileURL, entityType, entityID, fieldName)
|
|
}
|
|
delete(currentMap, fieldName) // Remove from current map
|
|
}
|
|
}
|
|
|
|
// Remove usages that are no longer present
|
|
for fieldName := range currentMap {
|
|
ft.DB.Where("entity_type = ? AND entity_id = ? AND field_name = ?",
|
|
entityType, entityID, fieldName).Delete(&models.FileUsage{})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TrackArticleFiles tracks all file usages in an article
|
|
func (ft *FileTracker) TrackArticleFiles(article *models.Article) error {
|
|
fieldURLMap := map[string]string{
|
|
"image_url": article.ImageURL,
|
|
"og_image_url": article.OGImageURL,
|
|
}
|
|
|
|
// Track attachments if present
|
|
if article.Attachments != "" {
|
|
// Attachments is a JSON array of URLs - parse properly
|
|
var attachmentURLs []string
|
|
if err := json.Unmarshal([]byte(article.Attachments), &attachmentURLs); err == nil {
|
|
// Successfully parsed as JSON array
|
|
for i, attachmentURL := range attachmentURLs {
|
|
if attachmentURL != "" {
|
|
// Extract filename from URL for better field naming
|
|
filename := filepath.Base(attachmentURL)
|
|
fieldName := "attachment_" + filename
|
|
// Ensure unique field names if same filename appears multiple times
|
|
if _, exists := fieldURLMap[fieldName]; exists {
|
|
fieldName = "attachment_" + filename + "_" + strconv.Itoa(i)
|
|
}
|
|
fieldURLMap[fieldName] = attachmentURL
|
|
}
|
|
}
|
|
} else {
|
|
// Fallback to simple comma-separated parsing
|
|
attachments := strings.Split(article.Attachments, ",")
|
|
for i, attachment := range attachments {
|
|
attachment = strings.Trim(attachment, `[]" `)
|
|
if attachment != "" {
|
|
filename := filepath.Base(attachment)
|
|
fieldName := "attachment_" + filename
|
|
if _, exists := fieldURLMap[fieldName]; exists {
|
|
fieldName = "attachment_" + filename + "_" + strconv.Itoa(i)
|
|
}
|
|
fieldURLMap[fieldName] = attachment
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return ft.UpdateFileUsages("article", article.ID, fieldURLMap)
|
|
}
|
|
|
|
// TrackPlayerFiles tracks all file usages in a player
|
|
func (ft *FileTracker) TrackPlayerFiles(player *models.Player) error {
|
|
fieldURLMap := map[string]string{
|
|
"image_url": player.ImageURL,
|
|
}
|
|
return ft.UpdateFileUsages("player", player.ID, fieldURLMap)
|
|
}
|
|
|
|
// TrackSponsorFiles tracks all file usages in a sponsor
|
|
func (ft *FileTracker) TrackSponsorFiles(sponsor *models.Sponsor) error {
|
|
fieldURLMap := map[string]string{
|
|
"logo_url": sponsor.LogoURL,
|
|
}
|
|
return ft.UpdateFileUsages("sponsor", sponsor.ID, fieldURLMap)
|
|
}
|
|
|
|
// TrackEventFiles tracks all file usages in an event
|
|
func (ft *FileTracker) TrackEventFiles(event *models.Event) error {
|
|
fieldURLMap := map[string]string{
|
|
"image_url": event.ImageURL,
|
|
"file_url": event.FileURL,
|
|
}
|
|
|
|
// Track each attachment separately
|
|
for i, attachment := range event.Attachments {
|
|
if attachment.URL != "" {
|
|
// Generate field name from attachment name or filename
|
|
fieldName := ""
|
|
if attachment.Name != "" {
|
|
// Use attachment name if available
|
|
fieldName = "attachment_" + strings.ReplaceAll(attachment.Name, " ", "_")
|
|
} else {
|
|
// Fall back to filename from URL
|
|
filename := filepath.Base(attachment.URL)
|
|
fieldName = "attachment_" + filename
|
|
}
|
|
|
|
// Ensure unique field names if duplicates exist
|
|
originalFieldName := fieldName
|
|
for counter := 0; ; counter++ {
|
|
if _, exists := fieldURLMap[fieldName]; !exists {
|
|
break
|
|
}
|
|
// Add counter suffix if field name already exists
|
|
fieldName = originalFieldName + "_" + strconv.Itoa(counter)
|
|
if counter > 999 { // Prevent infinite loop
|
|
fieldName = originalFieldName + "_" + strconv.Itoa(i)
|
|
break
|
|
}
|
|
}
|
|
|
|
fieldURLMap[fieldName] = attachment.URL
|
|
}
|
|
}
|
|
|
|
return ft.UpdateFileUsages("event", event.ID, fieldURLMap)
|
|
}
|
|
|
|
// TrackContactFiles tracks all file usages in a contact
|
|
func (ft *FileTracker) TrackContactFiles(contact *models.Contact) error {
|
|
fieldURLMap := map[string]string{
|
|
"image_url": contact.ImageURL,
|
|
}
|
|
return ft.UpdateFileUsages("contact", contact.ID, fieldURLMap)
|
|
}
|
|
|
|
// TrackSettingsFiles tracks all file usages in settings
|
|
func (ft *FileTracker) TrackSettingsFiles(settings *models.Settings) error {
|
|
fieldURLMap := map[string]string{
|
|
"default_og_image_url": settings.DefaultOGImageURL,
|
|
"club_logo_url": settings.ClubLogoURL,
|
|
}
|
|
return ft.UpdateFileUsages("settings", settings.ID, fieldURLMap)
|
|
}
|
|
|
|
// TrackTeamFiles tracks all file usages in a team
|
|
func (ft *FileTracker) TrackTeamFiles(team *models.Team) error {
|
|
fieldURLMap := map[string]string{
|
|
"logo_url": team.LogoURL,
|
|
}
|
|
return ft.UpdateFileUsages("team", team.ID, fieldURLMap)
|
|
}
|