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