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