001/*
002 *  Copyright 2013 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.cms.contenttype;
017
018import java.util.ArrayList;
019import java.util.Arrays;
020import java.util.Collection;
021import java.util.HashMap;
022import java.util.List;
023import java.util.Map;
024
025import org.apache.avalon.framework.parameters.Parameters;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.cocoon.acting.ServiceableAction;
029import org.apache.cocoon.environment.ObjectModelHelper;
030import org.apache.cocoon.environment.Redirector;
031import org.apache.cocoon.environment.Request;
032import org.apache.cocoon.environment.SourceResolver;
033
034import org.ametys.cms.content.RootContentHelper;
035import org.ametys.core.cocoon.JSonReader;
036import org.ametys.core.right.RightManager;
037import org.ametys.core.right.RightManager.RightResult;
038import org.ametys.core.user.CurrentUserProvider;
039import org.ametys.core.user.UserIdentity;
040
041/**
042 * Get information on content types.<br>
043 * If "inherited" request parameter is set to true, the sub-types will be also returned.<br>
044 * If "checkRights" request parameter is set to true, only content types allowed for creation will be returned<br>
045 */
046public class GetContentTypesListAction extends ServiceableAction
047{
048    /** Content type extension point. */
049    protected ContentTypeExtensionPoint _contentTypeExtensionPoint;
050    /** The current user provider */
051    protected CurrentUserProvider _userProvider;
052    /** The rights manager */
053    protected RightManager _rightManager;
054    /** Helper for root content */
055    protected RootContentHelper _rootContentHelper;
056    
057    @Override
058    public void service(ServiceManager smanager) throws ServiceException
059    {
060        super.service(smanager);
061        _contentTypeExtensionPoint = (ContentTypeExtensionPoint) smanager.lookup(ContentTypeExtensionPoint.ROLE);
062        _userProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE);
063        _rightManager = (RightManager) smanager.lookup(RightManager.ROLE);
064        _rootContentHelper = (RootContentHelper) smanager.lookup(RootContentHelper.ROLE);
065    }
066    
067    @Override
068    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
069    {
070        Map<String, Object> result = new HashMap<>();
071        
072        Request request = ObjectModelHelper.getRequest(objectModel);
073        List<String> contentTypesIds = Arrays.asList(request.getParameterValues("ids"));
074        
075        boolean inherited = request.getParameter("inherited") != null && "true".equalsIgnoreCase(request.getParameter("inherited"));
076        boolean checkRights = request.getParameter("checkRights") != null && "true".equalsIgnoreCase(request.getParameter("checkRights"));
077        boolean includePrivate = request.getParameter("includePrivate") != null && "true".equalsIgnoreCase(request.getParameter("includePrivate"));
078        
079        List<Map<String, Object>> contentTypes = new ArrayList<>();
080        List<String> unknownContentTypes = new ArrayList<>();
081        List<String> noRightContentTypes = new ArrayList<>();
082        List<String> privateContentTypes = new ArrayList<>();
083        
084        // Collect content types.
085        Collection<String> allContentTypesIds = new ArrayList<>();
086        for (String id : contentTypesIds)
087        {
088            _addIfNotPresent(allContentTypesIds, id);
089            
090            if (inherited)
091            {
092                for (String subTypeId : _contentTypeExtensionPoint.getSubTypes(id))
093                {
094                    _addIfNotPresent(allContentTypesIds, subTypeId);
095                }
096            }
097        }
098        
099        // Resolve and organize content types
100        for (String id : allContentTypesIds)
101        {
102            ContentType cType = _contentTypeExtensionPoint.getExtension(id);
103            
104            if (cType != null && !cType.isAbstract())
105            {
106                if (cType.isPrivate() && !includePrivate)
107                {
108                    privateContentTypes.add(id);
109                }
110                else if (checkRights && _hasRight(cType)
111                         || !checkRights)
112                {
113                    contentTypes.add(getContentTypeProperties(cType));
114                }
115                else
116                {
117                    noRightContentTypes.add(id);
118                }
119            }
120            else
121            {
122                unknownContentTypes.add(id);
123            }
124        }
125        
126        result.put("contentTypes", contentTypes);
127        result.put("noRightContentTypes", noRightContentTypes);
128        result.put("unknownContentTypes", unknownContentTypes);
129        result.put("privateContentTypes", noRightContentTypes);
130        
131        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
132        
133        return EMPTY_MAP;
134    }
135    
136    /**
137     * Get the content type properties
138     * @param contentType The content type
139     * @return The content type properties
140     */
141    protected Map<String, Object> getContentTypeProperties (ContentType contentType)
142    {
143        Map<String, Object> infos = new HashMap<>();
144        
145        infos.put("id", contentType.getId());
146        infos.put("label", contentType.getLabel());
147        infos.put("description", contentType.getDescription());
148        infos.put("defaultTitle", contentType.getDefaultTitle());
149        infos.put("iconGlyph", contentType.getIconGlyph());
150        infos.put("iconDecorator", contentType.getIconDecorator());
151        infos.put("iconSmall", contentType.getSmallIcon());
152        infos.put("iconMedium", contentType.getMediumIcon());
153        infos.put("iconLarge", contentType.getLargeIcon());
154        
155        return infos;
156    }
157    
158    /**
159     * Test if the current user has the right needed by the content type to create a content.
160     * @param contentType The content type
161     * @return true if the user has the right needed, false otherwise.
162     */
163    protected boolean _hasRight(ContentType contentType)
164    {
165        boolean hasRight = false;
166        
167        String right = contentType.getRight();
168        
169        if (right == null)
170        {
171            hasRight = true;
172        }
173        else
174        {
175            UserIdentity user = _userProvider.getUser();
176            hasRight = _rightManager.hasRight(user, right, "/cms") == RightResult.RIGHT_ALLOW || _rightManager.hasRight(user, right, _rootContentHelper.getRootContent()) == RightResult.RIGHT_ALLOW;
177        }
178        
179        return hasRight;
180    }
181    
182    private void _addIfNotPresent(Collection<String> collection, String value)
183    {
184        if (!collection.contains(value))
185        {
186            collection.add(value);
187        }
188    }
189}