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.workflow; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024 025import javax.jcr.RepositoryException; 026 027import org.apache.avalon.framework.context.Context; 028import org.apache.avalon.framework.context.ContextException; 029import org.apache.avalon.framework.context.Contextualizable; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032import org.apache.cocoon.components.ContextHelper; 033import org.apache.cocoon.environment.Request; 034 035import org.ametys.cms.workflow.AbstractContentWorkflowComponent; 036import org.ametys.plugins.newsletter.NewsletterDAO; 037import org.ametys.plugins.newsletter.category.Category; 038import org.ametys.plugins.newsletter.category.CategoryProvider; 039import org.ametys.plugins.newsletter.category.CategoryProviderExtensionPoint; 040import org.ametys.plugins.newsletter.daos.Subscriber; 041import org.ametys.plugins.newsletter.daos.SubscribersDAO; 042import org.ametys.plugins.workflow.EnhancedFunction; 043import org.ametys.runtime.i18n.I18nizableText; 044import org.ametys.web.repository.content.jcr.DefaultWebContent; 045import org.ametys.web.repository.site.Site; 046 047import com.opensymphony.module.propertyset.PropertySet; 048import com.opensymphony.workflow.WorkflowException; 049 050/** 051 * OSWorkflow function for creating a content. 052 */ 053public class SendNewsletterFunction extends AbstractContentWorkflowComponent implements EnhancedFunction, Contextualizable 054{ 055 private SubscribersDAO _subscribersDAO; 056 private CategoryProviderExtensionPoint _categoryProviderEP; 057 058 private Context _context; 059 private NewsletterDAO _newsletterDAO; 060 061 @Override 062 public void service(ServiceManager manager) throws ServiceException 063 { 064 super.service(manager); 065 _subscribersDAO = (SubscribersDAO) manager.lookup(SubscribersDAO.ROLE); 066 _categoryProviderEP = (CategoryProviderExtensionPoint) manager.lookup(CategoryProviderExtensionPoint.ROLE); 067 _newsletterDAO = (NewsletterDAO) manager.lookup(NewsletterDAO.ROLE); 068 } 069 070 public void contextualize(Context context) throws ContextException 071 { 072 _context = context; 073 } 074 075 @Override 076 public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException 077 { 078 Request request = _getRequest(); 079 if (request.getParameter("send") == null && request.getAttribute("send") == null) 080 { 081 // Do not send the newsletter 082 return; 083 } 084 085 DefaultWebContent content = (DefaultWebContent) getContent(transientVars); 086 try 087 { 088 // Subscribers 089 String categoryID = content.getInternalDataHolder().getValue("category"); 090 String siteName = content.getSiteName(); 091 Site site = content.getSite(); 092 093 boolean descending = site.getValue("newsletter-subscription-descending", false, false); 094 boolean ascending = site.getValue("newsletter-subscription-ascending", false, false); 095 096 List<Subscriber> subscribers = _subscribersDAO.getSubscribers(content.getSiteName(), content.getInternalDataHolder().getValue("category")); 097 if (descending) 098 { 099 subscribers.addAll(_getSubscribersOfParentCategories(categoryID, siteName)); 100 } 101 if (ascending) 102 { 103 subscribers.addAll(_getSubscribersOfChildCategories(categoryID, siteName)); 104 } 105 106 Map<String, String> recipients = new HashMap<>(); 107 for (Subscriber subcriber : subscribers) 108 { 109 recipients.put(subcriber.getEmail(), subcriber.getToken()); 110 } 111 112 _newsletterDAO.sendNewsletter(content, recipients); 113 114 content.getInternalDataHolder().setValue("sent", true); 115 try 116 { 117 _newsletterDAO.removeTestNewsletter(content, site); 118 } 119 catch (RepositoryException e) 120 { 121 _logger.warn("Unable to remove the temporary test newsletter.", e); 122 } 123 content.saveChanges(); 124 125 // Send a google analytics event for every newsletter e-mail sent. 126 SendWebAnalyticsEventsEngine sendGaEngine = new SendWebAnalyticsEventsEngine(); 127 sendGaEngine.initialize(_manager, _context); 128 sendGaEngine.parametrize(siteName, content, _newsletterDAO.getCategory(categoryID), recipients.size()); 129 130 new Thread(sendGaEngine).start(); 131 } 132 catch (IOException e) 133 { 134 throw new WorkflowException("Unable to send mails !", e); 135 } 136 catch (ContextException e) 137 { 138 _logger.warn("Context exception when initializing an engine.", e); 139 } 140 catch (ServiceException e) 141 { 142 _logger.warn("Service exception when initializing an engine.", e); 143 } 144 145 } 146 147 /** 148 * Get the subscribers of parent categories 149 * @param categoryID The category id 150 * @param siteName The site name 151 * @return the subscribers of parent categories 152 */ 153 protected List<Subscriber> _getSubscribersOfParentCategories (String categoryID, String siteName) 154 { 155 List<Subscriber> subscribers = new ArrayList<>(); 156 157 Category category = _newsletterDAO.getCategory(categoryID); 158 Category parentCategory = _newsletterDAO.getCategory(category.getParentId()); 159 while (parentCategory != null) 160 { 161 subscribers.addAll(_subscribersDAO.getSubscribers(siteName, parentCategory.getId())); 162 parentCategory = _newsletterDAO.getCategory(parentCategory.getParentId()); 163 } 164 165 return subscribers; 166 } 167 168 /** 169 * Get the subscribers of child categories 170 * @param categoryID The category id 171 * @param siteName The site name 172 * @return The subscribers of child categories 173 */ 174 protected List<Subscriber> _getSubscribersOfChildCategories (String categoryID, String siteName) 175 { 176 List<Subscriber> subscribers = new ArrayList<>(); 177 178 CategoryProvider provider = _getProvider(categoryID); 179 180 List<Category> children = provider.getCategories(categoryID); 181 for (Category child : children) 182 { 183 subscribers.addAll(_subscribersDAO.getSubscribers(siteName, child.getId())); 184 subscribers.addAll(_getSubscribersOfChildCategories (child.getId(), siteName)); 185 } 186 187 return subscribers; 188 } 189 190 /** 191 * Retrieve the request from which this component is called. 192 * @return the request 193 */ 194 protected Request _getRequest() 195 { 196 return ContextHelper.getRequest(_context); 197 } 198 199 /** 200 * Get the category provider 201 * @param categoryID The category id 202 * @return The category 203 */ 204 protected CategoryProvider _getProvider (String categoryID) 205 { 206 Set<String> ids = _categoryProviderEP.getExtensionsIds(); 207 for (String id : ids) 208 { 209 CategoryProvider provider = _categoryProviderEP.getExtension(id); 210 if (provider.hasCategory(categoryID)) 211 { 212 return provider; 213 } 214 } 215 216 return null; 217 } 218 219 @Override 220 public FunctionType getFunctionExecType() 221 { 222 return FunctionType.POST; 223 } 224 225 @Override 226 public I18nizableText getLabel() 227 { 228 return new I18nizableText("plugin.newsletter", "PLUGINS_NEWSLETTER_SEND_NEWSLETTER_FUNCTION_LABEL"); 229 } 230}