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.contenttype.MetadataType;
034import org.ametys.cms.search.query.Query;
035import org.ametys.cms.search.query.Query.Operator;
036import org.ametys.cms.search.ui.model.SearchUICriterion;
037import org.ametys.cms.search.ui.model.impl.AbstractCustomSearchUICriterion;
038import org.ametys.core.util.JSONUtils;
039import org.ametys.web.filter.SharedContentsHelper;
040import org.ametys.web.repository.site.Site;
041import org.ametys.web.repository.site.SiteManager;
042
043/**
044 * Custom boolean {@link SearchUICriterion} representing whether to take content
045 * access restrictions ("content privacy") into account.<br>
046 * It's generally used as a hidden search criterion to force the "true" or "false" value.
047 */
048public class ContentPrivacySearchUICriterion extends AbstractCustomSearchUICriterion implements Contextualizable
049{
050    
051    /** The site manager. */
052    protected SiteManager _siteManager;
053    
054    /** The JSON utils. */
055    protected JSONUtils _jsonUtils;
056    
057    /** The context. */
058    protected Context _context;
059    
060    /** The site criterion ID. */
061    protected String _siteCriterionId;
062    
063    @Override
064    public void contextualize(Context context) throws ContextException
065    {
066        _context = context;
067    }
068    
069    @Override
070    public void service(ServiceManager manager) throws ServiceException
071    {
072        super.service(manager);
073        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
074        _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE);
075    }
076    
077    @Override
078    public void configure(Configuration configuration) throws ConfigurationException
079    {
080        super.configure(configuration);
081        
082        _siteCriterionId = configuration.getChild("site-criterion").getValue("site");
083    }
084    
085    @Override
086    public MetadataType getType()
087    {
088        return MetadataType.BOOLEAN;
089    }
090    
091    @Override
092    public boolean isMultiple()
093    {
094        return false;
095    }
096    
097    @Override
098    public boolean isSortable()
099    {
100        // Not destined to be displayed.
101        return false;
102    }
103    
104    @Override
105    public Operator getOperator()
106    {
107        return Operator.EQ;
108    }
109    
110    @Override
111    public String getFieldId()
112    {
113        return getId();
114    }
115    
116    @Override
117    public Query getQuery(Object value, Operator customOperator, Map<String, Object> allValues, String language, Map<String, Object> contextualParameters)
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("property-" + _siteCriterionId + "-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    
177}