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}