reprogl

Форк
0
/
home.go 
267 строк · 6.4 Кб
1
package handlers
2

3
import (
4
	"errors"
5
	"fmt"
6
	"net/http"
7
	"strconv"
8
	"time"
9

10
	"github.com/go-chi/chi/v5"
11
	"xelbot.com/reprogl/container"
12
	"xelbot.com/reprogl/models"
13
	"xelbot.com/reprogl/models/repositories"
14
	"xelbot.com/reprogl/session"
15
	"xelbot.com/reprogl/views"
16
)
17

18
func IndexAction(app *container.Application) http.HandlerFunc {
19
	return func(w http.ResponseWriter, r *http.Request) {
20
		pageStr := chi.URLParam(r, "page")
21

22
		page, needsRedirect := pageOrRedirect(pageStr)
23
		if needsRedirect {
24
			http.Redirect(w, r, "/", 301)
25

26
			return
27
		}
28

29
		var isAdmin bool
30
		if user, ok := session.GetIdentity(r.Context()); ok {
31
			isAdmin = user.IsAdmin()
32
		}
33

34
		repo := repositories.ArticleRepository{DB: app.DB}
35
		articlesPaginator, err := repo.GetCollection(page, isAdmin)
36
		if err != nil {
37
			if errors.Is(err, models.RecordNotFound) {
38
				app.NotFound(w)
39
			} else {
40
				app.ServerError(w, err)
41
			}
42

43
			return
44
		}
45

46
		articlesPaginator.URLGenerator = indexPaginationURLs()
47

48
		tagRepo := repositories.TagRepository{DB: app.DB}
49
		err = tagRepo.PopulateTagsToArticles(articlesPaginator.Items)
50
		if err != nil {
51
			app.ServerError(w, err)
52

53
			return
54
		}
55

56
		templateData := views.NewIndexPageData(articlesPaginator)
57
		metaDescription := indexPageDescription(app)
58
		if page > 1 {
59
			templateData.AppendTitle(fmt.Sprintf("Страница %d", page))
60
			metaDescription += fmt.Sprintf(" Страница %d", page)
61
			templateData.SetCanonical(container.GenerateAbsoluteURL("blog-page", "page", strconv.Itoa(page)))
62
		} else {
63
			templateData.SetCanonical("https://" + container.GetConfig().Host)
64
		}
65
		templateData.AppendName("description", metaDescription)
66

67
		err = views.WriteTemplateWithContext(r.Context(), w, "index.gohtml", templateData)
68
		if err != nil {
69
			app.ServerError(w, err)
70
		}
71
	}
72
}
73

74
func CategoryAction(app *container.Application) http.HandlerFunc {
75
	return func(w http.ResponseWriter, r *http.Request) {
76
		slug := chi.URLParam(r, "slug")
77

78
		categoryRepo := repositories.CategoryRepository{DB: app.DB}
79
		category, err := categoryRepo.GetBySlug(slug)
80
		if err != nil {
81
			if errors.Is(err, models.RecordNotFound) {
82
				app.NotFound(w)
83
			} else {
84
				app.ServerError(w, err)
85
			}
86

87
			return
88
		}
89

90
		pageStr := chi.URLParam(r, "page")
91
		page, needsRedirect := pageOrRedirect(pageStr)
92
		if needsRedirect {
93
			http.Redirect(w, r, container.GenerateURL("category-first", "slug", slug), http.StatusMovedPermanently)
94

95
			return
96
		}
97

98
		repo := repositories.ArticleRepository{DB: app.DB}
99
		articlesPaginator, err := repo.GetCollectionByCategory(category, page)
100
		if err != nil {
101
			if errors.Is(err, models.RecordNotFound) {
102
				app.NotFound(w)
103
			} else {
104
				app.ServerError(w, err)
105
			}
106

107
			return
108
		}
109

110
		articlesPaginator.URLGenerator = categoryPaginationURLs(slug)
111

112
		tagRepo := repositories.TagRepository{DB: app.DB}
113
		err = tagRepo.PopulateTagsToArticles(articlesPaginator.Items)
114
		if err != nil {
115
			app.ServerError(w, err)
116

117
			return
118
		}
119

120
		templateData := views.NewCategoryPageData(articlesPaginator, category)
121
		if page > 1 {
122
			templateData.SetCanonical(
123
				container.GenerateAbsoluteURL("category", "slug", slug, "page", strconv.Itoa(page)),
124
			)
125
		} else {
126
			templateData.SetCanonical(container.GenerateAbsoluteURL("category-first", "slug", slug))
127
		}
128

129
		err = views.WriteTemplateWithContext(r.Context(), w, "index.gohtml", templateData)
130
		if err != nil {
131
			app.ServerError(w, err)
132
		}
133
	}
134
}
135

