article.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  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/mapper"
  8. )
  9. const (
  10. ArticleCacheKey = "article"
  11. maxArticlesCount = 3
  12. articleParam = "article"
  13. )
  14. func ArticleHandler(
  15. cacheService CacheService,
  16. articleRepository ArticleRepository,
  17. tagRepository TagRepository,
  18. ) fiber.Handler {
  19. return func(fctx *fiber.Ctx) error {
  20. ctx := fctx.Context()
  21. url := fctx.Params(articleParam)
  22. renderData, found := cacheService.Get(ArticleCacheKey + url)
  23. if !found {
  24. article, err := articleRepository.GetByURL(ctx, url)
  25. if err != nil {
  26. if errors.Is(err, sql.ErrNoRows) {
  27. return fiber.ErrNotFound
  28. }
  29. logger.Error(ctx, err.Error())
  30. return err
  31. }
  32. if !article.IsActive {
  33. return fiber.ErrNotFound
  34. }
  35. articleDTO := mapper.ToArticleDTO(*article)
  36. // All used tags
  37. tags, err := tagRepository.GetAllUsed(ctx)
  38. if err != nil {
  39. logger.Error(ctx, err.Error())
  40. return err
  41. }
  42. tagsDTO := mapper.ToTagDTOList(tags)
  43. // Last articles
  44. articles, err := articleRepository.GetAllPreview(ctx)
  45. if err != nil {
  46. logger.Error(ctx, err.Error())
  47. return err
  48. }
  49. if len(articles) > maxArticlesCount {
  50. articles = articles[:maxArticlesCount]
  51. }
  52. renderData = fiber.Map{
  53. "headTitle": "От слона к суслику - статьи про PHP, Go, алгоритмы",
  54. "headDescription": articleDTO.MetaDescription,
  55. "headKeywords": articleDTO.MetaKeywords,
  56. "pageTitle": "Статья<br>" + articleDTO.Title,
  57. "article": articleDTO,
  58. "sidebarArticles": mapper.ToArticlePreviewDTOList(articles),
  59. "sidebarTags": tagsDTO,
  60. }
  61. cacheService.Set(ArticleCacheKey+url, renderData, nil)
  62. }
  63. return fctx.Render("article", renderData, "_layout")
  64. }
  65. }