helper.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. package pagebuilder
  2. import (
  3. "path"
  4. "regexp"
  5. "github.com/qor5/admin/l10n"
  6. "github.com/qor5/web"
  7. "gorm.io/gorm"
  8. )
  9. var (
  10. directoryRe = regexp.MustCompile(`^([\/]{1}[a-z0-9.-]+)+(\/?){1}$|^([\/]{1})$`)
  11. )
  12. const (
  13. queryLocaleCodeCategoryPathSlugSQL = `
  14. SELECT pages.id AS id,
  15. pages.version AS version,
  16. pages.locale_code AS locale_code,
  17. categories.path AS category_path,
  18. pages.slug AS slug
  19. FROM page_builder_pages pages
  20. LEFT JOIN page_builder_categories categories ON category_id = categories.id AND pages.locale_code = categories.locale_code
  21. WHERE pages.deleted_at IS NULL AND categories.deleted_at IS NULL
  22. `
  23. invalidPathMsg = "Invalid Path"
  24. invalidSlugMsg = "Invalid Slug"
  25. conflictSlugMsg = "Conflicting Slug"
  26. conflictPathMsg = "Conflicting Path"
  27. existingPathMsg = "Existing Path"
  28. unableDeleteCategoryMsg = "this category cannot be deleted because it has used with pages"
  29. )
  30. type pagePathInfo struct {
  31. ID uint
  32. Version string
  33. LocaleCode string
  34. CategoryPath string
  35. Slug string
  36. }
  37. func pageValidator(p *Page, db *gorm.DB, l10nB *l10n.Builder) (err web.ValidationErrors) {
  38. if p.Slug != "" {
  39. pagePath := path.Clean(p.Slug)
  40. if !directoryRe.MatchString(pagePath) {
  41. err.FieldError("Page.Slug", invalidSlugMsg)
  42. return
  43. }
  44. }
  45. categories := []*Category{}
  46. if err := db.Model(&Category{}).Find(&categories).Error; err != nil {
  47. panic(err)
  48. }
  49. var currentPageCategory Category
  50. for _, category := range categories {
  51. if category.ID == p.CategoryID && category.LocaleCode == p.LocaleCode {
  52. currentPageCategory = *category
  53. break
  54. }
  55. }
  56. var localePath string
  57. if l10nB != nil {
  58. localePath = l10nB.GetLocalePath(p.LocaleCode)
  59. }
  60. currentPagePublishUrl := p.getPublishUrl(localePath, currentPageCategory.Path)
  61. {
  62. // Verify page publish URL does not conflict the other pages' PublishUrl.
  63. var pagePathInfos []pagePathInfo
  64. if err := db.Raw(queryLocaleCodeCategoryPathSlugSQL).Scan(&pagePathInfos).Error; err != nil {
  65. panic(err)
  66. }
  67. for _, info := range pagePathInfos {
  68. if info.ID == p.ID && info.LocaleCode == p.LocaleCode {
  69. continue
  70. }
  71. var localePath string
  72. if l10nB != nil {
  73. localePath = l10nB.GetLocalePath(info.LocaleCode)
  74. }
  75. if generatePublishUrl(localePath, info.CategoryPath, info.Slug) == currentPagePublishUrl {
  76. err.FieldError("Page.Slug", conflictSlugMsg)
  77. return
  78. }
  79. }
  80. }
  81. if p.Slug != "/" {
  82. var allLocalePaths []string
  83. if l10nB != nil {
  84. allLocalePaths = l10nB.GetAllLocalePaths()
  85. } else {
  86. allLocalePaths = []string{""}
  87. }
  88. for _, category := range categories {
  89. for _, localePath := range allLocalePaths {
  90. if generatePublishUrl(localePath, category.Path, "") == currentPagePublishUrl {
  91. err.FieldError("Page.Slug", conflictSlugMsg)
  92. return
  93. }
  94. }
  95. }
  96. }
  97. return
  98. }
  99. func categoryValidator(category *Category, db *gorm.DB, l10nB *l10n.Builder) (err web.ValidationErrors) {
  100. categoryPath := path.Clean(category.Path)
  101. if !directoryRe.MatchString(categoryPath) {
  102. err.FieldError("Category.Category", invalidPathMsg)
  103. return
  104. }
  105. var localePath string
  106. if l10nB != nil {
  107. localePath = l10nB.GetLocalePath(category.LocaleCode)
  108. }
  109. var currentCategoryPathPublishUrl = generatePublishUrl(localePath, categoryPath, "")
  110. {
  111. // Verify category does not conflict the pages' PublishUrl.
  112. var pagePathInfos []pagePathInfo
  113. if err := db.Raw(queryLocaleCodeCategoryPathSlugSQL).Scan(&pagePathInfos).Error; err != nil {
  114. panic(err)
  115. }
  116. for _, info := range pagePathInfos {
  117. var pageLocalePath string
  118. if l10nB != nil {
  119. pageLocalePath = l10nB.GetLocalePath(info.LocaleCode)
  120. }
  121. if generatePublishUrl(pageLocalePath, info.CategoryPath, info.Slug) == currentCategoryPathPublishUrl {
  122. err.FieldError("Category.Category", conflictPathMsg)
  123. return
  124. }
  125. }
  126. }
  127. {
  128. // Verify category not duplicate.
  129. categories := []*Category{}
  130. if err := db.Model(&Category{}).Find(&categories).Error; err != nil {
  131. panic(err)
  132. }
  133. for _, c := range categories {
  134. if c.ID == category.ID && c.LocaleCode == category.LocaleCode {
  135. continue
  136. }
  137. var localePath string
  138. if l10nB != nil {
  139. localePath = l10nB.GetLocalePath(c.LocaleCode)
  140. }
  141. if generatePublishUrl(localePath, c.Path, "") == currentCategoryPathPublishUrl {
  142. err.FieldError("Category.Category", existingPathMsg)
  143. return
  144. }
  145. }
  146. }
  147. return
  148. }