001/*
002 *  Copyright 2026 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.odfweb.service.search;
017
018import org.apache.avalon.framework.service.ServiceException;
019import org.apache.avalon.framework.service.ServiceManager;
020import org.apache.avalon.framework.service.Serviceable;
021
022import org.ametys.cms.search.query.JoinQuery;
023import org.ametys.cms.search.query.Query;
024import org.ametys.cms.search.solr.SearcherFactory.Searcher;
025import org.ametys.plugins.odfweb.restrictions.OdfProgramRestriction;
026import org.ametys.plugins.odfweb.restrictions.OdfProgramRestrictionManager;
027import org.ametys.web.frontoffice.search.instance.SearchServiceInstance;
028import org.ametys.web.frontoffice.search.metamodel.Returnable;
029import org.ametys.web.frontoffice.search.requesttime.AbstractSearchComponent;
030import org.ametys.web.frontoffice.search.requesttime.SearchComponent;
031import org.ametys.web.frontoffice.search.requesttime.SearchComponentArguments;
032
033/**
034 * This {@link SearchComponent} add a query to take into account the ODF restrictions on the current site
035 */
036public class ProgramRestrictionSearchComponent extends AbstractSearchComponent implements Serviceable
037{
038    private OdfProgramRestrictionManager _odfRestrictionManager;
039    
040    public void service(ServiceManager manager) throws ServiceException
041    {
042        _odfRestrictionManager = (OdfProgramRestrictionManager) manager.lookup(OdfProgramRestrictionManager.ROLE);
043    }
044    
045    public boolean supports(SearchComponentArguments args)
046    {
047        SearchServiceInstance serviceInstance = args.serviceInstance();
048        return _isProgramSearch(serviceInstance) || _isCourseSearch(serviceInstance);
049    }
050    
051    private boolean _isProgramSearch(SearchServiceInstance serviceInstance)
052    {
053        return serviceInstance.getReturnables()
054                .stream()
055                .map(Returnable::getId)
056                .anyMatch(r -> ProgramReturnable.ROLE.equals(r));
057    }
058
059    private boolean _isCourseSearch(SearchServiceInstance serviceInstance)
060    {
061        return serviceInstance.getReturnables()
062                .stream()
063                .map(Returnable::getId)
064                .anyMatch(r -> CourseReturnable.ROLE.equals(r));
065    }
066    
067    public int getPriority()
068    {
069        return SEARCH_PRIORITY - 10000;
070    }
071    
072    public void execute(SearchComponentArguments args) throws Exception
073    {
074        String siteName = args.currentPage().getSiteName();
075        
076        OdfProgramRestriction restriction = _odfRestrictionManager.getRestriction(siteName);
077        
078        if (restriction != null)
079        {
080            Query query = restriction.getQuery();
081            if (query != null)
082            {
083                Searcher searcher = args.searcher();
084                
085                if (_isProgramSearch(args.serviceInstance()))
086                {
087                    searcher.addFilterQuery(query);
088                }
089                else
090                {
091                    // Course search: add a join query on parent programs
092                    searcher.addFilterQuery(new JoinQuery(query, "parentPrograms"));
093                }
094            }
095        }
096    }
097}