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.HashMap; 019import java.util.List; 020import java.util.Map; 021 022import javax.jcr.RepositoryException; 023 024import org.apache.avalon.framework.component.Component; 025import org.apache.avalon.framework.context.Context; 026import org.apache.avalon.framework.context.ContextException; 027import org.apache.avalon.framework.context.Contextualizable; 028import org.apache.avalon.framework.logger.AbstractLogEnabled; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.avalon.framework.service.Serviceable; 032import org.apache.cocoon.components.ContextHelper; 033import org.apache.cocoon.environment.Request; 034 035import org.ametys.core.ui.Callable; 036import org.ametys.plugins.repository.AmetysObject; 037import org.ametys.plugins.repository.AmetysObjectResolver; 038import org.ametys.plugins.repository.AmetysRepositoryException; 039import org.ametys.plugins.repository.UnknownAmetysObjectException; 040import org.ametys.plugins.repository.jcr.DefaultTraversableAmetysObject; 041import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 042import org.ametys.web.repository.page.Page; 043import org.ametys.web.repository.page.ZoneDAO; 044import org.ametys.web.repository.page.ZoneItem; 045 046/** 047 * Various helpers for front-edition plugin 048 */ 049public class FrontEditionHelper extends AbstractLogEnabled implements Serviceable, Component, Contextualizable 050{ 051 /** Avalon Role */ 052 public static final String ROLE = FrontEditionHelper.class.getName(); 053 054 /** The Ametys object resolver */ 055 private AmetysObjectResolver _ametysObjectResolver; 056 private ZoneDAO _zoneDAO; 057 /** Context */ 058 private Context _context; 059 060 public void service(ServiceManager manager) throws ServiceException 061 { 062 _ametysObjectResolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 063 _zoneDAO = (ZoneDAO) manager.lookup(ZoneDAO.ROLE); 064 } 065 066 public void contextualize(Context context) throws ContextException 067 { 068 _context = context; 069 } 070 071 /** 072 * Get the first available parent for the current page, in the live workspace 073 * @param pageId id of the page that need to be checked 074 * @return path of the parent (can be this page if available in live) 075 */ 076 @Callable 077 public String firstAvailableParentInLivePath(String pageId) 078 { 079 AmetysObject resolveById = _ametysObjectResolver.resolveById(pageId); 080 if (resolveById instanceof Page) 081 { 082 Page page = (Page) resolveById; 083 return firstAvailableParentInLivePath(page); 084 } 085 else 086 { 087 return ""; 088 } 089 } 090 /** 091 * Get the first available parent for the requested page, in the live version 092 * @param page page to check 093 * @return path of the parent (can be this page if available in live) 094 */ 095 public String firstAvailableParentInLivePath(Page page) 096 { 097 Request request = ContextHelper.getRequest(_context); 098 if (page == null) 099 { 100 return ""; 101 } 102 AmetysObject available = page; 103 Page availablePage = null; 104 boolean found = false; 105 String forcedWorkspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 106 try 107 { 108 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, "live"); 109 110 while (!found) 111 { 112 try 113 { 114 AmetysObject resolveById = _ametysObjectResolver.resolveById(available.getId()); 115 if (resolveById != null) 116 { 117 found = true; 118 } 119 else 120 { 121 available = available.getParent(); 122 } 123 } 124 catch (UnknownAmetysObjectException e) 125 { 126 available = available.getParent(); 127 } 128 } 129 130 if (available instanceof Page) 131 { 132 availablePage = (Page) available; 133 } 134 } 135 finally 136 { 137 //reset workspace 138 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, forcedWorkspace); 139 } 140 return availablePage == null ? "" : availablePage.getPathInSitemap(); 141 } 142 143 /** 144 * Get the name of a workflow action by it's id 145 * @param contentId id of the content to check if action is available 146 * @param workflowName name of the workflow checked 147 * @param actionIds actions where the name needs to be retreived 148 * @return workwflow action name 149 */ 150 @Callable 151 public Map<Integer, String> getWorkflowActionName(String contentId, String workflowName, List<Integer> actionIds) 152 { 153 Map<Integer, String> result = new HashMap<>(); 154 for (Integer actionId : actionIds) 155 { 156 boolean hasWorkflowRight = AmetysFrontEditionHelper.hasWorkflowRight(actionId, contentId, false); 157 if (hasWorkflowRight) 158 { 159 String translatedName = AmetysFrontEditionHelper.getWorkflowName(workflowName, actionId); 160 result.put(actionId, translatedName); 161 } 162 } 163 return result; 164 } 165 /** 166 * Check if the action requested is available 167 * @param actionId Action Id 168 * @param contentIds List of Content Id 169 * @param checkEditionMode Check if we are in edition mode or not 170 * @return true if action available 171 */ 172 @Callable 173 public Map<String, Boolean> hasWorkflowRight(int actionId, List<String> contentIds, boolean checkEditionMode) 174 { 175 Map<String, Boolean> result = new HashMap<>(); 176 for (String contentId : contentIds) 177 { 178 boolean hasWorkflowRight = AmetysFrontEditionHelper.hasWorkflowRight(actionId, contentId, checkEditionMode); 179 result.put(contentId, hasWorkflowRight); 180 } 181 182 return result; 183 } 184 185 /** 186 * Move a zone item of a page before/after another zone item of the same page 187 * @param zoneItemId zone item to move 188 * @param zoneName name of the zone 189 * @param pageId page Id 190 * @param offset how many item back/forward to move ? (negative for up, positive to down) 191 * @return true if success 192 * @throws UnknownAmetysObjectException If an error occurred 193 * @throws AmetysRepositoryException If an error occurred 194 * @throws RepositoryException If an error occurred 195 */ 196 @Callable 197 public boolean moveZoneItemId(String zoneItemId, String zoneName, String pageId, int offset) throws UnknownAmetysObjectException, AmetysRepositoryException, RepositoryException 198 { 199 ZoneItem zoneItem = _ametysObjectResolver.resolveById(zoneItemId); 200 AmetysObject parent = zoneItem.getParent(); 201 if (parent instanceof DefaultTraversableAmetysObject) 202 { 203 DefaultTraversableAmetysObject traversableParent = (DefaultTraversableAmetysObject) parent; 204 long itemPosition = traversableParent.getChildPosition(zoneItem); 205 long targetPosition = itemPosition + offset; 206 ZoneItem targetZoneItem = traversableParent.getChildAt(targetPosition); 207 return _zoneDAO.moveZoneItemTo(zoneItemId, zoneName, offset < 0, targetZoneItem.getId(), pageId); 208 } 209 return false; 210 } 211}