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.web.repository.content.jcr.DefaultWebContent; 043import org.ametys.web.repository.site.Site; 044 045import com.opensymphony.module.propertyset.PropertySet; 046import com.opensymphony.workflow.FunctionProvider; 047import com.opensymphony.workflow.WorkflowException; 048 049/** 050 * OSWorkflow function for creating a content. 051 */ 052public class SendNewsletterFunction extends AbstractContentWorkflowComponent implements FunctionProvider, Contextualizable 053{ 054 private SubscribersDAO _subscribersDAO; 055 private CategoryProviderExtensionPoint _categoryProviderEP; 056 057 private Context _context; 058 private NewsletterDAO _newsletterDAO; 059 060 @Override 061 public void service(ServiceManager manager) throws ServiceException 062 { 063 super.service(manager); 064 _subscribersDAO = (SubscribersDAO) manager.lookup(SubscribersDAO.ROLE); 065 _categoryProviderEP = (CategoryProviderExtensionPoint) manager.lookup(CategoryProviderExtensionPoint.ROLE); 066 _newsletterDAO = (NewsletterDAO) manager.lookup(NewsletterDAO.ROLE); 067 } 068 069 public void contextualize(Context context) throws ContextException 070 { 071 _context = context; 072 } 073 074 @Override 075 public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException 076 { 077 Request request = _getRequest(); 078 if (request.getParameter("send") == null && request.getAttribute("send") == null) 079 { 080 // Do not send the newsletter 081 return; 082 } 083 084 DefaultWebContent content = (DefaultWebContent) getContent(transientVars); 085 try 086 { 087 // Subscribers 088 // TODO NEWATTRIBUTEAPI_CONTENT: There is no attribute category on newsletter content. See how to deal with this metadata 089 String categoryID = content.getMetadataHolder().getString("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 // TODO NEWATTRIBUTEAPI_CONTENT: There is no attribute category on newsletter content. See how to deal with this metadata 097 List<Subscriber> subscribers = _subscribersDAO.getSubscribers(content.getSiteName(), content.getMetadataHolder().getString("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 // TODO NEWATTRIBUTEAPI_CONTENT: There is no attribute sent on newsletter content. See how to deal with this metadata 116 content.getMetadataHolder().setMetadata("sent", true); 117 try 118 { 119 _newsletterDAO.removeTestNewsletter(content, site); 120 } 121 catch (RepositoryException e) 122 { 123 _logger.warn("Unable to remove the temporary test newsletter.", e); 124 } 125 content.saveChanges(); 126 127 // Send a google analytics event for every newsletter e-mail sent. 128 SendGAEventsEngine sendGaEngine = new SendGAEventsEngine(); 129 sendGaEngine.initialize(_manager, _context); 130 sendGaEngine.parametrize(siteName, content, _newsletterDAO.getCategory(categoryID), recipients.size()); 131 132 new Thread(sendGaEngine).start(); 133 } 134 catch (IOException e) 135 { 136 throw new WorkflowException("Unable to send mails !", e); 137 } 138 catch (ContextException e) 139 { 140 _logger.warn("Context exception when initializing an engine.", e); 141 } 142 catch (ServiceException e) 143 { 144 _logger.warn("Service exception when initializing an engine.", e); 145 } 146 147 } 148 149 /** 150 * Get the subscribers of parent categories 151 * @param categoryID The category id 152 * @param siteName The site name 153 * @return the subscribers of parent categories 154 */ 155 protected List<Subscriber> _getSubscribersOfParentCategories (String categoryID, String siteName) 156 { 157 List<Subscriber> subscribers = new ArrayList<>(); 158 159 Category category = _newsletterDAO.getCategory(categoryID); 160 Category parentCategory = _newsletterDAO.getCategory(category.getParentId()); 161 while (parentCategory != null) 162 { 163 subscribers.addAll(_subscribersDAO.getSubscribers(siteName, parentCategory.getId())); 164 parentCategory = _newsletterDAO.getCategory(parentCategory.getParentId()); 165 } 166 167 return subscribers; 168 } 169 170 /** 171 * Get the subscribers of child categories 172 * @param categoryID The category id 173 * @param siteName The site name 174 * @return The subscribers of child categories 175 */ 176 protected List<Subscriber> _getSubscribersOfChildCategories (String categoryID, String siteName) 177 { 178 List<Subscriber> subscribers = new ArrayList<>(); 179 180 CategoryProvider provider = _getProvider(categoryID); 181 182 List<Category> children = provider.getCategories(categoryID); 183 for (Category child : children) 184 { 185 subscribers.addAll(_subscribersDAO.getSubscribers(siteName, child.getId())); 186 subscribers.addAll(_getSubscribersOfChildCategories (child.getId(), siteName)); 187 } 188 189 return subscribers; 190 } 191 192 /** 193 * Retrieve the request from which this component is called. 194 * @return the request 195 */ 196 protected Request _getRequest() 197 { 198 return ContextHelper.getRequest(_context); 199 } 200 201 /** 202 * Get the category provider 203 * @param categoryID The category id 204 * @return The category 205 */ 206 protected CategoryProvider _getProvider (String categoryID) 207 { 208 Set<String> ids = _categoryProviderEP.getExtensionsIds(); 209 for (String id : ids) 210 { 211 CategoryProvider provider = _categoryProviderEP.getExtension(id); 212 if (provider.hasCategory(categoryID)) 213 { 214 return provider; 215 } 216 } 217 218 return null; 219 } 220 221}