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.plugins.newsletter.subscribe; 017 018import java.util.Collection; 019import java.util.Collections; 020import java.util.Date; 021import java.util.HashMap; 022import java.util.LinkedHashSet; 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026import java.util.UUID; 027import java.util.regex.Pattern; 028 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.commons.lang.StringUtils; 032 033import org.ametys.core.ui.Callable; 034import org.ametys.core.ui.StaticClientSideElement; 035import org.ametys.core.util.mail.SendMailHelper; 036import org.ametys.plugins.newsletter.category.Category; 037import org.ametys.plugins.newsletter.category.CategoryProviderExtensionPoint; 038import org.ametys.plugins.newsletter.daos.Subscriber; 039import org.ametys.plugins.newsletter.daos.SubscribersDAO; 040 041/** 042 * Client side element for newsletter subscribers 043 */ 044public class SubscribersClientSideElement extends StaticClientSideElement 045{ 046 private static final Pattern __EMAIL_VALIDATOR = SendMailHelper.EMAIL_VALIDATION; 047 048 /** The subscribers DAO. */ 049 protected SubscribersDAO _subscribersDao; 050 051 /** The category provider extension point. */ 052 protected CategoryProviderExtensionPoint _categoryProviderEP; 053 054 @Override 055 public void service(ServiceManager smanager) throws ServiceException 056 { 057 super.service(smanager); 058 _subscribersDao = (SubscribersDAO) smanager.lookup(SubscribersDAO.ROLE); 059 _categoryProviderEP = (CategoryProviderExtensionPoint) smanager.lookup(CategoryProviderExtensionPoint.ROLE); 060 } 061 062 /** 063 * Add a list of subscribers to the newsletter category of the specified site 064 * @param siteName The site name 065 * @param categoryId The category id 066 * @param emailsList The list of emails. Emails can be separeted by a new line or a semicolon. 067 * @return The result, with the count of subscribed or error emails. 068 */ 069 @Callable(rights = "Plugins_Newsletter_Right_HandleSubscribers") 070 public Map<String, Object> addSubscribers (String siteName, String categoryId, String emailsList) 071 { 072 Map<String, Object> result = new HashMap<>(); 073 074 // Test if the category exists. 075 Category category = _categoryProviderEP.getCategory(categoryId); 076 if (category == null) 077 { 078 return Collections.singletonMap("error", "unknown-category"); 079 } 080 081 // Extract the emails from the import file. 082 Collection<String> emails = getEmails(emailsList); 083 084 if (!emails.isEmpty()) 085 { 086 // Insert the emails. 087 insertSubscribers(emails, categoryId, siteName, result); 088 } 089 else 090 { 091 result.put("subscribedCount", "0"); 092 result.put("existingCount", "0"); 093 result.put("errorCount", "0"); 094 } 095 096 result.put("success", "true"); 097 result.put("categoryId", categoryId); 098 099 return result; 100 } 101 102 /** 103 * Extract the emails from the field. 104 * @param emailsList the list of emails 105 * @return a collection of the emails. 106 */ 107 protected Collection<String> getEmails(String emailsList) 108 { 109 Set<String> emails = new LinkedHashSet<>(); 110 111 String[] part = emailsList.split("[;\n]"); 112 for (String line : part) 113 { 114 String email = StringUtils.trimToEmpty(line); 115 if (__EMAIL_VALIDATOR.matcher(email.toLowerCase()).matches() && StringUtils.isNotBlank(email)) 116 { 117 emails.add(email); 118 } 119 else 120 { 121 getLogger().warn("Import subscribers email: '" + email + "' is not a valid email; it will be ignored"); 122 } 123 } 124 125 return emails; 126 } 127 128 129 /** 130 * Insert subscribers 131 * @param emails the list of emails 132 * @param categoryId the id of the newsletter category 133 * @param siteName the name of the sites 134 * @param result the result map 135 */ 136 protected void insertSubscribers(Collection<String> emails, String categoryId, String siteName, Map<String, Object> result) 137 { 138 int subscribedCount = 0; 139 int existingCount = 0; 140 int errorCount = 0; 141 142 for (String email : emails) 143 { 144 if (_subscribersDao.getSubscriber(email, siteName, categoryId) == null) 145 { 146 Subscriber subscriber = new Subscriber(); 147 subscriber.setEmail(email); 148 subscriber.setSiteName(siteName); 149 subscriber.setCategoryId(categoryId); 150 subscriber.setSubscribedAt(new Date()); 151 152 // Generate unique token. 153 String token = UUID.randomUUID().toString(); 154 subscriber.setToken(token); 155 156 _subscribersDao.subscribe(subscriber); 157 158 if (getLogger().isInfoEnabled()) 159 { 160 getLogger().info("The user with email '" + email + "' subscribed to the newsletter with the token " + token); 161 } 162 163 subscribedCount++; 164 } 165 else 166 { 167 existingCount++; 168 } 169 } 170 171 result.put("subscribedCount", Integer.toString(subscribedCount)); 172 result.put("existingCount", Integer.toString(existingCount)); 173 result.put("errorCount", Integer.toString(errorCount)); 174 } 175 176 177 /** 178 * Remove a list of subscribers from the newsletter category of the specified site 179 * @param siteName The site name 180 * @param categoryId The category id 181 * @param emails The list of emails. 182 * @return The error message, or an empty map if everything is ok. 183 */ 184 @Callable(rights = "Plugins_Newsletter_Right_HandleSubscribers") 185 public Map<String, Object> removeSubscribers (String siteName, String categoryId, List<String> emails) 186 { 187 Map<String, Object> result = new HashMap<>(); 188 189 // Test if the category exists. 190 Category category = _categoryProviderEP.getCategory(categoryId); 191 if (category == null) 192 { 193 return Collections.singletonMap("message", "unknown-category"); 194 } 195 196 if (emails.size() > 0) 197 { 198 for (String email : emails) 199 { 200 Subscriber subscriber = _subscribersDao.getSubscriber(email, siteName, categoryId); 201 202 if (subscriber != null) 203 { 204 String token = subscriber.getToken(); 205 206 _subscribersDao.unsubscribe(token); 207 208 if (getLogger().isInfoEnabled()) 209 { 210 getLogger().info("The user with email '" + email + "' unsubscribed from the newsletter in category " + categoryId + " of site " + siteName); 211 } 212 } 213 else 214 { 215 getLogger().error("Impossible to find and remove from the newsletter the subscriber with email '" + email + "' in category " + categoryId + " of site " + siteName); 216 } 217 } 218 } 219 220 return result; 221 } 222}