module_api.go 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. package modules
  2. import (
  3. "html"
  4. "net/http"
  5. "strings"
  6. "time"
  7. "golang-fave/assets"
  8. "golang-fave/engine/fetdata"
  9. "golang-fave/engine/wrapper"
  10. "golang-fave/utils"
  11. )
  12. func (this *Modules) api_GenerateXmlCurrencies(wrap *wrapper.Wrapper) string {
  13. result := ``
  14. rows, err := wrap.DB.Query(
  15. `SELECT
  16. code,
  17. coefficient
  18. FROM
  19. shop_currencies
  20. ORDER BY
  21. id ASC
  22. ;`,
  23. )
  24. if err == nil {
  25. defer rows.Close()
  26. values := make([]string, 2)
  27. scan := make([]interface{}, len(values))
  28. for i := range values {
  29. scan[i] = &values[i]
  30. }
  31. for rows.Next() {
  32. err = rows.Scan(scan...)
  33. if err == nil {
  34. result += `<currency id="` + html.EscapeString(string(values[0])) + `" rate="` + html.EscapeString(string(values[1])) + `"/>`
  35. }
  36. }
  37. }
  38. return result
  39. }
  40. func (this *Modules) api_GenerateXmlCategories(wrap *wrapper.Wrapper) string {
  41. result := ``
  42. rows, err := wrap.DB.Query(
  43. `SELECT
  44. data.id,
  45. data.user,
  46. data.name,
  47. data.alias,
  48. data.lft,
  49. data.rgt,
  50. MAX(data.parent_id) AS parent_id
  51. FROM
  52. (
  53. SELECT
  54. node.id,
  55. node.user,
  56. node.name,
  57. node.alias,
  58. node.lft,
  59. node.rgt,
  60. parent.id AS parent_id
  61. FROM
  62. shop_cats AS node,
  63. shop_cats AS parent
  64. WHERE
  65. node.lft BETWEEN parent.lft AND parent.rgt AND
  66. node.id > 1
  67. ORDER BY
  68. node.lft ASC
  69. ) AS data
  70. WHERE
  71. data.id <> data.parent_id
  72. GROUP BY
  73. data.id
  74. ORDER BY
  75. data.lft ASC
  76. ;`,
  77. )
  78. if err == nil {
  79. defer rows.Close()
  80. values := make([]string, 7)
  81. scan := make([]interface{}, len(values))
  82. for i := range values {
  83. scan[i] = &values[i]
  84. }
  85. for rows.Next() {
  86. err = rows.Scan(scan...)
  87. if err == nil {
  88. if utils.StrToInt(string(values[6])) > 1 {
  89. result += `<category id="` + html.EscapeString(string(values[0])) + `" parentId="` + html.EscapeString(string(values[6])) + `">` + html.EscapeString(string(values[2])) + `</category>`
  90. } else {
  91. result += `<category id="` + html.EscapeString(string(values[0])) + `">` + html.EscapeString(string(values[2])) + `</category>`
  92. }
  93. }
  94. }
  95. }
  96. return result
  97. }
  98. func (this *Modules) api_GenerateXmlOfferPictures(wrap *wrapper.Wrapper, product_id int) string {
  99. result := ``
  100. rows, err := wrap.DB.Query(
  101. `SELECT
  102. shop_product_images.product_id,
  103. shop_product_images.filename
  104. FROM
  105. shop_product_images
  106. WHERE
  107. shop_product_images.product_id = ?
  108. ;`,
  109. product_id,
  110. )
  111. if err == nil {
  112. defer rows.Close()
  113. values := make([]string, 2)
  114. scan := make([]interface{}, len(values))
  115. for i := range values {
  116. scan[i] = &values[i]
  117. }
  118. for rows.Next() {
  119. err = rows.Scan(scan...)
  120. if err == nil {
  121. result += `<picture>` + html.EscapeString((*wrap.Config).API.XML.Url) + `products/images/` + html.EscapeString(string(values[0])) + `/` + html.EscapeString(string(values[1])) + `</picture>`
  122. }
  123. }
  124. }
  125. return result
  126. }
  127. func (this *Modules) api_GenerateXmlOfferAttributes(wrap *wrapper.Wrapper, product_id int) string {
  128. result := ``
  129. filter_ids := []int{}
  130. filter_names := map[int]string{}
  131. filter_values := map[int][]string{}
  132. rows, err := wrap.DB.Query(
  133. `SELECT
  134. shop_filters.id,
  135. shop_filters.filter,
  136. shop_filters_values.name
  137. FROM
  138. shop_filter_product_values
  139. LEFT JOIN shop_filters_values ON shop_filters_values.id = shop_filter_product_values.filter_value_id
  140. LEFT JOIN shop_filters ON shop_filters.id = shop_filters_values.filter_id
  141. WHERE
  142. shop_filter_product_values.product_id = ?
  143. ORDER BY
  144. shop_filters.filter ASC,
  145. shop_filters_values.name ASC
  146. ;`,
  147. product_id,
  148. )
  149. if err == nil {
  150. defer rows.Close()
  151. values := make([]string, 3)
  152. scan := make([]interface{}, len(values))
  153. for i := range values {
  154. scan[i] = &values[i]
  155. }
  156. for rows.Next() {
  157. err = rows.Scan(scan...)
  158. if err == nil {
  159. if !utils.InArrayInt(filter_ids, utils.StrToInt(string(values[0]))) {
  160. filter_ids = append(filter_ids, utils.StrToInt(string(values[0])))
  161. }
  162. filter_names[utils.StrToInt(string(values[0]))] = html.EscapeString(string(values[1]))
  163. filter_values[utils.StrToInt(string(values[0]))] = append(filter_values[utils.StrToInt(string(values[0]))], string(values[2]))
  164. }
  165. }
  166. }
  167. for _, filter_id := range filter_ids {
  168. result += `<param name="` + html.EscapeString(filter_names[filter_id]) + `">` + html.EscapeString(strings.Join(filter_values[filter_id], ", ")) + `</param>`
  169. }
  170. return result
  171. }
  172. func (this *Modules) api_GenerateXmlOffers(wrap *wrapper.Wrapper) string {
  173. result := ``
  174. rows, err := wrap.DB.Query(
  175. `SELECT
  176. shop_products.id,
  177. shop_currencies.code,
  178. shop_products.price,
  179. shop_products.name,
  180. shop_products.alias,
  181. shop_products.vendor,
  182. shop_products.quantity,
  183. shop_products.category,
  184. shop_products.content
  185. FROM
  186. shop_products
  187. LEFT JOIN shop_currencies ON shop_currencies.id = shop_products.currency
  188. WHERE
  189. shop_products.active = 1 AND
  190. shop_products.category > 1
  191. ORDER BY
  192. shop_products.id
  193. ;`,
  194. )
  195. if err == nil {
  196. defer rows.Close()
  197. values := make([]string, 9)
  198. scan := make([]interface{}, len(values))
  199. for i := range values {
  200. scan[i] = &values[i]
  201. }
  202. for rows.Next() {
  203. err = rows.Scan(scan...)
  204. if err == nil {
  205. result += `<offer id="` + html.EscapeString(string(values[0])) + `" available="true">`
  206. result += `<url>` + html.EscapeString((*wrap.Config).API.XML.Url) + `shop/` + html.EscapeString(string(values[4])) + `/</url>`
  207. result += `<price>` + utils.Float64ToStrF(utils.StrToFloat64(string(values[0])), "%.2f") + `</price>`
  208. result += `<currencyId>` + html.EscapeString(string(values[1])) + `</currencyId>`
  209. result += `<categoryId>` + html.EscapeString(string(values[7])) + `</categoryId>`
  210. result += this.api_GenerateXmlOfferPictures(wrap, utils.StrToInt(string(values[0])))
  211. result += `<vendor>` + html.EscapeString(string(values[5])) + `</vendor>`
  212. result += `<stock_quantity>` + html.EscapeString(string(values[6])) + `</stock_quantity>`
  213. result += `<name>` + html.EscapeString(string(values[3])) + `</name>`
  214. result += `<description><![CDATA[` + string(values[8]) + `]]></description>`
  215. result += this.api_GenerateXmlOfferAttributes(wrap, utils.StrToInt(string(values[0])))
  216. result += `</offer>`
  217. }
  218. }
  219. }
  220. return result
  221. }
  222. func (this *Modules) api_GenerateXml(wrap *wrapper.Wrapper) string {
  223. return `<?xml version="1.0" encoding="UTF-8"?>
  224. <!DOCTYPE yml_catalog SYSTEM "shops.dtd">
  225. <yml_catalog date="` + time.Unix(int64(time.Now().Unix()), 0).Format("2006-01-02 15:04") + `">
  226. <shop>
  227. <name>` + html.EscapeString((*wrap.Config).API.XML.Name) + `</name>
  228. <company>` + html.EscapeString((*wrap.Config).API.XML.Company) + `</company>
  229. <url>` + html.EscapeString((*wrap.Config).API.XML.Url) + `</url>
  230. <currencies>` + this.api_GenerateXmlCurrencies(wrap) + `</currencies>
  231. <categories>` + this.api_GenerateXmlCategories(wrap) + `</categories>
  232. <offers>` + this.api_GenerateXmlOffers(wrap) + `</offers>
  233. </shop>
  234. </yml_catalog>`
  235. }
  236. func (this *Modules) RegisterModule_Api() *Module {
  237. return this.newModule(MInfo{
  238. WantDB: true,
  239. Mount: "api",
  240. Name: "Api",
  241. Order: 803,
  242. System: true,
  243. Icon: assets.SysSvgIconPage,
  244. Sub: &[]MISub{},
  245. }, func(wrap *wrapper.Wrapper) {
  246. if len(wrap.UrlArgs) == 2 && wrap.UrlArgs[0] == "api" && wrap.UrlArgs[1] == "products" {
  247. if (*wrap.Config).API.XML.Enabled == 1 {
  248. // Fix url
  249. if wrap.R.URL.Path[len(wrap.R.URL.Path)-1] != '/' {
  250. http.Redirect(wrap.W, wrap.R, wrap.R.URL.Path+"/"+utils.ExtractGetParams(wrap.R.RequestURI), 301)
  251. return
  252. }
  253. // XML
  254. wrap.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
  255. wrap.W.Header().Set("Content-Type", "text/xml; charset=utf-8")
  256. wrap.W.WriteHeader(http.StatusOK)
  257. wrap.W.Write([]byte(this.api_GenerateXml(wrap)))
  258. } else {
  259. wrap.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
  260. wrap.W.WriteHeader(http.StatusNotFound)
  261. wrap.W.Write([]byte("Disabled!"))
  262. }
  263. } else if len(wrap.UrlArgs) == 1 {
  264. // Fix url
  265. if wrap.R.URL.Path[len(wrap.R.URL.Path)-1] != '/' {
  266. http.Redirect(wrap.W, wrap.R, wrap.R.URL.Path+"/"+utils.ExtractGetParams(wrap.R.RequestURI), 301)
  267. return
  268. }
  269. // Some info
  270. wrap.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
  271. wrap.W.WriteHeader(http.StatusOK)
  272. wrap.W.Write([]byte("Fave engine API mount point!"))
  273. } else {
  274. // User error 404 page
  275. wrap.RenderFrontEnd("404", fetdata.New(wrap, nil, true), http.StatusNotFound)
  276. return
  277. }
  278. }, func(wrap *wrapper.Wrapper) (string, string, string) {
  279. // No any page for back-end
  280. return "", "", ""
  281. })
  282. }