123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174 |
- package handler
- import (
- "context"
- "database/sql"
- "errors"
- "git.dmitriygnatenko.ru/dima/go-common/logger"
- "github.com/gofiber/fiber/v2"
- "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/dto"
- customErrors "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/helpers/errors"
- "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/mapper"
- "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/i18n"
- )
- const (
- ArticleCacheKey = "article"
- RecentArticlesCacheKey = "recent-articles"
- UsedTagsCacheKey = "used-tags"
- previewArticlesCount = 3
- articleParam = "article"
- )
- type articlePage struct {
- cacheService CacheService
- articleRepository ArticleRepository
- tagRepository TagRepository
- }
- func NewArticlePageHandler(
- cacheService CacheService,
- articleRepository ArticleRepository,
- tagRepository TagRepository,
- ) fiber.Handler {
- h := articlePage{
- cacheService: cacheService,
- articleRepository: articleRepository,
- tagRepository: tagRepository,
- }
- return h.handler()
- }
- func (h articlePage) handler() fiber.Handler {
- return func(fctx *fiber.Ctx) error {
- ctx := fctx.Context()
- url := fctx.Params(articleParam)
- lang := i18n.LanguageFromContext(fctx)
- // article
- renderData, err := h.article(ctx, lang, url)
- if err != nil {
- if !errors.Is(err, fiber.ErrNotFound) {
- logger.Error(ctx, customErrors.Wrap(err, "article page").Error())
- }
- return err
- }
- // recent articles
- articles, err := h.recentArticles(ctx, lang)
- if err != nil {
- logger.Error(ctx, customErrors.Wrap(err, "article page").Error())
- return err
- }
- renderData["sidebarArticles"] = articles
- // tags
- tags, err := h.tags(ctx, lang)
- if err != nil {
- logger.Error(ctx, customErrors.Wrap(err, "article page").Error())
- return err
- }
- renderData["sidebarTags"] = tags
- return fctx.Render("article", renderData, "_layout")
- }
- }
- func (h articlePage) article(
- ctx context.Context,
- lang i18n.Language,
- url string,
- ) (fiber.Map, error) {
- articleCacheKey := ArticleCacheKey + url
- cacheData, found := h.cacheService.Get(articleCacheKey)
- if found {
- if articleData, ok := cacheData.(fiber.Map); ok {
- return articleData, nil
- }
- }
- articleModel, err := h.articleRepository.GetByURL(ctx, url)
- if err != nil {
- if errors.Is(err, sql.ErrNoRows) {
- return nil, fiber.ErrNotFound
- }
- return nil, customErrors.Wrap(err, "can't get article by url")
- }
- if !articleModel.IsActive {
- return nil, fiber.ErrNotFound
- }
- article := mapper.ToArticle(lang, *articleModel)
- renderData := fiber.Map{
- "lang": lang,
- "headTitle": i18n.T(lang, "head_title"),
- "headDescription": article.MetaDescription,
- "headKeywords": article.MetaKeywords,
- "pageTitle": i18n.T(lang, "article_page_title", article.Title),
- "article": article,
- }
- h.cacheService.Set(articleCacheKey, renderData, nil)
- return renderData, nil
- }
- func (h articlePage) recentArticles(
- ctx context.Context,
- lang i18n.Language,
- ) ([]dto.ArticlePreview, error) {
- recentArticlesCacheKey := RecentArticlesCacheKey + string(lang)
- cacheData, found := h.cacheService.Get(recentArticlesCacheKey)
- if found {
- if articles, ok := cacheData.([]dto.ArticlePreview); ok {
- return articles, nil
- }
- }
- articleModels, err := h.articleRepository.GetAllPreview(ctx, i18n.LanguageID(lang))
- if err != nil {
- return nil, customErrors.Wrap(err, "can't get articles")
- }
- if len(articleModels) > previewArticlesCount {
- articleModels = articleModels[:previewArticlesCount]
- }
- articles := mapper.ToArticlesPreview(lang, articleModels)
- h.cacheService.Set(recentArticlesCacheKey, articles, nil)
- return articles, nil
- }
- func (h articlePage) tags(
- ctx context.Context,
- lang i18n.Language,
- ) ([]dto.Tag, error) {
- usedTagsCacheKey := UsedTagsCacheKey + string(lang)
- cacheData, found := h.cacheService.Get(usedTagsCacheKey)
- if found {
- if tagsData, ok := cacheData.([]dto.Tag); ok {
- return tagsData, nil
- }
- }
- tagModels, err := h.tagRepository.GetAllUsed(ctx, i18n.LanguageID(lang))
- if err != nil {
- return nil, customErrors.Wrap(err, "can't get tags")
- }
- tags := mapper.ToTagsList(tagModels)
- h.cacheService.Set(usedTagsCacheKey, tags, nil)
- return tags, nil
- }
|