diff --git a/pom.xml b/pom.xml index 39031480e47256a1118015a580c4ce33bd745778..e4644e5f0b2b0a30f937698f8b29f7a95809c19c 100644 --- a/pom.xml +++ b/pom.xml @@ -64,6 +64,7 @@ 1.81 2.2.1 + 2.1 9.1.2.v20140210 @@ -302,11 +303,17 @@ ${oval.version} - - - - - + + com.fasterxml.jackson.core + jackson-databind + ${jackson.version} + + + javax.xml.bind + jaxb-api + ${jaxb-api.version} + runtime + @@ -508,7 +515,20 @@ urlrewritefilter 4.0.4 - + + org.apache.commons + commons-lang3 + 3.3.2 + + + + + dom4j + dom4j + 1.6.1 + + + diff --git a/src/main/java/org/genesys2/server/model/impl/Article.java b/src/main/java/org/genesys2/server/model/impl/Article.java index c969e9e27fe88928d876242c17bbc80cdb44d714..94c82672ea58c04e29f01c68278ee83a67ce92d4 100644 --- a/src/main/java/org/genesys2/server/model/impl/Article.java +++ b/src/main/java/org/genesys2/server/model/impl/Article.java @@ -16,20 +16,12 @@ package org.genesys2.server.model.impl; -import java.util.Calendar; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.JoinColumn; -import javax.persistence.Lob; -import javax.persistence.ManyToOne; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; - import org.genesys2.server.model.AuditedModel; import org.hibernate.annotations.Type; +import javax.persistence.*; +import java.util.Calendar; + @Entity @Table(name = "article") public class Article extends AuditedModel { @@ -61,6 +53,8 @@ public class Article extends AuditedModel { @Column(length = 100000) private String body; + private boolean transifexed = true; + @Temporal(TemporalType.TIMESTAMP) private Calendar postDate; @@ -119,4 +113,12 @@ public class Article extends AuditedModel { public void setLang(String lang) { this.lang = lang; } + + public boolean isTransifexed() { + return transifexed; + } + + public void setTransifexed(boolean transifexed) { + this.transifexed = transifexed; + } } diff --git a/src/main/java/org/genesys2/server/servlet/controller/transifex/TransifexAPIController.java b/src/main/java/org/genesys2/server/servlet/controller/transifex/TransifexAPIController.java new file mode 100644 index 0000000000000000000000000000000000000000..8d2f0a78c313d12041f623694e3f45f04f827b2c --- /dev/null +++ b/src/main/java/org/genesys2/server/servlet/controller/transifex/TransifexAPIController.java @@ -0,0 +1,234 @@ +package org.genesys2.server.servlet.controller.transifex; + +import org.apache.commons.codec.binary.Base64; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.DocumentHelper; +import org.dom4j.io.HTMLWriter; +import org.dom4j.io.OutputFormat; +import org.genesys2.server.model.impl.Article; +import org.genesys2.server.service.ContentService; +import org.genesys2.server.servlet.controller.BaseController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.http.*; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.util.LinkedMultiValueMap; +import org.springframework.util.MultiValueMap; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.client.HttpClientErrorException; +import org.springframework.web.client.RestTemplate; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +@Controller +@RequestMapping(value = "/transifex") +public class TransifexAPIController extends BaseController{ + + @Autowired + private ContentService contentService; + + @Value("${transifex.project}") + private String projectSlug; + + @Value("${transifex.username}") + private String trasifexUserName; + + @Value("${transifex.password}") + private String transifexPassord; + + @Value("${transifex.min.translated}") + private String minTranslatedValue; + + @Value("${transifex.base.api.url}") + private String baseApiURL; + + private RestTemplate template; + private HttpHeaders headers; + + @RequestMapping(value = "/deleteContent/{slug}") + public String deleteResource(@PathVariable String slug, Model model) { + //make authentication for Transifex + basicAuthentication(); + + Article article = contentService.getGlobalArticle(slug, getLocale()); + + // + if (resourceExists(article)) { + StringBuilder url = new StringBuilder(); + url.append("project/"); + url.append(projectSlug); + url.append("/resource/"); + url.append("article-"); + url.append(article.getSlug()); + HttpEntity request = new HttpEntity<>(headers); + ResponseEntity response = template.exchange(baseApiURL + url, HttpMethod.DELETE, request, String.class); + if(response.getStatusCode().value() == 204){ + model.addAttribute("result", "deleted ok"); + } + } + model.addAttribute("title", article.getTitle()); + model.addAttribute("article", article); + return "/content/article-edit"; + } + + @RequestMapping(value = "/hooks", method = RequestMethod.POST) + public void webHookHandle(@RequestParam(value = "project") String projectSlug, + @RequestParam(value = "resource") String resource, + @RequestParam(value = "language") String language, + @RequestParam(value = "translated") int translated){ + System.out.println(projectSlug+" done \n"); + } + + @RequestMapping(value = "/translate/{slug}/{lang}", method = RequestMethod.GET) + public String translateArticles(@PathVariable String lang, @PathVariable String slug, Model model) throws DocumentException { + //make authentication for Transifex + basicAuthentication(); + + //Extract article from database we need + Article article = contentService.getGlobalArticle(slug, getLocale()); + + StringBuilder url = new StringBuilder(); + url.append("project/"); + url.append(projectSlug); + url.append("/resource/"); + url.append("article-"); + url.append(slug); + url.append("/translation/"); + url.append(lang); + url.append("/?file"); + + HttpEntity request = new HttpEntity<>(headers); + + ResponseEntity response = template.exchange(baseApiURL + url, HttpMethod.GET, request, String.class); + + String title = response.getBody().split("")[1].split("")[0]; + String body = response.getBody().split("")[1].split("")[0]; + + article.setTitle(title); + article.setBody(body); + + contentService.updateArticle(article.getId(), article.getSlug(), article.getTitle(), article.getBody()); + + model.addAttribute("title", article.getTitle()); + model.addAttribute("article", article); + + return "/content/article-edit"; + } + + @RequestMapping(value = "/postContent/{slug}") + public String postResourceToTransifex(@PathVariable String slug, Model model) throws IOException, DocumentException { + //We want to sent .xhtml file to transifex, for this we use dom4j + + //Make the authentication for Transifex + basicAuthentication(); + + //Extract article from database we need + Article article = contentService.getGlobalArticle(slug, getLocale(), false); + + //Create temporary file articleSlug.xhtml + String filePath = "/home/alexander/Downloads/"+article.getSlug()+".xhtml"; + File xhtmlFile = new File(filePath); + xhtmlFile.createNewFile(); + + //Create dom4j document witch will be containing xhtml content + Document xhtmlDocument; + + //Define xhtml output format for HTMLWriter + OutputFormat outputFormat = OutputFormat.createPrettyPrint(); + outputFormat.setXHTML(true); + + HTMLWriter writer = new HTMLWriter(new FileWriter(xhtmlFile), outputFormat); + if (!resourceExists(article)) { + //We will request like MULTIPART_FORM_DATA + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + + //This is template our xhtml + String content = " \n" + + " \n" + + " \n" + + ""+article.getTitle()+" \n" + + " \n" + + " "+article.getBody()+" \n" + + ""; + + //Parse String content and write it into articleSlug.xhtml file + xhtmlDocument = DocumentHelper.parseText(content); + writer.write(xhtmlDocument); + writer.flush(); + + //Create Multi value map with all necessary information for request + MultiValueMap map = new LinkedMultiValueMap<>(); + map.add("slug", "article-"+slug); + map.add("name", article.getTitle()); + map.add("i18n_type", "XHTML"); + Resource resource = new FileSystemResource(filePath); + map.add("content", resource); + + //Create our request entity + HttpEntity> request = new HttpEntity<>(map, headers); + model.addAttribute("title", article.getTitle()); + model.addAttribute("article", article); + + StringBuilder url = new StringBuilder(); + url.append("project/"); + url.append(projectSlug); + url.append("/resources/"); + + try { + //Send our post request(with .xhtml file) to Transifex + template.postForLocation(baseApiURL + url, request); + model.addAttribute("responseFromTransifex", "Resource added"); + } catch (HttpClientErrorException e) { + model.addAttribute("responseFromTransifex", "fail"); + } + //After all operations, temporary .xhtml file is deleted + xhtmlFile.delete(); + } + return "/content/article-edit"; + } + + //Transifex requires Basic HTTP authentication! + //This method make authentication for Transifex + public void basicAuthentication() { + template = new RestTemplate(); + headers = new HttpHeaders(); + String trasifexCreds = trasifexUserName + ":" + transifexPassord; + byte[] transifexCredsBytes = trasifexCreds.getBytes(); + byte[] base64CredsBytes = Base64.encodeBase64(transifexCredsBytes); + String base64Creds = new String(base64CredsBytes); + headers.add("Authorization", "Basic " + base64Creds); + } + + //This method verify if article already exists in Transifex + public boolean resourceExists(Article resource) { + //make authentication for Transifex + basicAuthentication(); + StringBuilder url = new StringBuilder(); + url.append("project/"); + url.append(projectSlug); + url.append("/resource/"); + url.append("article-"); + url.append(resource.getSlug()); + + ResponseEntity response; + + HttpEntity request = new HttpEntity<>(headers); + try { + response = template.exchange(baseApiURL + url, HttpMethod.GET, request, String.class); + } catch (HttpClientErrorException e) { + return false; + } + + return response.getStatusCode().value() == 200; + } + +} diff --git a/src/main/resources/spring/spring.properties b/src/main/resources/spring/spring.properties index 68410f7c37c583af069308763381cf5252596a7b..72939b561c761f21cce6c4e86d6c97c53c8f68a7 100644 --- a/src/main/resources/spring/spring.properties +++ b/src/main/resources/spring/spring.properties @@ -125,3 +125,9 @@ cache.tileserver.eviction-policy=LRU # Connection to Elasticsearch elasticsearch.url=http://localhost:9200/ + +transifex.project=genesys-dev +transifex.username=Alexandr19011990 +transifex.password=Alexandr19011990 +transifex.min.translated=80 +transifex.base.api.url =https://www.transifex.com/api/2/ diff --git a/src/main/webapp/WEB-INF/jsp/content/article-edit.jsp b/src/main/webapp/WEB-INF/jsp/content/article-edit.jsp index 782505c14d7a6c63dd4acf34493367bdfb7f6c62..413be4d0d071b778fb3f102540d4bcf9665f71c7 100644 --- a/src/main/webapp/WEB-INF/jsp/content/article-edit.jsp +++ b/src/main/webapp/WEB-INF/jsp/content/article-edit.jsp @@ -1,63 +1,96 @@ -<%@include file="/WEB-INF/jsp/init.jsp"%> +<%@include file="/WEB-INF/jsp/init.jsp" %> -${title} + + ${title} -

- -

- -
" method="post"> - - - -
- -
- " class="span9 form-control required" /> -
-
-
- -
- " class="span9 form-control required" /> -
-
-
- -
- -
-
- - " class="btn btn-primary" /> - " class="btn btn-default">Cancel - - -
- - - - + + }); + } + }); + \ No newline at end of file