001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portlet.journal.util;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.templateparser.BaseTransformerListener;
020    import com.liferay.portal.kernel.util.GetterUtil;
021    import com.liferay.portal.kernel.util.HtmlUtil;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.kernel.xml.Document;
026    import com.liferay.portal.kernel.xml.Element;
027    import com.liferay.portal.kernel.xml.Node;
028    import com.liferay.portal.kernel.xml.SAXReaderUtil;
029    import com.liferay.portlet.dynamicdatamapping.util.DDMXMLUtil;
030    import com.liferay.portlet.journal.model.JournalArticle;
031    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
032    
033    import java.util.List;
034    import java.util.Map;
035    
036    /**
037     * @author Brian Wing Shun Chan
038     * @author Tina Tian
039     */
040    public class ContentTransformerListener extends BaseTransformerListener {
041    
042            @Override
043            public String onScript(
044                    String script, Document document, String languageId,
045                    Map<String, String> tokens) {
046    
047                    if (_log.isDebugEnabled()) {
048                            _log.debug("onScript");
049                    }
050    
051                    return injectEditInPlace(script, document);
052            }
053    
054            @Override
055            public Document onXml(
056                    Document document, String languageId, Map<String, String> tokens) {
057    
058                    if (_log.isDebugEnabled()) {
059                            _log.debug("onXml");
060                    }
061    
062                    replace(document, tokens);
063    
064                    return document;
065            }
066    
067            protected String getDynamicContent(Document document, String elementName) {
068                    String content = null;
069    
070                    try {
071                            Element rootElement = document.getRootElement();
072    
073                            for (Element element : rootElement.elements()) {
074                                    String curElementName = element.attributeValue(
075                                            "name", StringPool.BLANK);
076    
077                                    if (curElementName.equals(elementName)) {
078                                            content = element.elementText("dynamic-content");
079    
080                                            break;
081                                    }
082                            }
083                    }
084                    catch (Exception e) {
085                            _log.error(e, e);
086                    }
087    
088                    return GetterUtil.getString(content);
089            }
090    
091            protected String injectEditInPlace(String script, Document document) {
092                    if (!script.contains("$editInPlace(")) {
093                            return script;
094                    }
095    
096                    try {
097                            List<Node> nodes = document.selectNodes("//dynamic-element");
098    
099                            for (Node node : nodes) {
100                                    Element element = (Element)node;
101    
102                                    String name = GetterUtil.getString(
103                                            element.attributeValue("name"));
104                                    String type = GetterUtil.getString(
105                                            element.attributeValue("type"));
106    
107                                    if (!name.startsWith("reserved-") &&
108                                            (type.equals("text") || type.equals("text_area") ||
109                                             type.equals("text_box"))) {
110    
111                                            script = wrapEditInPlaceField(script, name, type, "data");
112                                            script = wrapEditInPlaceField(
113                                                    script, name, type, "getData()");
114                                    }
115                            }
116                    }
117                    catch (Exception e) {
118                            if (_log.isWarnEnabled()) {
119                                    _log.warn(e.getMessage());
120                            }
121                    }
122    
123                    return script;
124            }
125    
126            protected void replace(Document document, Map<String, String> tokens) {
127                    try {
128                            Element rootElement = document.getRootElement();
129    
130                            long articleGroupId = GetterUtil.getLong(
131                                    tokens.get("article_group_id"));
132    
133                            replace(rootElement, articleGroupId);
134                    }
135                    catch (Exception e) {
136                            if (_log.isWarnEnabled()) {
137                                    _log.warn(e.getMessage());
138                            }
139                    }
140            }
141    
142            protected void replace(Element root, long articleGroupId) throws Exception {
143                    for (Element element : root.elements()) {
144                            List<Element> dynamicContentElements = element.elements(
145                                    "dynamic-content");
146    
147                            for (Element dynamicContentElement : dynamicContentElements) {
148                                    String text = dynamicContentElement.getText();
149    
150                                    text = HtmlUtil.stripComments(text);
151                                    text = HtmlUtil.stripHtml(text);
152                                    text = text.trim();
153    
154                                    // [@articleId;elementName@]
155    
156                                    if (Validator.isNotNull(text) && (text.length() >= 7) &&
157                                            text.startsWith("[@") && text.endsWith("@]")) {
158    
159                                            text = text.substring(2, text.length() - 2);
160    
161                                            int pos = text.indexOf(";");
162    
163                                            if (pos != -1) {
164                                                    String articleId = text.substring(0, pos);
165                                                    String elementName = text.substring(pos + 1);
166    
167                                                    JournalArticle article =
168                                                            JournalArticleLocalServiceUtil.getArticle(
169                                                                    articleGroupId, articleId);
170    
171                                                    dynamicContentElement.clearContent();
172                                                    dynamicContentElement.addCDATA(
173                                                            getDynamicContent(
174                                                                    article.getDocument(), elementName));
175                                            }
176                                    }
177    
178                                    // Make sure to point images to the full path
179    
180                                    else if ((text != null) &&
181                                                     text.startsWith("/image/journal/article?img_id")) {
182    
183                                            dynamicContentElement.setText(
184                                                    "@cdn_host@@root_path@" + text);
185                                    }
186                            }
187    
188                            replace(element, articleGroupId);
189                    }
190            }
191    
192            /**
193             * Fill one article with content from another approved article. See the
194             * article DOCUMENTATION-INSTALLATION-BORLAND for a sample use case.
195             *
196             * @return the processed string
197             */
198            protected String replace(String xml, Map<String, String> tokens) {
199                    try {
200                            Document document = SAXReaderUtil.read(xml);
201    
202                            replace(document, tokens);
203    
204                            xml = DDMXMLUtil.formatXML(document);
205                    }
206                    catch (Exception e) {
207                            if (_log.isWarnEnabled()) {
208                                    _log.warn(e.getMessage());
209                            }
210                    }
211    
212                    return xml;
213            }
214    
215            protected String wrapEditInPlaceField(
216                    String script, String name, String type, String call) {
217    
218                    String field = "$" + name + "." + call;
219                    String wrappedField =
220                            "<span class=\"journal-content-eip-" + type + "\" " +
221                                    "id=\"journal-content-field-name-" + name + "\">" + field +
222                                            "</span>";
223    
224                    return StringUtil.replace(
225                            script, "$editInPlace(" + field + ")", wrappedField);
226            }
227    
228            private static final Log _log = LogFactoryUtil.getLog(
229                    ContentTransformerListener.class);
230    
231    }