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.Arrays; 020import java.util.Collections; 021import java.util.HashMap; 022import java.util.LinkedHashMap; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026 027import javax.jcr.RepositoryException; 028 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.avalon.framework.service.Serviceable; 032import org.apache.commons.lang3.ArrayUtils; 033import org.apache.commons.lang3.StringUtils; 034 035import org.ametys.cms.repository.Content; 036import org.ametys.cms.repository.WorkflowAwareContent; 037import org.ametys.cms.workflow.ContentWorkflowHelper; 038import org.ametys.core.right.RightManager; 039import org.ametys.core.right.RightManager.RightResult; 040import org.ametys.core.ui.ClientSideElement; 041import org.ametys.core.ui.ClientSideElement.Script; 042import org.ametys.core.ui.ClientSideElement.ScriptFile; 043import org.ametys.core.ui.widgets.richtext.RichTextConfiguration; 044import org.ametys.core.ui.widgets.richtext.RichTextConfigurationExtensionPoint; 045import org.ametys.core.util.JSONUtils; 046import org.ametys.plugins.core.ui.minimize.HashCache; 047import org.ametys.plugins.repository.AmetysObject; 048import org.ametys.plugins.repository.AmetysObjectResolver; 049import org.ametys.plugins.repository.AmetysRepositoryException; 050import org.ametys.plugins.repository.UnknownAmetysObjectException; 051import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject; 052import org.ametys.plugins.repository.jcr.JCRAmetysObject; 053import org.ametys.plugins.repository.version.VersionableAmetysObject; 054import org.ametys.plugins.workflow.support.WorkflowHelper; 055import org.ametys.web.WebConstants; 056import org.ametys.web.cache.PageHelper; 057import org.ametys.web.renderingcontext.RenderingContext; 058import org.ametys.web.repository.page.ModifiablePage; 059import org.ametys.web.repository.page.ModifiableZone; 060import org.ametys.web.repository.page.Page; 061import org.ametys.web.repository.page.ZoneItem; 062import org.ametys.web.repository.site.Site; 063import org.ametys.web.repository.site.SiteManager; 064import org.ametys.web.repository.sitemap.Sitemap; 065import org.ametys.web.transformation.xslt.AmetysXSLTHelper; 066 067/** 068 * Helper for preparing the Ametys Edition 069 */ 070public class AmetysFrontEditionHelper implements Serviceable 071{ 072 /** The right's id from front-edition access */ 073 public static final String FRONT_EDITION_RIGHT_ID = "Front_Edition_Access_Right"; 074 075 private static AmetysObjectResolver _ametysObjectResolver; 076 private static HashCache _hashCache; 077 private static RichTextConfigurationExtensionPoint _richTextConfigurationExtensionPoint; 078 private static RightManager _rightManager; 079 private static ContentWorkflowHelper _contentWorkflowHelper; 080 private static PageHelper _pageHelper; 081 private static WorkflowHelper _workflowHelper; 082 private static JSONUtils _jsonUtils; 083 private static SiteManager _siteManager; 084 085 public void service(ServiceManager manager) throws ServiceException 086 { 087 _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 088 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 089 _hashCache = (HashCache) manager.lookup(HashCache.ROLE); 090 _richTextConfigurationExtensionPoint = (RichTextConfigurationExtensionPoint) manager.lookup(RichTextConfigurationExtensionPoint.ROLE); 091 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 092 _contentWorkflowHelper = (ContentWorkflowHelper) manager.lookup(ContentWorkflowHelper.ROLE); 093 _pageHelper = (PageHelper) manager.lookup(PageHelper.ROLE); 094 _workflowHelper = (WorkflowHelper) manager.lookup(WorkflowHelper.ROLE); 095 _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE); 096 } 097 098 /** 099 * Prepare a hashcode for js files 100 * @param locale The language code to use 101 * @param rtlMode Is for right-to-left language? 102 * @return The new hashcode to read the minimified concatened file 103 */ 104 public static String prepareJSFiles(String locale, boolean rtlMode) 105 { 106 Map<String, String> filesInfos = new HashMap<>(); 107 filesInfos.put("media", ""); 108 filesInfos.put("tag", "script"); 109 110 Map<String, Map<String, String>> files = new LinkedHashMap<>(); 111 files.put("/plugins/extjs6/resources/ext-all.js", filesInfos); 112 files.put("/plugins/extjs6/resources/classic/locale/locale-" + locale + ".js", filesInfos); 113 files.put("/plugins/extjs6/resources/classic/theme-triton/theme-triton.js", filesInfos); 114 115 files.put("/plugins/core-ui/resources/js/Ext.fixes.js", filesInfos); 116 files.put("/plugins/core-ui/resources/js/Ext.enhancements.js", filesInfos); 117 118 files.put("/plugins/core-ui/resources/js/Ametys.js", filesInfos); 119 files.put("/plugins/core-ui/resources/js/Ametys/mask/GlobalLoadMask.js", filesInfos); 120 121 files.put("/plugins/core-ui/resources/js/Ametys/log/Logger.js", filesInfos); 122 files.put("/plugins/core-ui/resources/js/Ametys/log/Logger/Entry.js", filesInfos); 123 files.put("/plugins/core-ui/resources/js/Ametys/log/LoggerFactory.js", filesInfos); 124 files.put("/plugins/core-ui/resources/js/Ametys/log/ErrorDialog.js", filesInfos); 125 126 files.put("/plugins/core-ui/resources/js/Ametys/window/DialogBox.js", filesInfos); 127 files.put("/plugins/core-ui/resources/js/Ametys/window/MessageBox.js", filesInfos); 128 129 files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractField.js", filesInfos); 130 files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractFieldsWrapper.js", filesInfos); 131 files.put("/plugins/core-ui/resources/js/Ametys/form/AbstractQueryableComboBox.js", filesInfos); 132 files.put("/plugins/core-ui/resources/js/Ametys/form/field/DateTime.js", filesInfos); 133 files.put("/plugins/core-ui/resources/js/Ametys/form/field/StringTime.js", filesInfos); 134 files.put("/plugins/core-ui/resources/js/Ametys/form/field/Password.js", filesInfos); 135 files.put("/plugins/core-ui/resources/js/Ametys/form/field/ChangePassword.js", filesInfos); 136 files.put("/plugins/core-ui/resources/js/Ametys/form/field/ReferencedNumberField.js", filesInfos); 137 files.put("/plugins/core-ui/resources/js/Ametys/form/field/RichText.js", filesInfos); 138 files.put("/plugins/core-ui/resources/js/Ametys/form/field/RichText/SplitterTracker.js", filesInfos); 139 files.put("/plugins/core-ui/resources/js/Ametys/form/field/TextArea.js", filesInfos); 140 files.put("/plugins/core-ui/resources/js/Ametys/form/field/ColorSelector.js", filesInfos); 141 files.put("/plugins/core-ui/resources/js/Ametys/form/field/SelectUserDirectory.js", filesInfos); 142 files.put("/plugins/core-ui/resources/js/Ametys/form/field/SelectGroupDirectories.js", filesInfos); 143 files.put("/plugins/core-ui/resources/js/Ametys/form/field/Code.js", filesInfos); 144 files.put("/plugins/tiny_mce/resources/js/tinymce.js", filesInfos); 145 files.put("/plugins/codemirror/resources/js/codemirror.js", filesInfos); 146 files.put("/plugins/codemirror/resources/js/addon/edit/matchbrackets.js", filesInfos); 147 files.put("/plugins/codemirror/resources/js/addon/selection/active-line.js", filesInfos); 148 files.put("/plugins/codemirror/resources/js/mode/xml/xml.js", filesInfos); 149 files.put("/plugins/codemirror/resources/js/mode/javascript/javascript.js", filesInfos); 150 files.put("/plugins/codemirror/resources/js/mode/css/css.js", filesInfos); 151 files.put("/plugins/codemirror/resources/js/mode/htmlmixed/htmlmixed.js", filesInfos); 152 153 files.put("/plugins/core-ui/resources/js/Ametys/data/ServerCaller.js", filesInfos); 154 files.put("/plugins/core-ui/resources/js/Ametys/data/ServerComm.js", filesInfos); 155 files.put("/plugins/core-ui/resources/js/Ametys/data/ServerCommProxy.js", filesInfos); 156 files.put("/plugins/core-ui/resources/js/Ametys/data/ServerComm/TimeoutDialog.js", filesInfos); 157 158 files.put("/plugins/core-ui/resources/js/Ametys/form/widget/RichText/RichTextConfiguration.js", filesInfos); 159 160 files.put("/plugins/front-edition/resources/js/front-comm.js", filesInfos); 161 files.put("/plugins/front-edition/resources/js/front-widget.js", filesInfos); 162// files.put("/plugins/front-edition/resources/js/front-page.js", filesInfos); 163 files.put("/plugins/core-ui/resources/js/Ametys/helper/EnterURL.js", filesInfos); 164 files.put("/plugins/core-ui/resources/js/Ametys/helper/FileUpload.js", filesInfos); 165 files.put("/plugins/web/resources/js/Ametys/web/helper/ChoosePage.js", filesInfos); 166 files.put("/plugins/web/resources/js/Ametys/web/helper/ContextToolbar.js", filesInfos); 167 files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree.js", filesInfos); 168 files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree/Page.js", filesInfos); 169 files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapTree/Sitemap.js", filesInfos); 170 files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree/Site.js", filesInfos); 171 files.put("/plugins/cms/resources/js/Ametys/cms/editor/LinkHandler.js", filesInfos); 172 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Links.js", filesInfos); 173 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Links/LinkHandler.js", filesInfos); 174 files.put("/plugins/web/resources/js/Ametys/plugins/web/editor/Links.js", filesInfos); 175 files.put("/plugins/web/resources/js/Ametys/plugins/web/editor/PageLinkHandler.js", filesInfos); 176 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Images.js", filesInfos); 177 178 files.put("/plugins/front-edition/resources/js/tinymce/lists.js", filesInfos); 179 files.put("/plugins/front-edition/resources/js/tinymce/links.js", filesInfos); 180 files.put("/plugins/front-edition/resources/js/tinymce/styles.js", filesInfos); 181 files.put("/plugins/front-edition/resources/js/tinymce/images.js", filesInfos); 182 files.put("/plugins/front-edition/resources/js/tinymce/save.js", filesInfos); 183 184 //TinyMCE Tables 185 files.put("/plugins/front-edition/resources/js/tinymce/tables.js", filesInfos); 186 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/Tables.js", filesInfos); 187 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/editor/BasicActions.js", filesInfos); 188 //TinyMCE Images 189 files.put("/plugins/cms/resources/js/Ametys/cms/uihelper/ChooseResource.js", filesInfos); 190 files.put("/plugins/explorer/resources/js/Ametys/explorer/tree/ExplorerTree.js", filesInfos); 191 files.put("/plugins/explorer/resources/js/Ametys/explorer/tree/ExplorerTree/NodeEntry.js", filesInfos); 192 files.put("/plugins/explorer/resources/js/Ametys/explorer/Resource.js", filesInfos); 193 files.put("/plugins/explorer/resources/js/Ametys/explorer/ExplorerNodeDAO.js", filesInfos); 194 files.put("/plugins/explorer/resources/js/Ametys/explorer/applications/ExplorerApplicationProvider.js", filesInfos); 195 files.put("/plugins/cms/resources/js/Ametys/cms/attach/AttachmentsExplorerTree.js", filesInfos); 196 files.put("/plugins/cms/resources/js/Ametys/cms/uihelper/ChooseAttachmentFile.js", filesInfos); 197 files.put("/plugins/front-edition/resources/js/Ametys/override/cms/uihelper/ChooseAttachmentFile.js", filesInfos); 198 files.put("/plugins/explorer/resources/js/Ametys/explorer/resources/actions/FileActions.js", filesInfos); 199 files.put("/plugins/explorer/resources/js/Ametys/explorer/resources/helper/ResourceUpload.js", filesInfos); 200 201 //Empty Message class 202 files.put("/plugins/core-ui/resources/js/Ametys/message/Message.js", filesInfos); 203 files.put("/plugins/core-ui/resources/js/Ametys/message/MessageTarget.js", filesInfos); 204 files.put("/plugins/core-ui/resources/js/Ametys/message/MessageTargetFactory.js", filesInfos); 205 files.put("/plugins/core-ui/resources/js/Ametys/message/factory/DefaultMessageTargetFactory.js", filesInfos); 206 files.put("/plugins/front-edition/resources/js/Ametys/message/MessageTargetHelper.js", filesInfos); 207 //add page 208 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard.js", filesInfos); 209 files.put("/plugins/front-edition/resources/js/Ametys/override/plugins/web/page/AddPageWizard.js", filesInfos); 210 files.put("/plugins/web/resources/js/Ametys/web/sitemap/SitemapDAO.js", filesInfos); 211 files.put("/plugins/web/resources/js/Ametys/web/sitemap/Sitemap.js", filesInfos); 212 files.put("/plugins/web/resources/js/Ametys/web/page/PageDAO.js", filesInfos); 213 files.put("/plugins/front-edition/resources/js/Ametys/override/web/page/PageDAO.js", filesInfos); 214 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/Card.js", filesInfos); 215 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/CreatePageCard.js", filesInfos); 216 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/PageContentCard.js", filesInfos); 217 files.put("/plugins/front-edition/resources/js/Ametys/override/plugins/web/page/AddPageWizard/PageContentCard.js", filesInfos); 218 files.put("/plugins/cms/resources/js/Ametys/cms/content/ContentDAO.js", filesInfos); 219 files.put("/plugins/web/resources/js/Ametys/web/content/ContentDAO.js", filesInfos); 220 files.put("/plugins/front-edition/resources/js/Ametys/override/cms/content/ContentDAO.js", filesInfos); 221 files.put("/plugins/cms/resources/js/Ametys/cms/content/Content.js", filesInfos); 222 files.put("/plugins/core-ui/resources/js/Ametys/navhistory/HistoryDAO.js", filesInfos); 223 files.put("/plugins/core-ui/resources/js/Ametys/window/MessageBox.js", filesInfos); 224 files.put("/plugins/front-edition/resources/js/Ametys/tool/ToolsManager.js", filesInfos); 225 226 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/PageTypeCard.js", filesInfos); 227 files.put("/plugins/front-edition/resources/js/Ametys/override/plugins/web/page/AddPageWizard/PageTypeCard.js", filesInfos); 228 files.put("/plugins/web/resources/js/Ametys/web/form/widget/SelectPage.js", filesInfos); 229 files.put("/plugins/front-edition/resources/js/Ametys/override/web/form/widget/SelectPage.js", filesInfos); 230 files.put("/plugins/web/resources/js/Ametys/web/form/widget/SelectSite.js", filesInfos); 231 files.put("/plugins/web/resources/js/Ametys/web/helper/ChooseSite.js", filesInfos); 232 files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree.js", filesInfos); 233 files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree/Site.js", filesInfos); 234 files.put("/plugins/web/resources/js/Ametys/web/helper/ContextToolbar.js", filesInfos); 235 files.put("/plugins/web/resources/js/Ametys/web/site/SitesTree/Site.js", filesInfos); 236 files.put("/plugins/web/resources/js/Ametys/web/form/widget/SelectPage/PageEntry.js", filesInfos); 237 files.put("/plugins/web/resources/js/Ametys/plugins/web/page/AddPageWizard/TagsCard.js", filesInfos); 238 files.put("/plugins/web/resources/js/Ametys/web/page/Page.js", filesInfos); 239 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/tag/TagsTreePanel.js", filesInfos); 240 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/tag/TagsTreePanel/TagNode.js", filesInfos); 241 242 //delete page 243 files.put("/plugins/front-edition/resources/js/Ametys/override/Ametys.js", filesInfos); 244 files.put("/plugins/web/resources/js/Ametys/plugins/web/sitemap/SitemapActions.js", filesInfos); 245 246 //page tags 247 files.put("/plugins/web/resources/js/Ametys/plugins/web/tag/AffectTagAction.js", filesInfos); 248 files.put("/plugins/cms/resources/js/Ametys/cms/uihelper/ChooseTag.js", filesInfos); 249 files.put("/plugins/web/resources/js/Ametys/web/helper/ChooseTag.js", filesInfos); 250 files.put("/plugins/cms/resources/js/Ametys/plugins/cms/tag/TagActions.js", filesInfos); 251 files.put("/plugins/web/resources/js/Ametys/plugins/web/tag/TagsTreePanel.js", filesInfos); 252 253 // ping 254 files.put("/plugins/core-ui/resources/js/Ametys/plugins/coreui/system/StartTimeChecker.js", filesInfos); 255 256 // actions on content 257 files.put("/plugins/web/resources/js/Ametys/plugins/web/zone/ZoneActions.js", filesInfos); 258 files.put("/plugins/web/resources/js/Ametys/plugins/web/zone/ZoneDAO.js", filesInfos); 259 260 // file widget 261 files.put("/plugins/core-ui/resources/js/Ametys/form/widget/File.js", filesInfos); 262 files.put("/plugins/core-ui/resources/js/Ametys/form/widget/File/FileSource.js", filesInfos); 263 files.put("/plugins/core-ui/resources/js/Ametys/form/widget/File/External.js", filesInfos); 264 files.put("/plugins/cms/resources/js/Ametys/cms/form/widget/File/Resource.js", filesInfos); 265 266 // Let's add all richtextconfiguration files 267 _addRichTextConfigurationFiles(files, filesInfos, locale, rtlMode, true); 268 269 return _hashCache.createHash(files, locale); 270 } 271 272 /** 273 * Prepare a hashcode for css files 274 * @param locale The language code to use 275 * @param rtlMode Is for right-to-left language? 276 * @return The new hashcode to read the minimified concatened file 277 */ 278 public static String prepareCSSFiles(String locale, boolean rtlMode) 279 { 280 Map<String, String> filesInfos = new HashMap<>(); 281 filesInfos.put("media", ""); 282 filesInfos.put("tag", "link"); 283 284 Map<String, Map<String, String>> files = new LinkedHashMap<>(); 285 files.put("/plugins/extjs6/resources/classic/theme-triton/resources/theme-triton-all.css", filesInfos); 286 files.put("/plugins/front-edition/resources/css/theme-ametys-base-light.css", filesInfos); 287 files.put("/plugins/core-ui/resources/font/ametys/AmetysIcon.css", filesInfos); 288 289 // Let's add all richtextconfiguration files 290 _addRichTextConfigurationFiles(files, filesInfos, locale, rtlMode, false); 291 292 return _hashCache.createHash(files, locale); 293 } 294 295 private static List<ScriptFile> _getRichTextConfigurationFiles(boolean scripts, Map<String, Object> contextParameters) 296 { 297 List<ScriptFile> files = new ArrayList<>(); 298 299 for (String richTextConfigurationId : _richTextConfigurationExtensionPoint.getExtensionsIds()) 300 { 301 RichTextConfiguration richTextConfiguration = _richTextConfigurationExtensionPoint.getExtension(richTextConfigurationId); 302 for (String category : richTextConfiguration.getCategories()) 303 { 304 Set<ClientSideElement> convertors = richTextConfiguration.getConvertors(category, contextParameters); 305 if (convertors != null) 306 { 307 for (ClientSideElement convertor : convertors) 308 { 309 List<Script> scriptsToAdd = convertor.getScripts(Collections.EMPTY_MAP); 310 if (scriptsToAdd != null) 311 { 312 for (Script script : scriptsToAdd) 313 { 314 List<ScriptFile> scriptFiles = scripts ? script.getScriptFiles() : script.getCSSFiles(); 315 if (scriptFiles != null) 316 { 317 files.addAll(scriptFiles); 318 } 319 } 320 } 321 } 322 } 323 324 Set<ClientSideElement> validators = richTextConfiguration.getValidators(category, contextParameters); 325 if (validators != null) 326 { 327 for (ClientSideElement validator : validators) 328 { 329 List<Script> scriptsToAdd = validator.getScripts(Collections.EMPTY_MAP); 330 if (scriptsToAdd != null) 331 { 332 for (Script script : scriptsToAdd) 333 { 334 List<ScriptFile> scriptFiles = scripts ? script.getScriptFiles() : script.getCSSFiles(); 335 if (scriptFiles != null) 336 { 337 files.addAll(scriptFiles); 338 } 339 } 340 } 341 } 342 } 343 } 344 } 345 346 return files; 347 } 348 349 private static void _addRichTextConfigurationFiles(Map<String, Map<String, String>> files, Map<String, String> filesInfos, String locale, boolean rtlMode, boolean scripts) 350 { 351 Map<String, Object> contextParameters = new HashMap<>(); 352 contextParameters.put("siteName", AmetysXSLTHelper.site()); 353 354 List<ScriptFile> richTextConfigurationFiles = _getRichTextConfigurationFiles(scripts, contextParameters); 355 for (ScriptFile file : richTextConfigurationFiles) 356 { 357 String uri = null; 358 if (file.isLangSpecific()) 359 { 360 if (file.getLangPaths().containsKey(locale)) 361 { 362 uri = file.getLangPaths().get(locale); 363 } 364 else if (file.getLangPaths().containsKey(file.getDefaultLang())) 365 { 366 uri = file.getLangPaths().get(file.getDefaultLang()); 367 } 368 } 369 else 370 { 371 if (file.getRtlMode() == null || "all".equals(file.getRtlMode()) || Boolean.toString(rtlMode).equals(file.getRtlMode())) 372 { 373 uri = file.getPath(); 374 } 375 } 376 377 if (uri != null) 378 { 379 files.put(uri, filesInfos); 380 } 381 } 382 } 383 /** 384 * Check if we can display the front edition button for a specific right 385 * Checks : 386 * * Rendering context == front 387 * * Edition mode 388 * * Front_Edition_Access_Right 389 * * RightId available 390 * @param rightId right to check (can be null) 391 * @param inputPageId page to check 392 * @return true if all is OK, false if at least one is false 393 * @deprecated Use the version with three arguments 394 */ 395 @Deprecated 396 public static boolean hasFrontEditionRight(String rightId, String inputPageId) 397 { 398 return hasFrontEditionRight(rightId, inputPageId, true); 399 } 400 /** 401 * Check if we can display the front edition button for a specific right 402 * Checks : 403 * * Rendering context == front 404 * * Edition mode 405 * * Front_Edition_Access_Right 406 * * RightId available 407 * @param rightId right to check (can be null) 408 * @param objectId page/content to check 409 * @param editionModeOnly Check if the user is in edition mode 410 * @return true if all is OK, false if at least one is false 411 */ 412 public static boolean hasFrontEditionRight(String rightId, String objectId, boolean editionModeOnly) 413 { 414 String pageId = objectId; 415 if (StringUtils.isEmpty(pageId)) 416 { 417 pageId = AmetysXSLTHelper.pageId(); 418 } 419 420 if (StringUtils.isEmpty(pageId) // No page to check 421 || !RenderingContext.FRONT.toString().equals(AmetysXSLTHelper.renderingContext()) // We are no on front 422 || (editionModeOnly && !AmetysXSLTHelper.isEditionMode()) // Not in edition mode 423 || !hasFrontEditionRight()) // The user has the front edition right 424 { 425 426 return false; 427 } 428 429 430 return StringUtils.isEmpty(rightId) // There is no right to check OR the user has the right 431 || _rightManager.currentUserHasRight(rightId, _ametysObjectResolver.resolveById(pageId)) == RightResult.RIGHT_ALLOW; // Check right on page (If this page does not exists an exception will be thrown... this is fine) 432 } 433 /** 434 * Check if the current user has the Front_Edition_Access_Right right 435 * @return true if right granted 436 */ 437 public static boolean hasFrontEditionRight() 438 { 439 String pageId = AmetysXSLTHelper.pageId(); 440 if (StringUtils.isNotEmpty(pageId)) 441 { 442 Page page = _ametysObjectResolver.resolveById(pageId); 443 return _rightManager.currentUserHasRight(FRONT_EDITION_RIGHT_ID, page) == RightResult.RIGHT_ALLOW; 444 } 445 446 String lang = AmetysXSLTHelper.lang(); 447 String siteName = AmetysXSLTHelper.site(); 448 449 if (StringUtils.isNotEmpty(siteName) && StringUtils.isNoneEmpty(lang)) 450 { 451 Site site = _siteManager.getSite(siteName); 452 Sitemap sitemap = site.getSitemap(lang); 453 return _rightManager.currentUserHasRight(FRONT_EDITION_RIGHT_ID, sitemap) == RightResult.RIGHT_ALLOW; 454 } 455 456 return false; 457 } 458 /** 459 * Check if the current workflow action is available on this content 460 * @param actionId action to check 461 * @param contentId content to check 462 * @param checkEditionMode check also if we are in edition mode 463 * @return true if right is granted 464 */ 465 public static boolean hasWorkflowRight(int actionId, String contentId, boolean checkEditionMode) 466 { 467 List<Integer> actionIds = new ArrayList<>(); 468 actionIds.add(actionId); 469 return hasWorkflowRight(actionIds, contentId, checkEditionMode); 470 } 471 /** 472 * Check if a list of workflow actions are available on this content 473 * @param actionIds list of action ids 474 * @param contentId id of the content to check 475 * @param checkEditionMode check also if we are in edition mode 476 * @return true if all actions are available 477 */ 478 public static boolean hasWorkflowRight(List<Integer> actionIds, String contentId, boolean checkEditionMode) 479 { 480 Content content = _ametysObjectResolver.resolveById(contentId); 481 return hasWorkflowRight(actionIds, content, checkEditionMode); 482 } 483 /** 484 * Check if a list of workflow actions are available on this content 485 * @param actionIds list of action ids 486 * @param content content to check 487 * @param checkEditionMode check also if we are in edition mode 488 * @return true if all actions are available 489 */ 490 public static boolean hasWorkflowRight(List<Integer> actionIds, Content content, boolean checkEditionMode) 491 { 492 if (checkEditionMode) 493 { 494 boolean editionModeOk = AmetysXSLTHelper.isEditionMode(); 495 if (!editionModeOk) 496 { 497 return false; 498 } 499 } 500 boolean result = false; 501 if (content instanceof WorkflowAwareContent) 502 { 503 WorkflowAwareContent wcontent = (WorkflowAwareContent) content; 504 int[] availableActions = _contentWorkflowHelper.getAvailableActions(wcontent); 505 for (int actionId : actionIds) 506 { 507 result = result || ArrayUtils.contains(availableActions, actionId); 508 if (result) 509 { 510 break; 511 } 512 } 513 } 514 return result; 515 } 516 /** 517 * Get a string representing a json map of the contentIds with true/false if they can/can't be modified 518 * @param actionId action to check 519 * @param inputPageId page (can be null) 520 * @param checkEditionMode check also if we are in edition mode 521 * @return {contentId : true/false, ....} 522 */ 523 public static String getContentModifiables(int actionId, String inputPageId, boolean checkEditionMode) 524 { 525 Map<String, Boolean> jsonObject = new HashMap<>(); 526 List<Integer> actionIds = new ArrayList<>(); 527 actionIds.add(actionId); 528 String pageId = inputPageId; 529 if (StringUtils.isEmpty(inputPageId)) 530 { 531 pageId = AmetysXSLTHelper.pageId(); 532 } 533 if (!StringUtils.isEmpty(pageId)) 534 { 535 AmetysObject resolveById = _ametysObjectResolver.resolveById(pageId); 536 if (resolveById instanceof Page) 537 { 538 Page page = (Page) resolveById; 539 List<Content> contents = _pageHelper.getAllContents(page); 540 for (Content content : contents) 541 { 542 jsonObject.put(content.getId(), hasWorkflowRight(actionIds, content, checkEditionMode)); 543 } 544 } 545 } 546 547 return _jsonUtils.convertObjectToJson(jsonObject); 548 } 549 /** 550 * Get the name of a workflow action 551 * @param workflowName workflow name 552 * @param actionId action id in the workflow 553 * @return name of the workflow action 554 */ 555 public static String getWorkflowName(String workflowName, int actionId) 556 { 557 String workflowNameKey = _workflowHelper.getActionName(workflowName, actionId); 558 String translatedName = org.ametys.core.util.AmetysXSLTHelper.translate(workflowNameKey); 559 return translatedName; 560 } 561 /** 562 * Get the status (validated/draft) of all contents in a page 563 * @param pageId id of the page to check 564 * @return "" if not a page, "draft" if all contents are drafts, "validated" if all contents are validated, and "mixed" if there are both 565 */ 566 public String getPageStatus(String pageId) 567 { 568 boolean hasDraft = false; 569 boolean hasValidated = false; 570 AmetysObject resolveById = _ametysObjectResolver.resolveById(pageId); 571 if (resolveById instanceof Page) 572 { 573 Page page = (Page) resolveById; 574 List<Content> contents = _pageHelper.getAllContents(page); 575 for (Content content : contents) 576 { 577 if (isContentLive(content)) 578 { 579 hasValidated = true; 580 } 581 else 582 { 583 hasDraft = true; 584 } 585 } 586 String result = "none"; 587 if (hasDraft && !hasValidated) 588 { 589 result = "draft"; 590 } 591 else if (!hasDraft && hasValidated) 592 { 593 result = "validated"; 594 } 595 else if (hasDraft && hasValidated) 596 { 597 result = "mixed"; 598 } 599 return result; 600 } 601 else 602 { 603 return ""; 604 } 605 } 606 607 /** 608 * Get the workflow step id of a content 609 * @param contentId id of the content 610 * @return the step Id 611 */ 612 public long getContentWorkflowId(String contentId) 613 { 614 AmetysObject resolvedById = _ametysObjectResolver.resolveById(contentId); 615 if (resolvedById instanceof Content) 616 { 617 Content content = (Content) resolvedById; 618 return getContentWorkflowId(content); 619 } 620 else 621 { 622 return 0; 623 } 624 } 625 /** 626 * Get the workflow step id of a content 627 * @param content content 628 * @return the step Id 629 */ 630 public long getContentWorkflowId(Content content) 631 { 632 WorkflowAwareContent wContent = (WorkflowAwareContent) content; 633 return wContent.getCurrentStepId(); 634 } 635 636 /** 637 * check if a content is published ot not 638 * @param contentId id of the content 639 * @return "validated" or "draft", "" if not found 640 */ 641 public String getContentStatus(String contentId) 642 { 643 AmetysObject resolvedById = _ametysObjectResolver.resolveById(contentId); 644 if (resolvedById instanceof Content) 645 { 646 Content content = (Content) resolvedById; 647 return getContentStatus(content); 648 } 649 else 650 { 651 return ""; 652 } 653 } 654 /** 655 * check if a content is published ot not 656 * @param content content 657 * @return "validated" or "draft" 658 */ 659 public String getContentStatus(Content content) 660 { 661 return isContentLive(content) ? "validated" : "draft"; 662 } 663 /** 664 * check if a content is published ot not 665 * @param contentId id of the content 666 * @return true if validated 667 */ 668 public boolean isContentLive(String contentId) 669 { 670 AmetysObject resolvedById = _ametysObjectResolver.resolveById(contentId); 671 if (resolvedById instanceof Content) 672 { 673 Content content = (Content) resolvedById; 674 return isContentLive(content); 675 } 676 else 677 { 678 return false; 679 } 680 } 681 /** 682 * check if a content is published ot not 683 * @param content content 684 * @return true if validated 685 */ 686 public boolean isContentLive(Content content) 687 { 688 return Arrays.asList(((VersionableAmetysObject) content).getLabels()).contains(WebConstants.LIVE_LABEL); 689 } 690 /** 691 * Get the position of this zoneItem in the zone, or -1 if not found 692 * @param zoneItemId zoneitem to search 693 * @param pageId page id 694 * @return zero based position, -1 if not found 695 * @throws UnknownAmetysObjectException If an error occurred 696 * @throws AmetysRepositoryException If an error occurred 697 * @throws RepositoryException If an error occurred 698 */ 699 public long getZoneItemPosition(String zoneItemId, String pageId) throws UnknownAmetysObjectException, AmetysRepositoryException, RepositoryException 700 { 701 ModifiablePage page = _ametysObjectResolver.resolveById(pageId); 702 ZoneItem zoneItem = page instanceof JCRAmetysObject ? (ZoneItem) _ametysObjectResolver.resolveById(zoneItemId, ((JCRAmetysObject) page).getNode().getSession()) : (ZoneItem) _ametysObjectResolver.resolveById(zoneItemId); 703 AmetysObject parent = zoneItem.getParent(); 704 if (parent instanceof DefaultTraversableAmetysObject) 705 { 706 return ((DefaultTraversableAmetysObject) parent).getChildPosition(zoneItem); 707 } 708 return -1; 709 } 710 /** 711 * Return the size of a zone 712 * @param zoneName zone name 713 * @param pageId page Id 714 * @return size of the zone (-1 if not found) 715 */ 716 public long getZoneSize(String zoneName, String pageId) 717 { 718 ModifiablePage page = _ametysObjectResolver.resolveById(pageId); 719 ModifiableZone zone = page.getZone(zoneName); 720 if (zone != null) 721 { 722 return zone.getZoneItems().getSize(); 723 } 724 return -1; 725 } 726}