diff options
| author | Bobby <[email protected]> | 2025-07-19 17:06:56 +0530 |
|---|---|---|
| committer | Bobby <[email protected]> | 2025-07-19 17:06:56 +0530 |
| commit | 3f73b3c66de04a55bc101ffb96070ae19e7bf27a (patch) | |
| tree | 85ca777a49e3ec533b2fbc3c709ceb6e093c89c0 /models | |
| parent | d31111cf0133b223a8e665e6798b8ae09aa5c8a9 (diff) | |
| download | imageboard-3f73b3c66de04a55bc101ffb96070ae19e7bf27a.tar.xz imageboard-3f73b3c66de04a55bc101ffb96070ae19e7bf27a.zip | |
tag adding feature for images
Diffstat (limited to 'models')
| -rw-r--r-- | models/image.go | 16 | ||||
| -rw-r--r-- | models/tags.go | 67 |
2 files changed, 27 insertions, 56 deletions
diff --git a/models/image.go b/models/image.go index 35b407e..6dc8e32 100644 --- a/models/image.go +++ b/models/image.go @@ -75,7 +75,7 @@ type Image struct { FavouriteCount int64 `gorm:"not null;default:0" json:"favorite_count"` CommentCount int64 `gorm:"not null;default:0" json:"comment_count"` Sizes []ImageSize `gorm:"foreignKey:ImageID" json:"sizes,omitempty"` - Tags []Tag `gorm:"many2many:image_tags;joinForeignKey:image_id;joinReferences:tag_id" json:"tags,omitempty"` + Tags []Tag `gorm:"many2many:image_tags;joinForeignKey:image_id;joinReferences:tag_id;constraint:OnDelete:CASCADE" json:"tags,omitempty"` FavoritedBy []User `gorm:"many2many:user_favorites" json:"favorited_by,omitempty"` Comments []Comment `gorm:"foreignKey:ImageID" json:"comments,omitempty"` } @@ -326,3 +326,17 @@ func (i *Image) IsUserFavourited(tx *gorm.DB, user *User) bool { tx.Table("user_favorites").Where("user_id = ? AND image_id = ?", user.ID, i.ID).Count(&count) return count > 0 } + +// ImageTag represents the many-to-many relationship between images and tags +// with a unique constraint to prevent duplicate associations +type ImageTag struct { + ImageID uint `gorm:"not null;index;uniqueIndex:idx_image_tag_unique" json:"image_id"` + TagID uint `gorm:"not null;index;uniqueIndex:idx_image_tag_unique" json:"tag_id"` + Image Image `gorm:"foreignKey:ImageID;constraint:OnDelete:CASCADE" json:"-"` + Tag Tag `gorm:"foreignKey:TagID;constraint:OnDelete:CASCADE" json:"-"` +} + +// TableName specifies the table name for the ImageTag model +func (ImageTag) TableName() string { + return "image_tags" +} diff --git a/models/tags.go b/models/tags.go index c3c9063..986338e 100644 --- a/models/tags.go +++ b/models/tags.go @@ -19,7 +19,18 @@ type Tag struct { ParentID *uint `gorm:"index" json:"-"` Parent *Tag `gorm:"foreignKey:ParentID" json:"parent,omitempty"` Children []Tag `gorm:"foreignKey:ParentID" json:"children,omitempty"` - Images []Image `gorm:"many2many:image_tags;joinForeignKey:tag_id;joinReferences:image_id" json:"images,omitempty"` + Images []Image `gorm:"many2many:image_tags;joinForeignKey:tag_id;joinReferences:image_id;constraint:OnDelete:CASCADE" json:"images,omitempty"` + Wiki *TagWiki `gorm:"foreignKey:TagID" json:"wiki,omitempty"` +} + +type TagWiki struct { + gorm.Model + TagID uint `gorm:"not null;uniqueIndex" json:"-"` + Tag Tag `gorm:"foreignKey:TagID" json:"tag,omitempty"` + Content string `gorm:"type:text" json:"content"` + EditorID uint `gorm:"not null" json:"-"` + Editor User `gorm:"foreignKey:EditorID" json:"editor,omitempty"` + IsProtected bool `gorm:"not null;default:false" json:"is_protected"` } func (t *Tag) BeforeCreate(tx *gorm.DB) error { @@ -59,60 +70,6 @@ func (t *Tag) GetFullPath() string { return t.Parent.GetFullPath() + ":" + t.Name } -func SearchTags(tx *gorm.DB, query string, limit int) ([]Tag, error) { - var tags []Tag - searchPattern := "%" + strings.TrimSpace(strings.ToLower(query)) + "%" - - err := tx.Where("name LIKE ? AND is_deleted = ?", searchPattern, false). - Order("count DESC, name ASC").Limit(limit).Find(&tags).Error - - return tags, err -} - -func SearchTagsExcluding(tx *gorm.DB, query string, imageID uint, limit int) ([]Tag, error) { - var tags []Tag - searchPattern := "%" + strings.TrimSpace(strings.ToLower(query)) + "%" - - err := tx.Where("name LIKE ? AND is_deleted = ? AND id NOT IN (?)", - searchPattern, false, - tx.Table("image_tags").Select("tag_id").Where("image_id = ?", imageID)). - Order("count DESC, name ASC").Limit(limit).Find(&tags).Error - - return tags, err -} - -func FindOrCreateTag(tx *gorm.DB, name string, tagType config.TagType) (*Tag, error) { - name = strings.TrimSpace(strings.ToLower(name)) - - // First check for active tag - var tag Tag - if err := tx.Where("name = ? AND is_deleted = ?", name, false).First(&tag).Error; err == nil { - return &tag, nil - } - - // Check for deleted tag and restore it - if err := tx.Where("name = ? AND is_deleted = ?", name, true).First(&tag).Error; err == nil { - tag.IsDeleted = false - tag.Type = tagType // Update type in case it changed - if err := tx.Save(&tag).Error; err != nil { - return nil, fmt.Errorf("failed to restore tag: %v", err) - } - return &tag, nil - } - - // Create new tag - tag = Tag{ - Name: name, - Type: tagType, - } - - if err := tx.Create(&tag).Error; err != nil { - return nil, err - } - - return &tag, nil -} - func (t *Tag) DeleteTag(tx *gorm.DB) error { if t.IsDeleted { return fmt.Errorf("tag is already deleted") |
