package com.psddev.cms.db; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.psddev.cms.rte.ExternalContentCache; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import com.psddev.dari.util.HtmlWriter; import com.psddev.dari.util.IoUtils; import com.psddev.dari.util.ObjectUtils; import com.psddev.dari.util.StringUtils; import com.psddev.dari.util.TypeReference; /** * @see <a href="http://oembed.com/">oEmbed Specification</a> */ @ToolUi.Referenceable public class ExternalContent extends Content implements Renderer { @Required @ToolUi.NoteHtml("<a class=\"icon icon-action-preview\" target=\"contentExternalPreview\" onclick=\"this.href = CONTEXT_PATH + '/content/externalPreview?url=' + encodeURIComponent($(this).closest('.inputContainer').find('> .inputSmall > textarea').val() || ''); return true;\">Preview</a>") private String url; private transient Document document; private Integer maximumWidth; private Integer maximumHeight; @ToolUi.Hidden private Map<String, Object> response; public String getUrl() { return url; } public void setUrl(String url) { this.url = url; this.document = null; } /** * Returns a <a href="http://jsoup.org/">jsoup</a> {@link Document} * associated with the URL, downloading it if necessary. * * @return Never {@code null}. */ public Document getOrCreateDocument() throws IOException { if (document == null) { document = Jsoup.connect(url).get(); } return document; } public Integer getMaximumWidth() { return maximumWidth; } public void setMaximumWidth(Integer maximumWidth) { this.maximumWidth = maximumWidth; } public Integer getMaximumHeight() { return maximumHeight; } public void setMaximumHeight(Integer maximumHeight) { this.maximumHeight = maximumHeight; } public Map<String, Object> getResponse() { if (response == null) { response = ExternalContentCache.get(getUrl(), getMaximumWidth(), getMaximumHeight()); } return response; } public Map<String, Object> getResponseByOEmbedUrl(String oEmbedUrl) { try { Integer width = getMaximumWidth(); Integer height = getMaximumHeight(); Map<String, Object> newResponse = ObjectUtils.to( new TypeReference<Map<String, Object>>() { }, ObjectUtils.fromJson(IoUtils.toString(new URL( StringUtils.addQueryParameters(oEmbedUrl, "maxwidth", width, "maxheight", height))))); newResponse.put("_url", url); newResponse.put("_maximumWidth", width); newResponse.put("_maximumHeight", height); response = newResponse; } catch (IOException error) { error.printStackTrace(); } return response; } public void setResponse(Map<String, Object> response) { this.response = response; } @Override public String getLabel() { String url = getUrl(); if (response != null) { String title = ObjectUtils.to(String.class, response.get("title")); if (!ObjectUtils.isBlank(title)) { StringBuilder label = new StringBuilder(); try { String host = new URL(url).getHost(); if (!ObjectUtils.isBlank(host)) { label.append("("); label.append(host); label.append(") "); } } catch (MalformedURLException error) { // Not a valid URL, but that's OK. } label.append(title); return label.toString(); } } return url; } @Override protected void beforeCommit() { super.beforeCommit(); getResponse(); } @Override public void renderObject( HttpServletRequest httpRequest, HttpServletResponse httpResponse, HtmlWriter writer) throws IOException { Map<String, Object> response = getResponse(); if (!ObjectUtils.isBlank(response)) { Object type = response.get("type"); if ("photo".equals(type)) { writer.writeElement("img", "src", response.get("url"), "width", response.get("width"), "height", response.get("height"), "alt", response.get("title")); } else if ("video".equals(type)) { writer.writeRaw(response.get("html")); } else if ("link".equals(type)) { writer.writeStart("a", "href", response.get("_url")); writer.writeHtml(response.get("title")); writer.writeEnd(); } else if ("rich".equals(type)) { writer.writeRaw(response.get("html")); } } } }