001/*
002 *  Copyright 2015 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.web.search.model.impl;
017
018import java.util.List;
019import java.util.Map;
020import java.util.stream.Collectors;
021
022import org.apache.avalon.framework.configuration.Configuration;
023import org.apache.avalon.framework.configuration.ConfigurationException;
024import org.apache.avalon.framework.context.Context;
025import org.apache.avalon.framework.context.ContextException;
026import org.apache.avalon.framework.context.Contextualizable;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.cocoon.components.ContextHelper;
030import org.apache.cocoon.environment.Request;
031import org.apache.commons.lang3.StringUtils;
032
033import org.ametys.cms.search.model.SearchModelCriterionDefinition;
034import org.ametys.cms.search.model.impl.AbstractStaticSearchModelCriterionDefinition;
035import org.ametys.cms.search.model.impl.ReferencingSearchModelCriterionDefinition;
036import org.ametys.cms.search.query.Query;
037import org.ametys.cms.search.query.Query.Operator;
038import org.ametys.core.util.JSONUtils;
039import org.ametys.runtime.model.type.ModelItemTypeConstants;
040import org.ametys.web.filter.SharedContentsHelper;
041import org.ametys.web.repository.site.Site;
042import org.ametys.web.repository.site.SiteManager;
043
044/**
045 * Custom boolean {@link SearchModelCriterionDefinition} representing whether to take content
046 * access restrictions ("content privacy") into account.<br>
047 * It's generally used as a hidden criterion to force the "true" or "false" value.
048 */
049public class ContentPrivacyCriterionDefinition extends AbstractStaticSearchModelCriterionDefinition<Boolean> implements Contextualizable
050{
051    /** The site manager. */
052    protected SiteManager _siteManager;
053    
054    /** The JSON utils. */
055    protected JSONUtils _jsonUtils;
056    
057    /** The avalon context */
058    protected Context _context;
059    
060    /** The site criterion ID. */
061    protected String _siteCriterionName;
062    
063    @Override
064    public void service(ServiceManager manager) throws ServiceException
065    {
066        super.service(manager);
067        
068        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
069        _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE);
070    }
071    
072    public void contextualize(Context context) throws ContextException
073    {
074        _context = context;
075    }
076    
077    @Override
078    public void configure(Configuration configuration) throws ConfigurationException
079    {
080        super.configure(configuration);
081        setSiteCriterionName(configuration.getChild("site-criterion").getValue("site"));
082    }
083    
084    @Override
085    protected String getTypeId()
086    {
087        return ModelItemTypeConstants.BOOLEAN_TYPE_ID;
088    }
089    
090    @Override
091    public boolean isMultiple()
092    {
093        return false;
094    }
095    
096    @Override
097    public Operator getOperator()
098    {
099        return Operator.EQ;
100    }
101    
102    /**
103     * Set the site criterion name
104     * @param siteCriterionName the site criterion name to set
105     */
106    public void setSiteCriterionName(String siteCriterionName)
107    {
108        _siteCriterionName = siteCriterionName;
109    }
110    
111    @Override
112    public Query getQuery(Object value, Operator customOperator, Map<String, Object> allValues, String language, Map<String, Object> contextualParameters)
113    {
114        if (_getCriterionDefinitionHelper().isQueryValueEmpty(value))
115        {
116            return null;
117        }
118        
119        boolean restrict = (value instanceof Boolean) ? (Boolean) value : Boolean.parseBoolean(value.toString());
120        
121        if (restrict)
122        {
123            Request request = ContextHelper.getRequest(_context);
124            
125            String currentSiteName = (String) request.getAttribute("siteName");
126            if (StringUtils.isBlank(currentSiteName))
127            {
128                currentSiteName = (String) contextualParameters.get("siteName");
129            }
130            
131            // TODO Find a way to reference a value without ID.
132            Object siteParam = allValues.get(ReferencingSearchModelCriterionDefinition.CRITERION_DEFINITION_PREFIX + _siteCriterionName + "-eq");
133            if (siteParam != null)
134            {
135                Map<String, Object> siteValueMap = _jsonUtils.convertJsonToMap((String) siteParam);
136                String context = (String) siteValueMap.get("context");
137                if (context == null)
138                {
139                    context = "SITES_LIST";
140                }
141                
142                // CURRENT_SITE: no restriction.
143                // OTHER_SITES / SITES / SITES_LIST
144                
145                // "SITES_LIST" context: get the site list from the value map.
146                Iterable<Site> sites = null;
147                switch (context)
148                {
149                    case "SITES":
150                        // All sites
151                        sites = _siteManager.getSites();
152                        break;
153                    case "OTHER_SITES":
154                        // All sites except the current one.
155                        sites = _siteManager.getSites();
156                        break;
157                    case "SITES_LIST":
158                        // The given site list.
159                        @SuppressWarnings("unchecked")
160                        List<String> siteNames = (List<String>) siteValueMap.get("sites");
161                        sites = siteNames.stream().map(name -> _siteManager.getSite(name)).collect(Collectors.toList());
162                        break;
163                    case "CURRENT_SITE":
164                        // The current site means no restriction: return null.
165                    default:
166                        return null;
167                }
168                
169                Site currentSite = _siteManager.getSite(currentSiteName);
170                return SharedContentsHelper.getContentAccessQuery(currentSite, sites);
171            }
172        }
173        
174        return null;
175    }
176}