001/*
002 *  Copyright 2022 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.forms.helper;
017
018import java.util.HashMap;
019import java.util.List;
020import java.util.Map;
021import java.util.Objects;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027import org.apache.commons.lang.StringUtils;
028
029import org.ametys.core.right.RightManager;
030import org.ametys.core.ui.Callable;
031import org.ametys.core.user.User;
032import org.ametys.core.user.UserManager;
033import org.ametys.plugins.forms.dao.FormDAO;
034import org.ametys.plugins.forms.repository.Form;
035import org.ametys.plugins.repository.AmetysObjectResolver;
036import org.ametys.runtime.plugin.component.AbstractLogEnabled;
037import org.ametys.web.repository.page.Page;
038
039/**
040 * The helper to schedule opening of form
041 */
042public class FormInvitationsHelper extends AbstractLogEnabled implements Serviceable, Component
043{
044    /** Avalon ROLE. */
045    public static final String ROLE = FormInvitationsHelper.class.getName();
046    
047    /** Ametys object resolver. */
048    protected AmetysObjectResolver _resolver;
049    
050    /** The users manager */
051    protected UserManager _userManager;
052    
053    /** The right manager */
054    protected RightManager _rightManager;
055    
056    /** The limited entries helper */
057    protected LimitedEntriesHelper _limitedEntriesHelper;
058    
059    /** The form DAO */
060    protected FormDAO _formDAO;
061    
062    /** The form mail helper */
063    protected FormMailHelper _formMailHelper;
064    
065    public void service(ServiceManager manager) throws ServiceException
066    {
067        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
068        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
069        _rightManager = (RightManager) manager.lookup(RightManager.ROLE);
070        _limitedEntriesHelper = (LimitedEntriesHelper) manager.lookup(LimitedEntriesHelper.ROLE);
071        _formDAO = (FormDAO) manager.lookup(FormDAO.ROLE);
072        _formMailHelper = (FormMailHelper) manager.lookup(FormMailHelper.ROLE);
073    }
074    
075    /**
076     * Sends invitations emails.
077     * @param formId The id of the form.
078     * @param message The message content.
079     * @param siteName The site name.
080     * @param language the language
081     * @return An empty map
082     */
083    @Callable
084    public Map<String, Object> sendInvitations (String formId, String message, String siteName, String language)
085    {
086        Form form = _resolver.resolveById(formId);
087        _formDAO.checkHandleFormRight(form);
088        
089        List<Page> pages = _getFormPages(formId, siteName);
090        if (pages.isEmpty())
091        {
092            throw new IllegalAccessError("Can't send invitations for form id '" + formId + "' because it is not published.");
093        }
094        
095        _formMailHelper.sendInvitationMails(form, _getUsersToInvite(form), message);
096        return new HashMap<>();
097    }
098
099    private List<Page> _getFormPages(String formId, String siteName)
100    {
101        List<Page> pages = _formDAO.getFormPage(formId, siteName)
102            .stream()
103            .filter(Page.class::isInstance)
104            .map(Page.class::cast)
105            .toList();
106        return pages;
107    }
108    
109    /**
110     * Get users to invite to the form (user with mail and who are not answered yet to the form)
111     * @param form the form
112     * @return the users to invite
113     */
114    protected List<User> _getUsersToInvite(Form form)
115    {
116        // Can invite users if the form is on anonymous read access
117        if (_rightManager.hasAnonymousReadAccess(form))
118        {
119            return List.of();
120        }
121        
122        return _rightManager.getReadAccessAllowedUsers(form).resolveAllowedUsers(true)
123                    .stream()
124                    .filter(id -> !_limitedEntriesHelper.hasUserAlreadyAnswer(form, id, null)) // User who are not answered yet
125                    .map(id -> _userManager.getUser(id)) // Get user object
126                    .filter(Objects::nonNull) // User not null
127                    .filter(u -> StringUtils.isNotEmpty(u.getEmail())) // User with a mail
128                    .toList();
129    }
130    
131    /**
132     * Get users to invite to the form (user with mail and who are not answered yet to the form)
133     * @param formId The id of the form.
134     * @return The number of users to invite
135     */
136    @Callable
137    public int getNbOfUsersToInvite(String formId)
138    {
139        Form form = _resolver.resolveById(formId);
140        _formDAO.checkHandleFormRight(form);
141        
142        return _getUsersToInvite(form).size();
143    }
144}