|
using GoogleMaps.LocationServices; |
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using System.Text; |
|
using System.Web; |
|
using Telerik.Sitefinity; |
|
using Telerik.Sitefinity.Configuration; |
|
using Telerik.Sitefinity.DynamicModules; |
|
using Telerik.Sitefinity.DynamicModules.Model; |
|
using Telerik.Sitefinity.GenericContent.Model; |
|
using Telerik.Sitefinity.GeoLocations; |
|
using Telerik.Sitefinity.GeoLocations.Model; |
|
using Telerik.Sitefinity.Localization; |
|
using Telerik.Sitefinity.Model; |
|
using Telerik.Sitefinity.Model.ContentLinks; |
|
using Telerik.Sitefinity.Modules.Forms; |
|
using Telerik.Sitefinity.Modules.Forms.Configuration; |
|
using Telerik.Sitefinity.Modules.Forms.Events; |
|
using Telerik.Sitefinity.Project.Configuration; |
|
using Telerik.Sitefinity.Security; |
|
using Telerik.Sitefinity.Security.Model; |
|
using Telerik.Sitefinity.Services; |
|
using Telerik.Sitefinity.Services.Notifications; |
|
using Telerik.Sitefinity.Utilities.TypeConverters; |
|
using Telerik.Sitefinity.Web; |
|
|
|
namespace SitefinityWebApp.Custom |
|
{ |
|
public class FancyFormNotifications |
|
{ |
|
public void SendNotification(IFormEntryCreatedEvent eventInfo) |
|
{ |
|
// Pull back all the locations we're going to work with |
|
DynamicModuleManager dynamicModuleManager = DynamicModuleManager.GetManager(); |
|
Type storeType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Stores.Store"); |
|
|
|
// Grab all the live locations |
|
var locations = dynamicModuleManager.GetDataItems(storeType).Where(s => s.Status == ContentLifecycleStatus.Live); |
|
|
|
var zipField = eventInfo.Controls.Where(c => c.Title == "Zip").FirstOrDefault(); |
|
|
|
// Where is our visitor located? |
|
var locationService = new GoogleLocationService(); |
|
var userLocation = locationService.GetLatLongFromAddress(zipField.Value.ToString()); |
|
|
|
// Magic number time. Set the radius to whatever you want...just make sure there's a good chance |
|
// it's big enough to return at least one location :) |
|
var radius = 10000; |
|
|
|
// Filter and sort our locations |
|
var itemFilter = new ItemFilter { ContentType = storeType.ToString() }; |
|
IEnumerable<IGeoLocation> geolocations; |
|
|
|
locations = (dynamicModuleManager as IGeoLocationManager).FilterByGeoLocation(locations, userLocation.Latitude, userLocation.Longitude, radius, out geolocations, itemFilter: itemFilter); |
|
var sortedLocations = (dynamicModuleManager as IGeoLocationManager).SortByDistance(locations, geolocations, userLocation.Latitude, userLocation.Longitude, DistanceSorting.Asc); |
|
|
|
// Get the closest location, geographically speaking, to our visitor |
|
DynamicContent closestStore = sortedLocations.FirstOrDefault(); |
|
|
|
if (closestStore == null) |
|
return; |
|
|
|
// **** |
|
// Time to start building our custom "subscribers" list |
|
// **** |
|
|
|
// These are the IDs of the users who should get the notifications |
|
IEnumerable<Guid> recipientIds = closestStore.GetValue<Guid[]>("NotificationRecipients"); |
|
|
|
UserManager userManager = UserManager.GetManager(); |
|
|
|
// Grab the user accounts that correspond to the users selected in our closest location |
|
IEnumerable<User> recipients = userManager.GetUsers().Where(u => recipientIds.Contains(u.Id)).ToList(); |
|
|
|
// No sense in continuing on if we don't need to (or can't) send the notification |
|
if (recipients.Count() == 0 || !Config.Get<FormsConfig>().Notifications.Enabled) |
|
return; |
|
|
|
// **** |
|
// Here's where we really work out who should be on our subscriber list |
|
// and set up the notification email |
|
// |
|
// Helpful Resources: |
|
// http://www.sitefinity.com/documentation/documentationarticles/developers-guide/deep-dive/notification-service/message-jobs |
|
// http://www.sitefinity.com/documentation/documentationarticles/developers-guide/deep-dive/notification-service/subscription-lists |
|
// **** |
|
|
|
var ns = SystemManager.GetNotificationService(); |
|
var serviceContext = new ServiceContext("ThisApplicationKey", "Forms"); |
|
|
|
Guid subscriptionListId = eventInfo.FormSubscriptionListId; |
|
|
|
// Who's already subscribed? |
|
IEnumerable<ISubscriberRequest> currentSubscribers = ns.GetSubscribers(serviceContext, subscriptionListId, null); |
|
|
|
// Remove them from our "recipients" so we don't send duplicate notifications |
|
var currentSubscribersLookup = currentSubscribers.ToLookup(s => s.Email); |
|
var dynamicSubscribers = recipients.Where(r => (!currentSubscribersLookup.Contains(r.Email))); |
|
|
|
// We still good on recipients? |
|
if (dynamicSubscribers.Count() == 0) |
|
return; |
|
|
|
// This is going to be our impromptu subscriber list |
|
List<ISubscriberRequest> subscribers = new List<ISubscriberRequest>(); |
|
|
|
foreach (User user in dynamicSubscribers) |
|
{ |
|
var subscriber = new SubscriberRequestProxy() |
|
{ |
|
Email = user.Email, |
|
ResolveKey = user.Id.ToString() |
|
}; |
|
|
|
subscribers.Add(subscriber); |
|
} |
|
|
|
// Get all the things! |
|
IDictionary<string, string> notificationTemplateItems = GetNotificationTemplateItems(eventInfo); |
|
|
|
MessageJobRequestProxy messageJobRequestProxy = new MessageJobRequestProxy() |
|
{ |
|
Subscribers = subscribers, |
|
MessageTemplateId = Config.Get<FormsConfig>().Notifications.FormEntrySubmittedNotificationTemplateId, |
|
SenderProfileName = Config.Get<FormsConfig>().Notifications.SenderProfile, |
|
Description = string.Format("Form entry submission email notification for form '{0}'", eventInfo.FormTitle) |
|
}; |
|
|
|
// Make it so, Number One. |
|
ns.SendMessage(serviceContext, messageJobRequestProxy, notificationTemplateItems); |
|
} |
|
|
|
// Borrowed from the Telerik Sitefinity Forms module |
|
// It constructs the items we're going to plug into our notification template |
|
private IDictionary<string, string> GetNotificationTemplateItems(IFormEntryCreatedEvent evt) |
|
{ |
|
Dictionary<string, string> strs = new Dictionary<string, string>(); |
|
string projectName = Config.Get<ProjectConfig>().ProjectName; |
|
strs.Add("Form.ProjectName", projectName); |
|
string domainUrl = UrlPath.GetDomainUrl(); |
|
char[] chrArray = new char[] { '/' }; |
|
strs.Add("Form.Host", string.Concat(domainUrl, "/", projectName.TrimStart(chrArray))); |
|
string empty = string.Empty; |
|
HttpContextBase currentHttpContext = SystemManager.CurrentHttpContext; |
|
if (currentHttpContext != null && currentHttpContext.Request != null) |
|
{ |
|
empty = currentHttpContext.Request.Url.AbsoluteUri; |
|
} |
|
strs.Add("Form.Url", empty); |
|
strs.Add("Form.Title", evt.FormTitle); |
|
strs.Add("Form.IpAddress", evt.IpAddress); |
|
DateTime sitefinityUITime = evt.SubmissionTime.ToSitefinityUITime(); |
|
strs.Add("Form.SubmittedOn", sitefinityUITime.ToString("dd MMMM yyyy")); |
|
string username = evt.Username; |
|
if (string.IsNullOrWhiteSpace(username)) |
|
{ |
|
username = Res.Get<FormsResources>("AnonymousUsername"); |
|
} |
|
strs.Add("Form.Username", username); |
|
if (evt.Controls.Any<IFormEntryEventControl>()) |
|
{ |
|
strs.Add("Form.Fields", GetNotificationControlsHtml(evt.Controls)); |
|
} |
|
return strs; |
|
} |
|
|
|
// Borrowed from the Telerik Sitefinity Forms module |
|
// This could be customized to return whatever HTML you want. |
|
private string GetNotificationControlsHtml(IEnumerable<IFormEntryEventControl> controls) |
|
{ |
|
StringBuilder stringBuilder = new StringBuilder(); |
|
stringBuilder.Append("<table width=\"580px\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" style=\"width: 580px; margin: 0 auto; padding: 0; background-color: #fff; border-left: 1px solid #e4e4e4; border-right: 1px solid #e4e4e4; border-top: 1px solid #e4e4e4;\">"); |
|
foreach (IFormEntryEventControl control in controls) |
|
{ |
|
switch (control.Type) |
|
{ |
|
case FormEntryEventControlType.FieldControl: |
|
case FormEntryEventControlType.FileFieldControl: |
|
{ |
|
stringBuilder.AppendFormat("<tr><th width=\"190px\" bgcolor=\"#f2f2f2\" style=\"width: 190px; padding: 10px 9px; border-bottom: 1px solid #e4e4e4; border-right: 1px solid #e4e4e4; font-family: arial,verdana,sans-serif; line-height: 1.2; font-size: 11px; font-weight: normal; font-style: normal; text-align: left; background-color: #f2f2f2;\">{0}</th>", control.Title ?? ""); |
|
stringBuilder.Append("<td style=\"padding: 10px 9px; border-bottom: 1px solid #e4e4e4; font-family: arial,verdana,sans-serif; line-height: 1.2; font-size: 12px; font-weight: normal; font-style: normal; text-align: left;\">"); |
|
string contentLinksHtml = ""; |
|
if (control.Type != FormEntryEventControlType.FieldControl) |
|
{ |
|
IEnumerable<ContentLink> value = control.Value as IEnumerable<ContentLink>; |
|
if (value != null) |
|
{ |
|
contentLinksHtml = GetContentLinksHtml(value); |
|
} |
|
} |
|
else |
|
{ |
|
contentLinksHtml = control.Value.ToString(); |
|
} |
|
stringBuilder.Append(contentLinksHtml); |
|
stringBuilder.Append("</td></tr>"); |
|
continue; |
|
} |
|
case FormEntryEventControlType.SectionHeader: |
|
{ |
|
stringBuilder.AppendFormat("<tr><th colspan='2' style=\"padding: 12px 9px 12px; border-bottom: 1px solid #e4e4e4; font-family: arial,verdana,sans-serif; line-height: 1.2; font-size: 15px; font-weight: normal; font-style: normal; text-align: left;\">{0}<th/></tr>", control.Title); |
|
continue; |
|
} |
|
case FormEntryEventControlType.InstructionalText: |
|
{ |
|
stringBuilder.AppendFormat("<tr><th colspan='2' style=\"padding: 9px; border-bottom: 1px solid #e4e4e4; font-family: arial,verdana,sans-serif; line-height: 1.2; font-size: 12px; font-weight: normal; font-style: italic; color: #666; text-align: left;\">{0}<th/></tr>", control.Title); |
|
continue; |
|
} |
|
default: |
|
{ |
|
continue; |
|
} |
|
} |
|
} |
|
stringBuilder.Append("</table>"); |
|
return stringBuilder.ToString(); |
|
} |
|
|
|
// Borrowed from the Telerik Sitefinity Forms module |
|
private string GetContentLinksHtml(IEnumerable<ContentLink> contentLinks) |
|
{ |
|
StringBuilder stringBuilder = new StringBuilder(); |
|
foreach (ContentLink contentLink in contentLinks) |
|
{ |
|
if (stringBuilder.Length > 0) |
|
{ |
|
stringBuilder.Append(", "); |
|
} |
|
string childItemAdditionalInfo = contentLink.ChildItemAdditionalInfo; |
|
int num = childItemAdditionalInfo.IndexOf('|'); |
|
if (num == -1) |
|
{ |
|
continue; |
|
} |
|
string str = childItemAdditionalInfo.Substring(0, num); |
|
string str1 = childItemAdditionalInfo.Substring(num + 1); |
|
stringBuilder.AppendFormat("<a href=\"{0}\">{1}</a>", str1, HttpUtility.HtmlEncode(str)); |
|
} |
|
return stringBuilder.ToString(); |
|
} |
|
} |
|
} |