article.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. package handler
  2. import (
  3. "database/sql"
  4. "errors"
  5. "git.dmitriygnatenko.ru/dima/go-common/logger"
  6. "github.com/gofiber/fiber/v2"
  7. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/dto"
  8. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/mapper"
  9. "git.dmitriygnatenko.ru/dima/dmitriygnatenko-v2/internal/services/i18n"
  10. )
  11. const (
  12. ArticleCacheKey = "article"
  13. RecentArticlesCacheKey = "recent-articles"
  14. UsedTagsCacheKey = "used-tags"
  15. previewArticlesCount = 3
  16. articleParam = "article"
  17. )
  18. func ArticleHandler(
  19. cacheService CacheService,
  20. articleRepository ArticleRepository,
  21. tagRepository TagRepository,
  22. ) fiber.Handler {
  23. return func(fctx *fiber.Ctx) error {
  24. var renderData fiber.Map
  25. ctx := fctx.Context()
  26. url := fctx.Params(articleParam)
  27. lang := mapper.LanguageFromContext(fctx)
  28. // article
  29. articleCacheKey := ArticleCacheKey + url
  30. cacheData, found := cacheService.Get(articleCacheKey)
  31. if found {
  32. if articleData, ok := cacheData.(fiber.Map); ok {
  33. renderData = articleData
  34. }
  35. }
  36. if renderData == nil {
  37. article, err := articleRepository.GetByURL(ctx, url, mapper.ToLanguageModel(lang))
  38. if err != nil {
  39. logger.Error(ctx, err.Error())
  40. if errors.Is(err, sql.ErrNoRows) {
  41. return fiber.ErrNotFound
  42. }
  43. logger.Error(ctx, err.Error())
  44. return err
  45. }
  46. if !article.IsActive {
  47. return fiber.ErrNotFound
  48. }
  49. articleDTO := mapper.ToArticle(lang, *article)
  50. renderData = fiber.Map{
  51. "lang": lang,
  52. "headTitle": i18n.T(lang, "head_title"),
  53. "headDescription": articleDTO.MetaDescription,
  54. "headKeywords": articleDTO.MetaKeywords,
  55. "pageTitle": i18n.T(lang, "article_page_title", articleDTO.Title),
  56. "article": articleDTO,
  57. }
  58. cacheService.Set(articleCacheKey, renderData, nil)
  59. }
  60. // recent articles
  61. recentArticlesCacheKey := RecentArticlesCacheKey + string(lang)
  62. cacheData, found = cacheService.Get(recentArticlesCacheKey)
  63. if found {
  64. if articlesData, ok := cacheData.([]dto.ArticlePreview); ok {
  65. renderData["sidebarArticles"] = articlesData
  66. }
  67. }
  68. if _, ok := renderData["sidebarArticles"]; !ok {
  69. articles, err := articleRepository.GetAllPreview(ctx, mapper.ToLanguageModel(lang))
  70. if err != nil {
  71. logger.Error(ctx, err.Error())
  72. return err
  73. }
  74. if len(articles) > previewArticlesCount {
  75. articles = articles[:previewArticlesCount]
  76. }
  77. sidebarArticles := mapper.ToArticlesPreview(lang, articles)
  78. renderData["sidebarArticles"] = sidebarArticles
  79. cacheService.Set(recentArticlesCacheKey, sidebarArticles, nil)
  80. }
  81. // tags
  82. usedTagsCacheKey := UsedTagsCacheKey + string(lang)
  83. cacheData, found = cacheService.Get(usedTagsCacheKey)
  84. if found {
  85. if tagsData, ok := cacheData.([]dto.Tag); ok {
  86. renderData["sidebarTags"] = tagsData
  87. }
  88. }
  89. if _, ok := renderData["sidebarTags"]; !ok {
  90. tags, err := tagRepository.GetAllUsed(ctx, mapper.ToLanguageModel(lang))
  91. if err != nil {
  92. logger.Error(ctx, err.Error())
  93. return err
  94. }
  95. sidebarTags := mapper.ToTagsList(tags)
  96. renderData["sidebarTags"] = sidebarTags
  97. cacheService.Set(usedTagsCacheKey, sidebarTags, nil)
  98. }
  99. return fctx.Render("article", renderData, "_layout")
  100. }
  101. }