Vova Tkach 5 years ago
parent
commit
c6722f64dd
4 changed files with 205 additions and 21 deletions
  1. 13 0
      engine/wrapper/config.go
  2. 111 21
      modules/module_api.go
  3. 45 0
      modules/module_settings.go
  4. 36 0
      modules/module_settings_act_api.go

+ 13 - 0
engine/wrapper/config.go

@@ -18,6 +18,14 @@ type Config struct {
 			Category int
 		}
 	}
+	API struct {
+		XML struct {
+			Enabled int
+			Name    string
+			Company string
+			Url     string
+		}
+	}
 }
 
 func configNew() *Config {
@@ -32,6 +40,11 @@ func (this *Config) configDefault() {
 
 	this.Shop.Pagination.Index = 9
 	this.Shop.Pagination.Category = 9
+
+	this.API.XML.Enabled = 0
+	this.API.XML.Name = ""
+	this.API.XML.Company = ""
+	this.API.XML.Url = ""
 }
 
 func (this *Config) configRead(file string) error {

+ 111 - 21
modules/module_api.go

@@ -1,8 +1,9 @@
 package modules
 
 import (
-	// "html"
+	"html"
 	"net/http"
+	"time"
 
 	"golang-fave/assets"
 	// "golang-fave/consts"
@@ -12,6 +13,89 @@ import (
 	"golang-fave/utils"
 )
 
+func (this *Modules) api_GenerateXmlCurrencies(wrap *wrapper.Wrapper) string {
+	result := ``
+	rows, err := wrap.DB.Query(
+		`SELECT
+			code,
+			coefficient
+		FROM
+			shop_currencies
+		ORDER BY
+			id ASC
+		;`,
+	)
+	if err == nil {
+		defer rows.Close()
+		values := make([]string, 2)
+		scan := make([]interface{}, len(values))
+		for i := range values {
+			scan[i] = &values[i]
+		}
+		for rows.Next() {
+			err = rows.Scan(scan...)
+			if err == nil {
+				result += `<currency id="` + html.EscapeString(string(values[0])) + `" rate="` + html.EscapeString(string(values[1])) + `"/>`
+			}
+		}
+	}
+	return result
+}
+
+func (this *Modules) api_GenerateXmlCategories(wrap *wrapper.Wrapper) string {
+	/*
+		<category id="2">Женская одежда</category>
+		<category id="261" parentId="2">Платья</category>
+		<category id="3">Мужская одежда</category>
+		<category id="391" parentId="3">Куртки</category>
+	*/
+	return ``
+}
+
+func (this *Modules) api_GenerateXmlOffers(wrap *wrapper.Wrapper) string {
+	/*
+		<offer id="19305" available="true">
+			<url>http://abc.ua/catalog/muzhskaya_odezhda/kurtki/kurtkabx.html</url>
+			<price>4499</price>
+			<currencyId>UAH</currencyId>
+			<categoryId>391</categoryId>
+			<picture>http://abc.ua/upload/iblock/a53/a5391cddb40be91705.jpg</picture>
+			<picture>http://abc.ua/upload/iblock/9d0/9d06805d219fb525fc.jpg</picture>
+			<picture>http://abc.ua/upload/iblock/93d/93de38537e1cc1f8f2.jpg</picture>
+			<vendor>Abc clothes</vendor>
+			<stock_quantity>100</stock_quantity>
+			<name>Куртка Abc clothes Scoperandom-HH XL Черная (1323280942900)</name>
+			<description><![CDATA[<p>Одежда<b>Abc clothes</b> способствует развитию функций головного мозга за счет поощрения мелкой моторики.</p><p>В Abc <b>New Collection</b> будет особенно удобно лазать, прыгать, бегать.</p><p>За счет своей универсальноcти и многофункциональности, <b>Abc clothes</b> отлично подходит:</p><ul><li><b>Для весны</b></li><li><b>Для лета</b></li><li><b>Для ранней осени</b> </li></ul><br><p><b>Состав:</b><br>• 92% полиэстер, 8% эластан, нетоксичность подтверждена лабораторно.</p><p><b>Вес:</b> 305 г</p>]]></description>
+			<param name="Вид">Куртка</param>
+			<param name="Размер">XL</param>
+			<param name="Сезон">Весна-Осень</param>
+			<param name="Категория">Мужская</param>
+			<param name="Цвет">Черный</param>
+			<param name="Длина">Средней длины</param>
+			<param name="Стиль">Повседневный (casual)</param>
+			<param name="Особенности">Модель с капюшоном</param>
+			<param name="Состав">92% полиэстер, 8% эластан</param>
+			<param name="Артикул">58265468</param>
+		</offer>
+	*/
+	return ``
+}
+
+func (this *Modules) api_GenerateXml(wrap *wrapper.Wrapper) string {
+	return `<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE yml_catalog SYSTEM "shops.dtd">
+<yml_catalog date="` + time.Unix(int64(time.Now().Unix()), 0).Format("2006-01-02 15:04") + `">
+	<shop>
+		<name>` + html.EscapeString((*wrap.Config).API.XML.Name) + `</name>
+		<company>` + html.EscapeString((*wrap.Config).API.XML.Company) + `</company>
+		<url>` + html.EscapeString((*wrap.Config).API.XML.Url) + `</url>
+		<currencies>` + this.api_GenerateXmlCurrencies(wrap) + `</currencies>
+		<categories>` + this.api_GenerateXmlCategories(wrap) + `</categories>
+		<offers>` + this.api_GenerateXmlOffers(wrap) + `</offers>
+	</shop>
+</yml_catalog>`
+}
+
 func (this *Modules) RegisterModule_Api() *Module {
 	return this.newModule(MInfo{
 		WantDB: true,
@@ -22,29 +106,35 @@ func (this *Modules) RegisterModule_Api() *Module {
 		Icon:   assets.SysSvgIconPage,
 		Sub:    &[]MISub{},
 	}, func(wrap *wrapper.Wrapper) {
-		if len(wrap.UrlArgs) == 2 && wrap.UrlArgs[0] == "api" && wrap.UrlArgs[1] == "products" {
-			// Fix url
-			if wrap.R.URL.Path[len(wrap.R.URL.Path)-1] != '/' {
-				http.Redirect(wrap.W, wrap.R, wrap.R.URL.Path+"/"+utils.ExtractGetParams(wrap.R.RequestURI), 301)
-				return
-			}
+		if (*wrap.Config).API.XML.Enabled == 1 {
+			if len(wrap.UrlArgs) == 2 && wrap.UrlArgs[0] == "api" && wrap.UrlArgs[1] == "products" {
+				// Fix url
+				if wrap.R.URL.Path[len(wrap.R.URL.Path)-1] != '/' {
+					http.Redirect(wrap.W, wrap.R, wrap.R.URL.Path+"/"+utils.ExtractGetParams(wrap.R.RequestURI), 301)
+					return
+				}
+
+				// XML
+				wrap.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
+				wrap.W.Header().Set("Content-Type", "text/xml; charset=utf-8")
+				wrap.W.WriteHeader(http.StatusOK)
+				wrap.W.Write([]byte(this.api_GenerateXml(wrap)))
+			} else if len(wrap.UrlArgs) == 1 {
+				// Fix url
+				if wrap.R.URL.Path[len(wrap.R.URL.Path)-1] != '/' {
+					http.Redirect(wrap.W, wrap.R, wrap.R.URL.Path+"/"+utils.ExtractGetParams(wrap.R.RequestURI), 301)
+					return
+				}
 
-			// XML
-			wrap.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
-			wrap.W.Header().Set("Content-Type", "text/xml; charset=utf-8")
-			wrap.W.WriteHeader(http.StatusOK)
-			wrap.W.Write([]byte("XML"))
-		} else if len(wrap.UrlArgs) == 1 {
-			// Fix url
-			if wrap.R.URL.Path[len(wrap.R.URL.Path)-1] != '/' {
-				http.Redirect(wrap.W, wrap.R, wrap.R.URL.Path+"/"+utils.ExtractGetParams(wrap.R.RequestURI), 301)
+				// Some info
+				wrap.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
+				wrap.W.WriteHeader(http.StatusOK)
+				wrap.W.Write([]byte("Fave engine API mount point!"))
+			} else {
+				// User error 404 page
+				wrap.RenderFrontEnd("404", fetdata.New(wrap, nil, true), http.StatusNotFound)
 				return
 			}
-
-			// Some info
-			wrap.W.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
-			wrap.W.WriteHeader(http.StatusOK)
-			wrap.W.Write([]byte("Fave engine API mount point!"))
 		} else {
 			// User error 404 page
 			wrap.RenderFrontEnd("404", fetdata.New(wrap, nil, true), http.StatusNotFound)

+ 45 - 0
modules/module_settings.go

@@ -23,6 +23,7 @@ func (this *Modules) RegisterModule_Settings() *Module {
 		Sub: &[]MISub{
 			{Mount: "default", Name: "Robots.txt", Show: true, Icon: assets.SysSvgIconBug},
 			{Mount: "pagination", Name: "Pagination", Show: true, Icon: assets.SysSvgIconList},
+			{Mount: "api", Name: "API", Show: true, Icon: assets.SysSvgIconList},
 		},
 	}, nil, func(wrap *wrapper.Wrapper) (string, string, string) {
 		content := ""
@@ -120,6 +121,50 @@ func (this *Modules) RegisterModule_Settings() *Module {
 				},
 			})
 
+			sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Save</button>`
+		} else if wrap.CurrSubModule == "api" {
+			content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
+				{Name: "API"},
+			})
+
+			content += builder.DataForm(wrap, []builder.DataFormField{
+				{
+					Kind:  builder.DFKHidden,
+					Name:  "action",
+					Value: "settings-api",
+				},
+				{
+					Kind:    builder.DFKCheckBox,
+					Caption: "XML enabled",
+					Name:    "xml-enabled",
+					Value:   utils.IntToStr((*wrap.Config).API.XML.Enabled),
+					Hint:    "XML: <a href=\"/api/products/\" target=\"_blank\">/api/products/</a>",
+				},
+				{
+					Kind:    builder.DFKText,
+					Caption: "XML name",
+					Name:    "xml-name",
+					Value:   (*wrap.Config).API.XML.Name,
+				},
+				{
+					Kind:    builder.DFKText,
+					Caption: "XML company",
+					Name:    "xml-company",
+					Value:   (*wrap.Config).API.XML.Company,
+				},
+				{
+					Kind:    builder.DFKText,
+					Caption: "XML url",
+					Name:    "xml-url",
+					Value:   (*wrap.Config).API.XML.Url,
+				},
+				{
+					Kind:   builder.DFKSubmit,
+					Value:  "Save",
+					Target: "add-edit-button",
+				},
+			})
+
 			sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Save</button>`
 		}
 		return this.getSidebarModules(wrap), content, sidebar

+ 36 - 0
modules/module_settings_act_api.go

@@ -0,0 +1,36 @@
+package modules
+
+import (
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) RegisterAction_SettingsApi() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "settings-api",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_xml_enabled := wrap.R.FormValue("xml-enabled")
+		pf_xml_name := wrap.R.FormValue("xml-name")
+		pf_xml_company := wrap.R.FormValue("xml-company")
+		pf_xml_url := wrap.R.FormValue("xml-url")
+
+		if pf_xml_enabled == "" {
+			pf_xml_enabled = "0"
+		}
+
+		(*wrap.Config).API.XML.Enabled = utils.StrToInt(pf_xml_enabled)
+		(*wrap.Config).API.XML.Name = pf_xml_name
+		(*wrap.Config).API.XML.Company = pf_xml_company
+		(*wrap.Config).API.XML.Url = pf_xml_url
+
+		if err := wrap.ConfigSave(); err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Reload current page
+		wrap.Write(`window.location.reload(false);`)
+	})
+}