001/*
002 *  Copyright 2024 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.pagesubscription.dao;
017
018import java.util.HashMap;
019import java.util.List;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.commons.lang3.tuple.Pair;
026
027import org.ametys.cms.fo.ForceDefaultRepositoryWorkspaceCallableDecorator;
028import org.ametys.core.ui.Callable;
029import org.ametys.core.user.UserIdentity;
030import org.ametys.plugins.pagesubscription.BroadcastChannelHelper.BroadcastChannel;
031import org.ametys.plugins.pagesubscription.FrequencyHelper.Frequency;
032import org.ametys.plugins.pagesubscription.context.PageSubscriptionContext;
033import org.ametys.plugins.pagesubscription.type.PageSubscriptionType;
034import org.ametys.plugins.pagesubscription.type.SubscriptionTypeExtensionPoint;
035import org.ametys.web.repository.page.Page;
036import org.ametys.web.repository.site.Site;
037import org.ametys.web.rights.PageRightAssignmentContext;
038
039/**
040 * DAO for page subscriptions
041 */
042public class PageSubscriptionsDAO extends AbstractSubscriptionsDAO
043{
044    /** The subscription type extension point */
045    protected SubscriptionTypeExtensionPoint _subscriptionTypeEP;
046    
047    /** The page subscription type */
048    protected PageSubscriptionType _pageSubscriptionType;
049    
050    @Override
051    public void service(ServiceManager smanager) throws ServiceException
052    {
053        super.service(smanager);
054        _subscriptionTypeEP = (SubscriptionTypeExtensionPoint) smanager.lookup(SubscriptionTypeExtensionPoint.ROLE);
055        _pageSubscriptionType = (PageSubscriptionType) _subscriptionTypeEP.getExtension(PageSubscriptionType.ID);
056    }
057    
058    /**
059     * Get subscriptions of a page
060     * @param pageId the page id
061     * @return the results
062     */
063    @Callable(rights = Callable.READ_ACCESS, paramIndex = 0, rightContext = PageRightAssignmentContext.ID, decorators = ForceDefaultRepositoryWorkspaceCallableDecorator.DECORATOR_ID)
064    public Map<String, Object> getPageSubscriptions(String pageId)
065    {
066        UserIdentity user = _currentUserProvider.getUser();
067        
068        Page page = _resolver.resolveById(pageId);
069        
070        return _getPageSubscriptions(page, user);
071    }
072    
073    private Map<String, Object> _getPageSubscriptions(Page page, UserIdentity user)
074    {
075        Map<String, Object> results = new HashMap<>();
076        
077        Set<UserIdentity> subscribers = getPageSubscribers(page);
078        
079        results.put("hasSubscribed", subscribers.stream()
080                .filter(u -> u.equals(user))
081                .findAny()
082                .isPresent()
083        );
084        results.put("nbSubscribers", subscribers.size());
085        
086        return results;
087    }
088    
089    /**
090     * Subscribe the current user to a page
091     * @param pageId the page id
092     * @return the results
093     */
094    @Callable(rights = Callable.READ_ACCESS, paramIndex = 0, rightContext = PageRightAssignmentContext.ID, decorators = ForceDefaultRepositoryWorkspaceCallableDecorator.DECORATOR_ID)
095    public Map<String, Object> subscribePage(String pageId)
096    {
097        Map<String, Object> results = new HashMap<>();
098        
099        Page page = _resolver.resolveById(pageId);
100        UserIdentity user = _currentUserProvider.getUser();
101        try
102        {
103            Pair<Frequency, List<BroadcastChannel>> defaultPreference = _getDefaultPreference(page.getSite());
104            PageSubscriptionContext context = PageSubscriptionContext.newInstance()
105                    .withPage(page);
106            _pageSubscriptionType.subscribe(page.getSite(), user, defaultPreference.getLeft(), defaultPreference.getRight(), context);
107            results.put("success", true);
108        }
109        catch (Exception e)
110        {
111            getLogger().error("An error occurred subscribing to the page with id '{}'", pageId, e);
112            results.put("success", false);
113        }
114        
115        results.putAll(_getPageSubscriptions(page, user));
116        return results;
117    }
118    
119    private Pair<Frequency, List<BroadcastChannel>> _getDefaultPreference(Site site)
120    {
121        String frequencyValue = site.getValueOrDefault("page-default-frequency");
122        return "NOMAIL".equals(frequencyValue)
123            ? Pair.of(Frequency.INSTANT, List.of(BroadcastChannel.SITE))
124            : Pair.of(Frequency.valueOf(frequencyValue), List.of(BroadcastChannel.MAIL, BroadcastChannel.SITE));
125    }
126    
127    /**
128     * Unsubscribe the current user to a page
129     * @param pageId the page id
130     * @return the results
131     */
132    @Callable(rights = Callable.READ_ACCESS, paramIndex = 0, rightContext = PageRightAssignmentContext.ID, decorators = ForceDefaultRepositoryWorkspaceCallableDecorator.DECORATOR_ID)
133    public Map<String, Object> unsubscribePage(String pageId)
134    {
135        Map<String, Object> results = new HashMap<>();
136        
137        Page page = _resolver.resolveById(pageId);
138        UserIdentity user = _currentUserProvider.getUser();
139        
140        try
141        {
142            PageSubscriptionContext context = PageSubscriptionContext.newInstance()
143                    .withPage(page);
144            _pageSubscriptionType.unsubscribe(page.getSite(), user, context);
145            results.put("success", true);
146        }
147        catch (Exception e)
148        {
149            getLogger().error("An error occurred unsubscribing to the page with id '{}'", pageId, e);
150            results.put("success", false);
151            return results;
152        }
153        
154        results.putAll(_getPageSubscriptions(page, user));
155        return results;
156    }
157    
158    /**
159     * Get the page subscribers
160     * @param page the page
161     * @return the subscribers
162     */
163    public Set<UserIdentity> getPageSubscribers(Page page)
164    {
165        PageSubscriptionContext context = PageSubscriptionContext.newInstance()
166                .withPage(page);
167        return _pageSubscriptionType.getSubscribers(page.getSite(), null, null, context);
168    }
169    
170}