model.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. package seo
  2. import (
  3. "bytes"
  4. "database/sql/driver"
  5. "encoding/csv"
  6. "encoding/json"
  7. "strings"
  8. "time"
  9. "github.com/qor5/admin/l10n"
  10. "github.com/qor5/admin/media/media_library"
  11. h "github.com/theplant/htmlgo"
  12. )
  13. // QorSEOSettingInterface support customize Seo model
  14. // @snippet_begin(QorSEOSettingInterface)
  15. type QorSEOSettingInterface interface {
  16. GetName() string
  17. SetName(string)
  18. GetSEOSetting() Setting
  19. SetSEOSetting(Setting)
  20. GetVariables() Variables
  21. SetVariables(Variables)
  22. GetLocale() string
  23. SetLocale(string)
  24. GetTitle() string
  25. GetDescription() string
  26. GetKeywords() string
  27. GetOpenGraphTitle() string
  28. GetOpenGraphDescription() string
  29. GetOpenGraphURL() string
  30. GetOpenGraphType() string
  31. GetOpenGraphImageURL() string
  32. GetOpenGraphImageFromMediaLibrary() media_library.MediaBox
  33. GetOpenGraphMetadata() []OpenGraphMetadata
  34. }
  35. // @snippet_end
  36. // QorSEOSetting default seo model
  37. type QorSEOSetting struct {
  38. Name string `gorm:"primary_key"`
  39. Setting Setting
  40. Variables Variables `sql:"type:text"`
  41. CreatedAt time.Time
  42. UpdatedAt time.Time
  43. DeletedAt *time.Time `gorm:"index"`
  44. l10n.Locale
  45. }
  46. // Setting defined meta's attributes
  47. type Setting struct {
  48. Title string `gorm:"size:4294967295"`
  49. Description string
  50. Keywords string
  51. OpenGraphTitle string
  52. OpenGraphDescription string
  53. OpenGraphURL string
  54. OpenGraphType string
  55. OpenGraphImageURL string
  56. OpenGraphImageFromMediaLibrary media_library.MediaBox
  57. OpenGraphMetadata []OpenGraphMetadata
  58. EnabledCustomize bool
  59. }
  60. // OpenGraphMetadata open graph meta data
  61. type OpenGraphMetadata struct {
  62. Property string
  63. Content string
  64. }
  65. func (s *QorSEOSetting) SetSEOSetting(setting Setting) {
  66. s.Setting = setting
  67. }
  68. // GetSEOSetting get seo setting
  69. func (s QorSEOSetting) GetSEOSetting() Setting {
  70. return s.Setting
  71. }
  72. // SetVariablesSetting set variables setting
  73. func (s *QorSEOSetting) SetVariables(setting Variables) {
  74. s.Variables = setting
  75. }
  76. // GetVariablesSetting get variables setting
  77. func (s QorSEOSetting) GetVariables() Variables {
  78. return s.Variables
  79. }
  80. // GetName get QorSeoSetting's name
  81. func (s QorSEOSetting) GetLocale() string {
  82. return s.Name
  83. }
  84. // SetName set QorSeoSetting's name
  85. func (s *QorSEOSetting) SetLocale(locale string) {
  86. s.LocaleCode = locale
  87. }
  88. // GetName get QorSeoSetting's name
  89. func (s QorSEOSetting) GetName() string {
  90. return s.Name
  91. }
  92. // SetName set QorSeoSetting's name
  93. func (s *QorSEOSetting) SetName(name string) {
  94. s.Name = name
  95. }
  96. func (s QorSEOSetting) GetOpenGraphTitle() string {
  97. return s.Setting.OpenGraphTitle
  98. }
  99. func (s QorSEOSetting) GetOpenGraphDescription() string {
  100. return s.Setting.OpenGraphDescription
  101. }
  102. func (s QorSEOSetting) GetOpenGraphURL() string {
  103. return s.Setting.OpenGraphURL
  104. }
  105. func (s QorSEOSetting) GetOpenGraphType() string {
  106. return s.Setting.OpenGraphType
  107. }
  108. func (s QorSEOSetting) GetOpenGraphImageURL() string {
  109. return s.Setting.OpenGraphImageURL
  110. }
  111. func (s QorSEOSetting) GetOpenGraphImageFromMediaLibrary() media_library.MediaBox {
  112. return s.Setting.OpenGraphImageFromMediaLibrary
  113. }
  114. func (s QorSEOSetting) GetOpenGraphMetadata() []OpenGraphMetadata {
  115. return s.Setting.OpenGraphMetadata
  116. }
  117. // GetTitle get Setting's title
  118. func (s QorSEOSetting) GetTitle() string {
  119. return s.Setting.Title
  120. }
  121. // GetDescription get Setting's description
  122. func (s QorSEOSetting) GetDescription() string {
  123. return s.Setting.Description
  124. }
  125. // GetKeywords get Setting's keywords
  126. func (s QorSEOSetting) GetKeywords() string {
  127. return s.Setting.Keywords
  128. }
  129. // Scan scan value from database into struct
  130. func (setting *Setting) Scan(value interface{}) error {
  131. if bytes, ok := value.([]byte); ok {
  132. json.Unmarshal(bytes, setting)
  133. } else if str, ok := value.(string); ok {
  134. json.Unmarshal([]byte(str), setting)
  135. } else if strs, ok := value.([]string); ok {
  136. for _, str := range strs {
  137. json.Unmarshal([]byte(str), setting)
  138. }
  139. }
  140. return nil
  141. }
  142. // Value get value from struct, and save into database
  143. func (setting Setting) Value() (driver.Value, error) {
  144. result, err := json.Marshal(setting)
  145. return string(result), err
  146. }
  147. func (setting Setting) IsEmpty() bool {
  148. return setting.Title == "" && setting.Description == "" && setting.Keywords == "" &&
  149. setting.OpenGraphTitle == "" && setting.OpenGraphDescription == "" &&
  150. setting.OpenGraphURL == "" && setting.OpenGraphType == "" && setting.OpenGraphImageURL == "" &&
  151. setting.OpenGraphImageFromMediaLibrary.Url == "" && len(setting.OpenGraphMetadata) == 0
  152. }
  153. type Variables map[string]string
  154. // Scan scan value from database into struct
  155. func (setting *Variables) Scan(value interface{}) error {
  156. if bytes, ok := value.([]byte); ok {
  157. json.Unmarshal(bytes, setting)
  158. } else if str, ok := value.(string); ok {
  159. json.Unmarshal([]byte(str), setting)
  160. } else if strs, ok := value.([]string); ok {
  161. for _, str := range strs {
  162. json.Unmarshal([]byte(str), setting)
  163. }
  164. }
  165. return nil
  166. }
  167. // Value get value from struct, and save into database
  168. func (setting Variables) Value() (driver.Value, error) {
  169. result, err := json.Marshal(setting)
  170. return string(result), err
  171. }
  172. func (setting Setting) HTMLComponent(tags map[string]string) h.HTMLComponent {
  173. openGraphData := map[string]string{
  174. "og:title": setting.OpenGraphTitle,
  175. "og:description": setting.OpenGraphDescription,
  176. "og:url": setting.OpenGraphURL,
  177. "og:type": setting.OpenGraphType,
  178. "og:image": setting.OpenGraphImageURL,
  179. }
  180. for _, metavalue := range setting.OpenGraphMetadata {
  181. openGraphData[metavalue.Property] = metavalue.Content
  182. }
  183. for _, key := range []string{"og:title", "og:description", "og:url", "og:type", "og:image"} {
  184. if v := openGraphData[key]; v == "" {
  185. if v, ok := tags[key]; ok {
  186. openGraphData[key] = v
  187. }
  188. }
  189. }
  190. if openGraphData["og:type"] == "" {
  191. openGraphData["og:type"] = "website"
  192. }
  193. for key, value := range tags {
  194. if _, ok := openGraphData[key]; !ok {
  195. openGraphData[key] = value
  196. }
  197. }
  198. var openGraphDataComponents h.HTMLComponents
  199. for key, value := range openGraphData {
  200. openGraphDataComponents = append(openGraphDataComponents, h.Meta().Attr("property", key).Attr("name", key).Attr("content", value))
  201. }
  202. return h.HTMLComponents{
  203. h.Title(setting.Title),
  204. h.Meta().Attr("name", "description").Attr("content", setting.Description),
  205. h.Meta().Attr("name", "keywords").Attr("content", setting.Keywords),
  206. openGraphDataComponents,
  207. }
  208. }
  209. func GetOpenGraphMetadata(in string) (metadata []OpenGraphMetadata) {
  210. r := csv.NewReader(strings.NewReader(in))
  211. records, err := r.ReadAll()
  212. if err != nil {
  213. return
  214. }
  215. for _, row := range records {
  216. if len(row) != 2 {
  217. continue
  218. }
  219. metadata = append(metadata, OpenGraphMetadata{
  220. Property: row[0],
  221. Content: row[1],
  222. })
  223. }
  224. return
  225. }
  226. func GetOpenGraphMetadataString(metadata []OpenGraphMetadata) string {
  227. records := [][]string{}
  228. for _, m := range metadata {
  229. records = append(records, []string{m.Property, m.Content})
  230. }
  231. buf := new(bytes.Buffer)
  232. w := csv.NewWriter(buf)
  233. w.WriteAll(records)
  234. return buf.String()
  235. }