136
func TagAction(app *container.Application) http.HandlerFunc {
137
	return func(w http.ResponseWriter, r *http.Request) {
138
		slug := chi.URLParam(r, "slug")
139

140
		tagRepo := repositories.TagRepository{DB: app.DB}
141
		tag, err := tagRepo.GetBySlug(slug)
142
		if err != nil {
143
			if errors.Is(err, models.RecordNotFound) {
144
				app.NotFound(w)
145
			} else {
146
				app.ServerError(w, err)
147
			}
148

149
			return
150
		}
151

152
		pageStr := chi.URLParam(r, "page")
153
		page, needsRedirect := pageOrRedirect(pageStr)
154
		if needsRedirect {
155
			http.Redirect(w, r, container.GenerateURL("tag-first", "slug", slug), http.StatusMovedPermanently)
156

157
			return
158
		}
159

160
		repo := repositories.ArticleRepository{DB: app.DB}
161
		articlesPaginator, err := repo.GetCollectionByTag(tag, page)
162
		if err != nil {
163
			if errors.Is(err, models.RecordNotFound) {
164
				app.NotFound(w)
165
			} else {
166
				app.ServerError(w, err)
167
			}
168

169
			return
170
		}
171

172
		articlesPaginator.URLGenerator = tagPaginationURLs(slug)
173

174
		err = tagRepo.PopulateTagsToArticles(articlesPaginator.Items)
175
		if err != nil {
176
			app.ServerError(w, err)
177

178
			return
179
		}
180

181
		templateData := views.NewCategoryPageData(articlesPaginator, tag)
182
		if page > 1 {
183
			templateData.SetCanonical(
184
				container.GenerateAbsoluteURL("tag", "slug", slug, "page", strconv.Itoa(page)),
185
			)
186
		} else {
187
			templateData.SetCanonical(container.GenerateAbsoluteURL("tag-first", "slug", slug))
188
		}
189

190
		err = views.WriteTemplateWithContext(r.Context(), w, "index.gohtml", templateData)
191
		if err != nil {
192
			app.ServerError(w, err)
193
		}
194
	}
195
}
196

197
func indexPaginationURLs() models.URLGenerator {
198
	return func(page int, dir models.PaginationDirection) string {
199
		switch dir {
200
		case models.PaginationNext:
201
			page++
202
		case models.PaginationPrev:
203
			page--
204
		}
205

206
		if page == 1 {
207
			return "/"
208
		}
209

210
		return container.GenerateURL("blog-page", "page", strconv.Itoa(page))
211
	}
212
}
213

214
func categoryPaginationURLs(slug string) models.URLGenerator {
215
	return paginationURLsWithSlug(slug, "category-first", "category")
216
}
217

218
func tagPaginationURLs(slug string) models.URLGenerator {
219
	return paginationURLsWithSlug(slug, "tag-first", "tag")
220
}
221

222
func paginationURLsWithSlug(slug, firstRouteName, othersRouteName string) models.URLGenerator {
223
	return func(page int, dir models.PaginationDirection) string {
224
		var (
225
			routeName string
226
			pairs     []string
227
		)
228

229
		switch dir {
230
		case models.PaginationNext:
231
			page++
232
		case models.PaginationPrev:
233
			page--
234
		}
235

236
		pairs = append(pairs, "slug")
237
		pairs = append(pairs, slug)
238

239
		if page == 1 {
240
			routeName = firstRouteName
241
		} else {
242
			routeName = othersRouteName
243
			pairs = append(pairs, "page")
244
			pairs = append(pairs, strconv.Itoa(page))
245
		}
246

247
		return container.GenerateURL(routeName, pairs...)
248
	}
249
}
250

251
func indexPageDescription(app *container.Application) string {
252
	var metaDescription string
253

254
	key := "meta_description"
255

256
	cache := app.GetStringCache()
257
	if value, found := cache.Get(key); found {
258
		return value
259
	} else {
260
		sysParamsRepo := repositories.SystemParametersRepository{DB: app.DB}
261
		metaDescription, _ = sysParamsRepo.FindByKey(key)
262
	}
263

264
	cache.Set(key, metaDescription, 30*24*3600*time.Second)
265

266
	return metaDescription
267
}
268

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.