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)) || !checkRights)
111                {
112                    contentTypes.add(getContentTypeProperties(cType));
113                }
114                else
115                {
116                    noRightContentTypes.add(id);
117                }
118            }
119            else
120            {
121                unknownContentTypes.add(id);
122            }
123        }
124        
125        result.put("contentTypes", contentTypes);
126        result.put("noRightContentTypes", noRightContentTypes);
127        result.put("unknownContentTypes", unknownContentTypes);
128        result.put("privateContentTypes", noRightContentTypes);
129        
130        request.setAttribute(JSonReader.OBJECT_TO_READ, result);
131        
132        return EMPTY_MAP;
133    }
134    
135    /**
136     * Get the content type properties
137     * @param contentType The content type
138     * @return The content type properties
139     */
140    protected Map<String, Object> getContentTypeProperties (ContentType contentType)
141    {
142        Map<String, Object> infos = new HashMap<>();
143        
144        infos.put("id", contentType.getId());
145        infos.put("label", contentType.getLabel());
146        infos.put("description", contentType.getDescription());
147        infos.put("defaultTitle", contentType.getDefaultTitle());
148        infos.put("iconGlyph", contentType.getIconGlyph());
149        infos.put("iconDecorator", contentType.getIconDecorator());
150        infos.put("iconSmall", contentType.getSmallIcon());
151        infos.put("iconMedium", contentType.getMediumIcon());
152        infos.put("iconLarge", contentType.getLargeIcon());
153        
154        return infos;
155    }
156    
157    /**
158     * Test if the current user has the right needed by the content type to create a content.
159     * @param contentType The content type
160     * @return true if the user has the right needed, false otherwise.
161     */
162    protected boolean _hasRight(ContentType contentType)
163    {
164        boolean hasRight = false;
165        
166        String right = contentType.getRight();
167        
168        if (right == null)
169        {
170            hasRight = true;
171        }
172        else
173        {
174            UserIdentity user = _userProvider.getUser();
175            hasRight = _rightManager.hasRight(user, right, "/cms") == RightResult.RIGHT_ALLOW || _rightManager.hasRight(user, right, _rootContentHelper.getRootContent()) == RightResult.RIGHT_ALLOW;
176        }
177        
178        return hasRight;
179    }
180    
181    private void _addIfNotPresent(Collection<String> collection, String value)
182    {
183        if (!collection.contains(value))
184        {
185            collection.add(value);
186        }
187    }
188}