001/*
002 *  Copyright 2017 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.frontedition;
017
018import java.util.ArrayList;
019import java.util.Collections;
020import java.util.HashMap;
021import java.util.LinkedHashMap;
022import java.util.List;
023import java.util.Map;
024import java.util.Set;
025
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029
030import org.ametys.core.ui.ClientSideElement;
031import org.ametys.core.ui.ClientSideElement.Script;
032import org.ametys.core.ui.ClientSideElement.ScriptFile;
033import org.ametys.core.ui.widgets.richtext.RichTextConfiguration;
034import org.ametys.core.ui.widgets.richtext.RichTextConfigurationExtensionPoint;
035import org.ametys.plugins.core.ui.minimize.HashCache;
036import org.ametys.web.transformation.xslt.AmetysXSLTHelper;
037
038/**
039 * Helper for preparing the Ametys Edition
040 */
041public class AmetysFrontEditionHelper implements Serviceable
042{
043    private static HashCache _hashCache;
044    private static RichTextConfigurationExtensionPoint _richTextConfigurationExtensionPoint;
045
046    public void service(ServiceManager manager) throws ServiceException
047    {
048        _hashCache = (HashCache) manager.lookup(HashCache.ROLE);
049        _richTextConfigurationExtensionPoint = (RichTextConfigurationExtensionPoint) manager.lookup(RichTextConfigurationExtensionPoint.ROLE);
050    }
051    
052    /**
053     * Prepare a hashcode for js files
054     * @param locale The language code to use
055     * @param rtlMode Is for right-to-left language?
056     * @return The new hashcode to read the minimified concatened file
057     */
058    public static String prepareJSFiles(String locale, boolean rtlMode)
059    {
060        Map<String, String> filesInfos = new HashMap<>();
061        filesInfos.put("media", "");
062        filesInfos.put("tag", "script");
063        
064        Map<String, Map<String, String>> files = new LinkedHashMap<>();
065        files.put("/plugins/extjs6/resources/ext-all.js", filesInfos); 
066        files.put("/plugins/extjs6/resources/classic/locale/locale-" + locale + ".js", filesInfos);
067        files.put("/plugins/extjs6/resources/classic/theme-triton/theme-triton.js", filesInfos);
068
069        files.put("/plugins/core-ui/resources/js/Ext.fixes.js", filesInfos);
070        files.put("/plugins/core-ui/resources/js/Ext.enhancements.js", filesInfos);
071        
072        files.put("/plugins/core-ui/resources/js/Ametys.js", filesInfos);
073        files.put("/plugins/core-ui/resources/js/Ametys/mask/GlobalLoadMask.js", filesInfos);
074        
075        files.put("/plugins/core-ui/resources/js/Ametys/log/Logger.js", filesInfos);
076        files.put("/plugins/core-ui/resources/js/Ametys/log/Logger/Entry.js", filesInfos);
077        files.put("/plugins/core-ui/resources/js/Ametys/log/LoggerFactory.js", filesInfos);
078        files.put("/plugins/core-ui/resources/js/Ametys/log/ErrorDialog.js", filesInfos);
079        
080        files.put("/plugins/core-ui/resources/js/Ametys/window/DialogBox.js", filesInfos);
081        files.put("/plugins/core-ui/resources/js/Ametys/window/MessageBox.js", filesInfos);
082        
083        files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractField.js", filesInfos);
084        files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractFieldsWrapper.js", filesInfos);
085        files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractQueryableComboBox.js", filesInfos);
086        files.put("/plugins/core-ui/resources/js/Ametys/form/field/DateTime.js", filesInfos);
087        files.put("/plugins/core-ui/resources/js/Ametys/form/field/StringTime.js", filesInfos);
088        files.put("/plugins/core-ui/resources/js/Ametys/form/field/Password.js", filesInfos);
089        files.put("/plugins/core-ui/resources/js/Ametys/form/field/ChangePassword.js", filesInfos);
090        files.put("/plugins/core-ui/resources/js/Ametys/form/field/ReferencedNumberField.js", filesInfos);
091        files.put("/plugins/core-ui/resources/js/Ametys/form/field/RichText.js", filesInfos);
092        files.put("/plugins/core-ui/resources/js/Ametys/form/field/RichText/SplitterTracker.js", filesInfos);
093        files.put("/plugins/core-ui/resources/js/Ametys/form/field/TextArea.js", filesInfos);
094        files.put("/plugins/core-ui/resources/js/Ametys/form/field/ColorSelector.js", filesInfos);
095        files.put("/plugins/core-ui/resources/js/Ametys/form/field/SelectUserDirectory.js", filesInfos);
096        files.put("/plugins/core-ui/resources/js/Ametys/form/field/SelectGroupDirectories.js", filesInfos);
097        files.put("/plugins/core-ui/resources/js/Ametys/form/field/Code.js", filesInfos);
098        files.put("/plugins/tiny_mce/resources/js/tinymce.min.js", filesInfos);
099        files.put("/plugins/codemirror/resources/js/codemirror.js", filesInfos);
100        files.put("/plugins/codemirror/resources/js/addon/edit/matchbrackets.js", filesInfos);
101        files.put("/plugins/codemirror/resources/js/addon/selection/active-line.js", filesInfos);
102        files.put("/plugins/codemirror/resources/js/mode/xml/xml.js", filesInfos);
103        files.put("/plugins/codemirror/resources/js/mode/javascript/javascript.js", filesInfos);
104        files.put("/plugins/codemirror/resources/js/mode/css/css.js", filesInfos);
105        files.put("/plugins/codemirror/resources/js/mode/htmlmixed/htmlmixed.js", filesInfos);
106        
107        files.put("/plugins/core-ui/resources/js/Ametys/data/ServerCaller.js", filesInfos);
108        files.put("/plugins/core-ui/resources/js/Ametys/data/ServerComm.js", filesInfos);
109        files.put("/plugins/core-ui/resources/js/Ametys/data/ServerCommProxy.js", filesInfos);
110        files.put("/plugins/core-ui/resources/js/Ametys/data/ServerComm/TimeoutDialog.js", filesInfos);
111
112        files.put("/plugins/core-ui/resources/js/Ametys/form/widget/RichText/RichTextConfiguration.js", filesInfos);
113
114        files.put("/plugins/front-edition/resources/js/front-comm.js", filesInfos);
115        files.put("/plugins/front-edition/resources/js/front-widget.js", filesInfos);
116        files.put("/plugins/core-ui/resources/js/Ametys/helper/EnterURL.js", filesInfos);
117        files.put("/plugins/core-ui/resources/js/Ametys/helper/FileUpload.js", filesInfos);
118        files.put("/plugins/web/resources/js/Ametys/web/helper/ChoosePage.js", filesInfos);
119        files.put("/plugins/web/resources/js/Ametys/web/helper/ContextToolbar.js", filesInfos);
120        files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree.js", filesInfos);
121        files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree/Page.js", filesInfos);
122        files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree/Sitemap.js", filesInfos);
123        files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree/Site.js", filesInfos);
124        files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Links.js", filesInfos);
125        files.put("/plugins/web/resources/js/Ametys/plugins/web/editor/Links.js", filesInfos);
126        files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Images.js", filesInfos);
127        
128        files.put("/plugins/front-edition/resources/js/tinymce/lists.js", filesInfos);
129        files.put("/plugins/front-edition/resources/js/tinymce/links.js", filesInfos);
130        files.put("/plugins/front-edition/resources/js/tinymce/styles.js", filesInfos);
131        files.put("/plugins/front-edition/resources/js/tinymce/images.js", filesInfos);
132
133        
134        // Let's add all richtextconfiguration files
135        _addRichTextConfigurationFiles(files, filesInfos, locale, rtlMode, true);
136        
137        return _hashCache.createHash(files, locale);
138    }
139
140    /**
141     * Prepare a hashcode for css files
142     * @param locale The language code to use
143     * @param rtlMode Is for right-to-left language?
144     * @return The new hashcode to read the minimified concatened file
145     */
146    public static String prepareCSSFiles(String locale, boolean rtlMode)
147    {
148        Map<String, String> filesInfos = new HashMap<>();
149        filesInfos.put("media", "");
150        filesInfos.put("tag", "link");
151        
152        Map<String, Map<String, String>> files = new LinkedHashMap<>();
153        files.put("/plugins/extjs6/resources/classic/theme-triton/resources/theme-triton-all.css", filesInfos); 
154        files.put("/plugins/front-edition/resources/css/theme-ametys-base-light.css", filesInfos); 
155        files.put("/plugins/core-ui/resources/font/ametys/AmetysIcon.css", filesInfos);
156        
157        // Let's add all richtextconfiguration files
158        _addRichTextConfigurationFiles(files, filesInfos, locale, rtlMode, false);
159        
160        return _hashCache.createHash(files, locale);
161    }
162    
163
164    private static List<ScriptFile> _getRichTextConfigurationFiles(boolean scripts, Map<String, Object> contextParameters)
165    {
166        List<ScriptFile> files = new ArrayList<>();
167        
168        for (String richTextConfigurationId : _richTextConfigurationExtensionPoint.getExtensionsIds())
169        {
170            RichTextConfiguration richTextConfiguration = _richTextConfigurationExtensionPoint.getExtension(richTextConfigurationId);
171            for (String category : richTextConfiguration.getCategories())
172            {
173                Set<ClientSideElement> convertors = richTextConfiguration.getConvertors(category, contextParameters);
174                if (convertors != null)
175                {
176                    for (ClientSideElement convertor : convertors)
177                    {
178                        List<Script> scriptsToAdd = convertor.getScripts(Collections.EMPTY_MAP);
179                        if (scriptsToAdd != null)
180                        {
181                            for (Script script : scriptsToAdd)
182                            {
183                                List<ScriptFile> scriptFiles = scripts ? script.getScriptFiles() : script.getCSSFiles();
184                                if (scriptFiles != null)
185                                {
186                                    files.addAll(scriptFiles);
187                                }
188                            }
189                        }
190                    }
191                }
192                
193                Set<ClientSideElement> validators = richTextConfiguration.getValidators(category, contextParameters);
194                if (validators != null)
195                {
196                    for (ClientSideElement validator : validators)
197                    {
198                        List<Script> scriptsToAdd = validator.getScripts(Collections.EMPTY_MAP);
199                        if (scriptsToAdd != null)
200                        {
201                            for (Script script : scriptsToAdd)
202                            {
203                                List<ScriptFile> scriptFiles = scripts ? script.getScriptFiles() : script.getCSSFiles();
204                                if (scriptFiles != null)
205                                {
206                                    files.addAll(scriptFiles);
207                                }
208                            }
209                        }
210                    }
211                }
212            }
213        }
214
215        return files;
216    }
217    
218
219    private static void _addRichTextConfigurationFiles(Map<String, Map<String, String>> files, Map<String, String> filesInfos, String locale, boolean rtlMode, boolean scripts)
220    {
221        Map<String, Object> contextParameters = new HashMap<>();
222        contextParameters.put("siteName", AmetysXSLTHelper.site());
223        
224        List<ScriptFile> richTextConfigurationFiles = _getRichTextConfigurationFiles(scripts, contextParameters);
225        for (ScriptFile file : richTextConfigurationFiles)
226        {
227            String uri = null;
228            if (file.isLangSpecific())
229            {
230                if (file.getLangPaths().containsKey(locale))
231                {
232                    uri = file.getLangPaths().get(locale);
233                }
234                else if (file.getLangPaths().containsKey(file.getDefaultLang()))
235                {
236                    uri = file.getLangPaths().get(file.getDefaultLang());
237                }
238            }
239            else
240            {
241                if (!"true".equals(file.getDebugMode())
242                        && (file.getRtlMode() == null || "all".equals(file.getRtlMode()) || Boolean.toString(rtlMode).equals(file.getRtlMode())))
243                {
244                    uri = file.getPath();
245                }
246            }
247            
248            if (uri != null)
249            {
250                files.put(uri, filesInfos);
251            }
252        }
253    }    
254}