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}