-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtag_service.go
121 lines (93 loc) · 2.36 KB
/
tag_service.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package service
import (
"context"
"errors"
"fontseca.dev/model"
"fontseca.dev/transfer"
"log/slog"
"strings"
)
type tagsRepositoryAPI interface {
Create(context.Context, *transfer.TagCreation) error
List(context.Context) ([]*model.Tag, error)
Update(context.Context, string, *transfer.TagUpdate) error
Remove(context.Context, string) error
}
// TagsService is a high level provider for tags.
type TagsService struct {
cache []*model.Tag
r tagsRepositoryAPI
}
func NewTagsService(r tagsRepositoryAPI) *TagsService {
return &TagsService{
cache: nil,
r: r,
}
}
// Create adds a new tag.
func (s *TagsService) Create(ctx context.Context, creation *transfer.TagCreation) error {
if nil == creation {
err := errors.New("nil value for parameter: creation")
slog.Error(err.Error())
return err
}
creation.Name = strings.TrimSpace(creation.Name)
sanitizeTextWordIntersections(&creation.Name)
creation.ID = toKebabCase(creation.Name)
err := s.r.Create(ctx, creation)
if nil != err {
return err
}
s.setCache(ctx)
return nil
}
// List retrieves all the tags.
func (s *TagsService) List(ctx context.Context) (tags []*model.Tag, err error) {
if s.hasCache() {
return s.cache, nil
}
tags, err = s.r.List(ctx)
if nil != err {
return nil, err
}
s.cache = tags
return tags, err
}
// Update updates an existing tag.
func (s *TagsService) Update(ctx context.Context, id string, update *transfer.TagUpdate) error {
if nil == update {
err := errors.New("nil value for parameter: creation")
slog.Error(err.Error())
return err
}
id = strings.TrimSpace(id)
update.Name = strings.TrimSpace(update.Name)
sanitizeTextWordIntersections(&update.Name)
update.ID = toKebabCase(update.Name)
err := s.r.Update(ctx, id, update)
if nil != err {
return err
}
s.setCache(ctx)
return nil
}
// Remove removes a tag and detaches it from any
// article that currently uses it.
func (s *TagsService) Remove(ctx context.Context, id string) error {
err := s.r.Remove(ctx, id)
if nil != err {
return err
}
s.setCache(ctx)
return nil
}
func (s *TagsService) setCache(ctx context.Context) {
s.cache = nil
s.cache, _ = s.List(ctx)
}
func (s *TagsService) hasCache() bool {
return 0 < len(s.cache)
}
func (s *TagsService) SetCache(ctx context.Context) {
s.setCache(ctx)
}