Merge branch 'master' into service-template

pull/1159/head
Halil ibrahim Kalkan 7 years ago
commit f6c85f3694

@ -14,8 +14,12 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\Emailing\Templates\*.html" />
<None Remove="Volo\Abp\Emailing\Templates\*.html" />
<EmbeddedResource Include="Volo\Abp\Emailing\Templates\DefaultEmailTemplates\*\*.tpl" />
<None Remove="Volo\Abp\Emailing\Templates\DefaultEmailTemplates\*\*.tpl" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Scriban" Version="2.0.1" />
</ItemGroup>
<ItemGroup>

@ -1,6 +1,8 @@
using Volo.Abp.BackgroundJobs;
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.Emailing.Templates.Virtual;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
@ -16,6 +18,11 @@ namespace Volo.Abp.Emailing
)]
public class AbpEmailingModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
AutoAddDefinitionProviders(context.Services);
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<VirtualFileSystemOptions>(options =>
@ -27,18 +34,42 @@ namespace Volo.Abp.Emailing
{
options.AddJob<BackgroundEmailSendingJob>();
});
}
Configure<EmailTemplateOptions>(options =>
private static void AutoAddDefinitionProviders(IServiceCollection services)
{
var definitionProviders = new List<Type>();
services.OnRegistred(context =>
{
options.Templates
.Add(
new EmailTemplateDefinition(StandardEmailTemplates.DefaultLayout, isLayout: true, layout: null)
.SetVirtualFilePath("/Volo/Abp/Emailing/Templates/DefaultLayout.html")
).Add(
new EmailTemplateDefinition(StandardEmailTemplates.SimpleMessage)
.SetVirtualFilePath("/Volo/Abp/Emailing/Templates/SimpleMessageTemplate.html")
);
if (typeof(IEmailTemplateDefinitionProvider).IsAssignableFrom(context.ImplementationType))
{
definitionProviders.Add(context.ImplementationType);
}
});
services.Configure<EmailTemplateOptions>(options =>
{
options.DefinitionProviders.AddIfNotContains(definitionProviders);
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
using (var scope = context.ServiceProvider.CreateScope())
{
var emailTemplateDefinitionManager =
scope.ServiceProvider.GetRequiredService<IEmailTemplateDefinitionManager>();
foreach (var templateDefinition in emailTemplateDefinitionManager.GetAll())
{
foreach (var contributor in templateDefinition.Contributors)
{
contributor.Initialize(new EmailTemplateInitializationContext(templateDefinition, scope.ServiceProvider));
}
}
}
}
}
}

@ -0,0 +1,16 @@
using Volo.Abp.Emailing.Templates.VirtualFiles;
namespace Volo.Abp.Emailing.Templates
{
public class DefaultEmailTemplateProvider : EmailTemplateDefinitionProvider
{
public override void Define(IEmailTemplateDefinitionContext context)
{
context.Add(new EmailTemplateDefinition(StandardEmailTemplates.DefaultLayout, isLayout: true, layout: null)
.AddTemplateVirtualFiles("/Volo/Abp/Emailing/Templates/DefaultEmailTemplates/Layout"));
context.Add(new EmailTemplateDefinition(StandardEmailTemplates.SimpleMessage)
.AddTemplateVirtualFiles("/Volo/Abp/Emailing/Templates/DefaultEmailTemplates/Message"));
}
}
}

@ -0,0 +1,22 @@
using System.Collections.Generic;
using System.Linq;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateContributorList : List<IEmailTemplateContributor>
{
public string GetOrNull(string cultureName)
{
foreach (var contributor in this.AsQueryable().Reverse())
{
var templateString = contributor.GetOrNull(cultureName);
if (templateString != null)
{
return templateString;
}
}
return null;
}
}
}

@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.Emailing.Templates
@ -16,29 +15,22 @@ namespace Volo.Abp.Emailing.Templates
public Type LocalizationResource { get; set; }
public Dictionary<string, object> Properties { get; }
/// <summary>
/// Gets/sets a key-value on the <see cref="Properties"/>.
/// </summary>
/// <param name="name">Name of the property</param>
/// <returns>
/// Returns the value in the <see cref="Properties"/> dictionary by given <see cref="name"/>.
/// Returns null if given <see cref="name"/> is not present in the <see cref="Properties"/> dictionary.
/// </returns>
public object this[string name]
{
get => Properties.GetOrDefault(name);
set => Properties[name] = value;
}
public EmailTemplateContributorList Contributors { get; }
public string DefaultCultureName { get; }
public bool SingleTemplateFile { get; }
public EmailTemplateDefinition([NotNull]string name, Type localizationResource = null, bool isLayout = false, string layout = DefaultLayoutPlaceHolder)
public EmailTemplateDefinition([NotNull] string name, Type localizationResource = null, bool isLayout = false,
string layout = DefaultLayoutPlaceHolder, string defaultCultureName = null, bool singleTemplateFile = false)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
Properties = new Dictionary<string, object>();
LocalizationResource = localizationResource;
Contributors = new EmailTemplateContributorList();
IsLayout = isLayout;
Layout = layout;
DefaultCultureName = defaultCultureName;
SingleTemplateFile = singleTemplateFile;
}
}
}

@ -0,0 +1,38 @@
using System.Collections.Generic;
using System.Collections.Immutable;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateDefinitionContext : IEmailTemplateDefinitionContext
{
protected Dictionary<string, EmailTemplateDefinition> EmailTemplates { get; }
public EmailTemplateDefinitionContext(Dictionary<string, EmailTemplateDefinition> emailTemplates)
{
EmailTemplates = emailTemplates;
}
public virtual EmailTemplateDefinition GetOrNull(string name)
{
return EmailTemplates.GetOrDefault(name);
}
public virtual IReadOnlyList<EmailTemplateDefinition> GetAll()
{
return EmailTemplates.Values.ToImmutableList();
}
public virtual void Add(params EmailTemplateDefinition[] definitions)
{
if (definitions.IsNullOrEmpty())
{
return;
}
foreach (var definition in definitions)
{
EmailTemplates[definition.Name] = definition;
}
}
}
}

@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateDefinitionManager : IEmailTemplateDefinitionManager, ISingletonDependency
{
protected Lazy<IDictionary<string, EmailTemplateDefinition>> EmailTemplateDefinitions { get; }
protected EmailTemplateOptions Options { get; }
protected IServiceProvider ServiceProvider { get; }
public EmailTemplateDefinitionManager(
IOptions<EmailTemplateOptions> options,
IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Options = options.Value;
EmailTemplateDefinitions =
new Lazy<IDictionary<string, EmailTemplateDefinition>>(CreateEmailTemplateDefinitions, true);
}
public virtual EmailTemplateDefinition Get(string name)
{
Check.NotNull(name, nameof(name));
var template = GetOrNull(name);
if (template == null)
{
throw new AbpException("Undefined template: " + name);
}
return template;
}
public virtual IReadOnlyList<EmailTemplateDefinition> GetAll()
{
return EmailTemplateDefinitions.Value.Values.ToImmutableList();
}
public virtual EmailTemplateDefinition GetOrNull(string name)
{
return EmailTemplateDefinitions.Value.GetOrDefault(name);
}
protected virtual IDictionary<string, EmailTemplateDefinition> CreateEmailTemplateDefinitions()
{
var templates = new Dictionary<string, EmailTemplateDefinition>();
using (var scope = ServiceProvider.CreateScope())
{
var providers = Options
.DefinitionProviders
.Select(p => scope.ServiceProvider.GetRequiredService(p) as IEmailTemplateDefinitionProvider)
.ToList();
foreach (var provider in providers)
{
provider.Define(new EmailTemplateDefinitionContext(templates));
}
}
return templates;
}
}
}

@ -0,0 +1,9 @@
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Emailing.Templates
{
public abstract class EmailTemplateDefinitionProvider : IEmailTemplateDefinitionProvider, ITransientDependency
{
public abstract void Define(IEmailTemplateDefinitionContext context);
}
}

@ -0,0 +1,18 @@
using System;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateInitializationContext
{
public EmailTemplateDefinition EmailTemplateDefinition { get; }
public IServiceProvider ServiceProvider { get; }
public EmailTemplateInitializationContext(EmailTemplateDefinition emailTemplateDefinition,
IServiceProvider serviceProvider)
{
EmailTemplateDefinition = emailTemplateDefinition;
ServiceProvider = serviceProvider;
}
}
}

@ -1,26 +1,18 @@
using System.Collections.Generic;
using Volo.Abp.Emailing.Templates.Virtual;
using Volo.Abp.Collections;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateOptions
{
public List<IEmailTemplateProviderContributor> Providers { get; }
public EmailTemplateDefinitionDictionary Templates { get; }
public string DefaultLayout { get; set; }
public ITypeList<IEmailTemplateDefinitionProvider> DefinitionProviders { get; }
public EmailTemplateOptions()
{
Providers = new List<IEmailTemplateProviderContributor>
{
new VirtualFileEmailTemplateProviderContributor()
};
Templates = new EmailTemplateDefinitionDictionary();
DefaultLayout = StandardEmailTemplates.DefaultLayout;
DefinitionProviders = new TypeList<IEmailTemplateDefinitionProvider>();
}
}
}

@ -1,6 +1,6 @@
using System;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
@ -10,80 +10,105 @@ namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateProvider : IEmailTemplateProvider, ITransientDependency
{
protected IServiceProvider ServiceProvider { get; }
protected IEmailTemplateDefinitionManager EmailTemplateDefinitionManager;
protected ITemplateLocalizer TemplateLocalizer { get; }
protected EmailTemplateOptions Options { get; }
protected IStringLocalizerFactory StringLocalizerFactory;
public EmailTemplateProvider(
IOptions<EmailTemplateOptions> options,
IServiceProvider serviceProvider,
ITemplateLocalizer templateLocalizer)
public EmailTemplateProvider(IEmailTemplateDefinitionManager emailTemplateDefinitionManager,
ITemplateLocalizer templateLocalizer, IStringLocalizerFactory stringLocalizerFactory,
IOptions<EmailTemplateOptions> options)
{
ServiceProvider = serviceProvider;
EmailTemplateDefinitionManager = emailTemplateDefinitionManager;
TemplateLocalizer = templateLocalizer;
StringLocalizerFactory = stringLocalizerFactory;
Options = options.Value;
}
public async Task<EmailTemplate> GetAsync(string name)
public async Task<EmailTemplate> GetAsync(string name, string cultureName)
{
using (var scope = ServiceProvider.CreateScope())
{
return await GetInternalAsync(scope.ServiceProvider, name);
}
return await GetInternalAsync(name, cultureName);
}
protected virtual async Task<EmailTemplate> GetInternalAsync(IServiceProvider serviceProvider, string name)
protected virtual async Task<EmailTemplate> GetInternalAsync(string name, string cultureName)
{
var context = new EmailTemplateProviderContributorContext(name, serviceProvider);
var emailTemplateDefinition = EmailTemplateDefinitionManager.GetOrNull(name);
if (emailTemplateDefinition == null)
{
// TODO: Localized message
throw new AbpException($"email template {name} not definition");
}
foreach (var provider in Options.Providers)
var emailTemplateString = emailTemplateDefinition.Contributors.GetOrNull(cultureName);
if (emailTemplateString == null && emailTemplateDefinition.DefaultCultureName != null)
{
await provider.ProvideAsync(context);
emailTemplateString =
emailTemplateDefinition.Contributors.GetOrNull(emailTemplateDefinition.DefaultCultureName);
if (emailTemplateString != null)
{
cultureName = emailTemplateDefinition.DefaultCultureName;
}
}
if (context.Template == null)
if (emailTemplateString != null)
{
throw new AbpException($"Could not found the template: {name}");
var emailTemplate = new EmailTemplate(emailTemplateString, emailTemplateDefinition);
await SetLayoutAsync(emailTemplateDefinition, emailTemplate, cultureName);
if (emailTemplateDefinition.SingleTemplateFile)
{
await LocalizeAsync(emailTemplateDefinition, emailTemplate, cultureName);
}
return emailTemplate;
}
await SetLayoutAsync(serviceProvider, context);
await LocalizeAsync(serviceProvider, context);
return context.Template;
// TODO: Localized message
throw new AbpException($"{cultureName} template not exist!");
}
protected virtual async Task SetLayoutAsync(IServiceProvider serviceProvider, EmailTemplateProviderContributorContext context)
protected virtual async Task SetLayoutAsync(EmailTemplateDefinition emailTemplateDefinition,
EmailTemplate emailTemplate, string cultureName)
{
var layout = context.Template.Definition.Layout;
if (layout.IsNullOrEmpty())
var layout = emailTemplateDefinition.Layout;
if (layout.IsNullOrWhiteSpace())
{
return;
}
if (layout == EmailTemplateDefinition.DefaultLayoutPlaceHolder)
{
layout = Options.DefaultLayout;
}
var layoutTemplate = await GetInternalAsync(serviceProvider, layout);
context.Template.SetLayout(layoutTemplate);
var layoutTemplate = await GetInternalAsync(layout, cultureName);
emailTemplate.SetLayout(layoutTemplate);
}
protected virtual Task LocalizeAsync(IServiceProvider serviceProvider, EmailTemplateProviderContributorContext context)
protected virtual Task LocalizeAsync(EmailTemplateDefinition emailTemplateDefinition,
EmailTemplate emailTemplate, string cultureName)
{
if (context.Template.Definition.LocalizationResource == null)
if (emailTemplateDefinition.LocalizationResource == null)
{
return Task.CompletedTask;
}
var localizer = serviceProvider
.GetRequiredService<IStringLocalizerFactory>()
.Create(context.Template.Definition.LocalizationResource);
context.Template.SetContent(
TemplateLocalizer.Localize(localizer, context.Template.Content)
);
var localizer = StringLocalizerFactory.Create(emailTemplateDefinition.LocalizationResource);
if (cultureName != null)
{
emailTemplate.SetContent(
TemplateLocalizer.Localize(localizer.WithCulture(new CultureInfo(cultureName)),
emailTemplate.Content)
);
}
else
{
emailTemplate.SetContent(
TemplateLocalizer.Localize(localizer, emailTemplate.Content)
);
}
return Task.CompletedTask;
}

@ -1,20 +0,0 @@
using System;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateProviderContributorContext : IServiceProviderAccessor
{
public string Name { get; }
public IServiceProvider ServiceProvider { get; }
public EmailTemplate Template { get; set; }
public EmailTemplateProviderContributorContext(string name, IServiceProvider serviceProvider)
{
Name = name;
ServiceProvider = serviceProvider;
}
}
}

@ -0,0 +1,9 @@
namespace Volo.Abp.Emailing.Templates
{
public interface IEmailTemplateContributor
{
void Initialize(EmailTemplateInitializationContext context);
string GetOrNull(string cultureName);
}
}

@ -0,0 +1,9 @@
namespace Volo.Abp.Emailing.Templates
{
public interface IEmailTemplateDefinitionContext
{
EmailTemplateDefinition GetOrNull(string name);
void Add(params EmailTemplateDefinition[] definitions);
}
}

@ -0,0 +1,15 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.Emailing.Templates
{
public interface IEmailTemplateDefinitionManager
{
[NotNull]
EmailTemplateDefinition Get([NotNull] string name);
IReadOnlyList<EmailTemplateDefinition> GetAll();
EmailTemplateDefinition GetOrNull(string name);
}
}

@ -0,0 +1,7 @@
namespace Volo.Abp.Emailing.Templates
{
public interface IEmailTemplateDefinitionProvider
{
void Define(IEmailTemplateDefinitionContext context);
}
}

@ -4,6 +4,6 @@ namespace Volo.Abp.Emailing.Templates
{
public interface IEmailTemplateProvider
{
Task<EmailTemplate> GetAsync(string name);
Task<EmailTemplate> GetAsync(string name, string cultureName);
}
}
}

@ -1,9 +0,0 @@
using System.Threading.Tasks;
namespace Volo.Abp.Emailing.Templates
{
public interface IEmailTemplateProviderContributor
{
Task ProvideAsync(EmailTemplateProviderContributorContext contributorContext);
}
}

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.Emailing.Templates
{
public interface ITemplateRender
{
Task<string> RenderAsync(string template, object model = null);
}
}

@ -0,0 +1,15 @@
using System.Threading.Tasks;
using Scriban;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Emailing.Templates
{
public class TemplateRender : ITemplateRender, ITransientDependency
{
public async Task<string> RenderAsync(string template, object model = null)
{
var scribanTemplate = Template.Parse(template);
return await scribanTemplate.RenderAsync(model);
}
}
}

@ -1,16 +0,0 @@
namespace Volo.Abp.Emailing.Templates.Virtual
{
public static class EmailTemplateDefinitionExtensions
{
public static EmailTemplateDefinition SetVirtualFilePath(this EmailTemplateDefinition emailTemplateDefinition, string path)
{
emailTemplateDefinition[VirtualFileEmailTemplateProviderContributor.VirtualFilePathKey] = path;
return emailTemplateDefinition;
}
public static string GetVirtualFilePathOrNull(this EmailTemplateDefinition emailTemplateDefinition)
{
return emailTemplateDefinition[VirtualFileEmailTemplateProviderContributor.VirtualFilePathKey] as string;
}
}
}

@ -1,14 +0,0 @@
using System.Collections.Generic;
namespace Volo.Abp.Emailing.Templates.Virtual
{
public class VirtualFileEmailTemplateOptions
{
public IDictionary<string, string> Templates { get; }
public VirtualFileEmailTemplateOptions()
{
Templates = new Dictionary<string, string>();
}
}
}

@ -1,61 +0,0 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Emailing.Templates.Virtual
{
public class VirtualFileEmailTemplateProviderContributor : IEmailTemplateProviderContributor
{
public const string VirtualFilePathKey = "VirtualFilePath";
public Task ProvideAsync(EmailTemplateProviderContributorContext contributorContext)
{
var templateDefinition = FindTemplateDefinition(contributorContext);
if (templateDefinition == null)
{
return Task.CompletedTask;
}
var fileInfo = FindVirtualFileInfo(contributorContext, templateDefinition);
if (fileInfo == null)
{
return Task.CompletedTask;
}
contributorContext.Template = new EmailTemplate(fileInfo.ReadAsString(), templateDefinition);
return Task.CompletedTask;
}
protected virtual EmailTemplateDefinition FindTemplateDefinition(EmailTemplateProviderContributorContext contributorContext)
{
return contributorContext
.ServiceProvider
.GetRequiredService<IOptions<EmailTemplateOptions>>()
.Value
.Templates
.GetOrDefault(contributorContext.Name);
}
protected virtual IFileInfo FindVirtualFileInfo(EmailTemplateProviderContributorContext contributorContext, EmailTemplateDefinition templateDefinition)
{
var virtualFilePath = templateDefinition?.GetVirtualFilePathOrNull();
if (virtualFilePath == null)
{
return null;
}
var virtualFileProvider = contributorContext.ServiceProvider.GetRequiredService<IVirtualFileProvider>();
var fileInfo = virtualFileProvider.GetFileInfo(virtualFilePath);
if (fileInfo?.Exists != true)
{
return null;
}
return fileInfo;
}
}
}

@ -0,0 +1,19 @@
namespace Volo.Abp.Emailing.Templates.VirtualFiles
{
public static class EmailTemplateDefinitionExtensions
{
public static EmailTemplateDefinition AddTemplateVirtualFile(
this EmailTemplateDefinition emailTemplateDefinition, string path)
{
emailTemplateDefinition.Contributors.Add(new SingleVirtualFileEmailTemplateContributor(path));
return emailTemplateDefinition;
}
public static EmailTemplateDefinition AddTemplateVirtualFiles(
this EmailTemplateDefinition emailTemplateDefinition, string path)
{
emailTemplateDefinition.Contributors.Add(new MultipleVirtualFilesEmailTemplateContributor(path));
return emailTemplateDefinition;
}
}
}

@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Emailing.Templates.VirtualFiles
{
public class MultipleVirtualFilesEmailTemplateContributor : IEmailTemplateContributor
{
private readonly string _virtualPath;
private IVirtualFileProvider _virtualFileProvider;
private Dictionary<string, string> _templateDictionary;
private readonly object _syncObj = new object();
public MultipleVirtualFilesEmailTemplateContributor(string virtualPath)
{
_virtualPath = virtualPath;
}
public void Initialize(EmailTemplateInitializationContext context)
{
_virtualFileProvider = context.ServiceProvider.GetRequiredService<IVirtualFileProvider>();
}
public string GetOrNull(string cultureName)
{
return GetTemplateDictionary().GetOrDefault(cultureName);
}
private Dictionary<string, string> GetTemplateDictionary()
{
var dictionaries = _templateDictionary;
if (dictionaries != null)
{
return dictionaries;
}
lock (_syncObj)
{
dictionaries = _templateDictionary;
if (dictionaries != null)
{
return dictionaries;
}
_templateDictionary = new Dictionary<string, string>();
foreach (var file in _virtualFileProvider.GetDirectoryContents(_virtualPath))
{
if (file.IsDirectory)
{
continue;
}
// TODO: How to normalize file names?
_templateDictionary.Add(file.Name.RemovePostFix(".tpl"), file.ReadAsString());
}
dictionaries = _templateDictionary;
}
return dictionaries;
}
}
}

@ -0,0 +1,34 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Emailing.Templates.VirtualFiles
{
public class SingleVirtualFileEmailTemplateContributor : IEmailTemplateContributor
{
private readonly string _virtualPath;
private IVirtualFileProvider _virtualFileProvider;
public SingleVirtualFileEmailTemplateContributor(string virtualPath)
{
_virtualPath = virtualPath;
}
public void Initialize(EmailTemplateInitializationContext context)
{
_virtualFileProvider = context.ServiceProvider.GetRequiredService<IVirtualFileProvider>();
}
public string GetOrNull(string cultureName)
{
var file = _virtualFileProvider.GetFileInfo(_virtualPath);
if (file == null || !file.Exists || file.IsDirectory)
{
return null;
}
return file.ReadAsString();
}
}
}

@ -11,12 +11,15 @@
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\Emailing\TestTemplates\*.*" />
<None Remove="Volo\Abp\Emailing\TestTemplates\*.*" />
<EmbeddedResource Include="Volo\Abp\Emailing\TestTemplates\*\*.tpl" />
<None Remove="Volo\Abp\Emailing\TestTemplates\*\*.tpl" />
<EmbeddedResource Include="Volo\Abp\Emailing\Localization\*.json" />
<None Remove="Volo\Abp\Emailing\Localization\*.json" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Emailing\Volo.Abp.Emailing.csproj" />
<ProjectReference Include="..\..\src\Volo.Abp.Autofac\Volo.Abp.Autofac.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.0.1" />
</ItemGroup>

@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.Emailing.Templates.Virtual;
using Volo.Abp.Emailing.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
@ -18,12 +17,13 @@ namespace Volo.Abp.Emailing
options.FileSets.AddEmbedded<AbpEmailingTestModule>();
});
Configure<EmailTemplateOptions>(options =>
Configure<AbpLocalizationOptions>(options =>
{
options.Templates["template1"] =
new EmailTemplateDefinition("template1")
.SetVirtualFilePath("/Volo/Abp/Emailing/TestTemplates/template1.html");
options.Resources
.Add<AbpEmailingTestResource>()
.AddVirtualJson("/Volo/Abp/Emailing/Localization");
});
}
}
}
}

@ -0,0 +1,64 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Emailing.Templates;
using Xunit;
namespace Volo.Abp.Emailing
{
public class EmailTemplateRender_Tests : AbpIntegratedTest<AbpEmailingTestModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
private readonly ITemplateRender _templateRender;
public EmailTemplateRender_Tests()
{
_templateRender = GetRequiredService<ITemplateRender>();
}
[Fact]
public async Task RenderAsync()
{
var template = "Hello {{email}} {{ for order in orders }}{{ order.id }}:{{ order.name }},{{ end }}";
var model = new ModelClass
{
Email = "john@abp.io",
Orders = new List<ModelClass.Order>
{
new ModelClass.Order
{
Id = "1",
Name = "iphone"
},
new ModelClass.Order
{
Id = "2",
Name = "ipad"
}
}
};
var result = await _templateRender.RenderAsync(template, model);
result.ShouldBe("Hello john@abp.io 1:iphone,2:ipad,");
}
public class ModelClass
{
public string Email { get; set; }
public List<Order> Orders { get; set; }
public class Order
{
public string Id { get; set; }
public string Name { get; set; }
}
}
}
}

@ -7,6 +7,11 @@ namespace Volo.Abp.Emailing
{
public class EmailTemplateStore_Tests : AbpIntegratedTest<AbpEmailingTestModule>
{
protected override void SetAbpApplicationCreationOptions(AbpApplicationCreationOptions options)
{
options.UseAutofac();
}
private readonly IEmailTemplateProvider _emailTemplateProvider;
public EmailTemplateStore_Tests()
@ -17,8 +22,31 @@ namespace Volo.Abp.Emailing
[Fact]
public async Task Should_Get_Registered_Template()
{
var template = await _emailTemplateProvider.GetAsync("template1");
template.Content.ShouldContain("This is a test template!");
var template = await _emailTemplateProvider.GetAsync("template1", "tr");
template.Content.ShouldContain("Lütfen aşağıdaki bağlantıya tıklayarak e-posta adresinizi onaylayın.");
}
[Fact]
public async Task Should_Get_Default_Culture_Template()
{
var template = await _emailTemplateProvider.GetAsync("template1", "zh-Hans");
template.Content.ShouldContain("Please confirm your email address by clicking the link below.");
}
[Fact]
public async Task Should_Get_Registered_Template_With_Layout()
{
var template = await _emailTemplateProvider.GetAsync("template2", "en");
template.Content.ShouldContain("<body>\r\n " + "Please confirm your email address by clicking the link below.");
}
[Fact]
public async Task Should_Get_Registered_Template_With_Localize()
{
var template = await _emailTemplateProvider.GetAsync("template3", "tr");
template.Content.ShouldContain("Merhaba Abp");
}
}
}

@ -0,0 +1,10 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Volo.Abp.Emailing.Localization
{
public class AbpEmailingTestResource
{
}
}

@ -0,0 +1,6 @@
{
"culture": "en",
"texts": {
"hello": "hello"
}
}

@ -0,0 +1,6 @@
{
"culture": "tr",
"texts": {
"hello": "Merhaba"
}
}

@ -0,0 +1,24 @@
using Volo.Abp.Emailing.Localization;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.Emailing.Templates.VirtualFiles;
namespace Volo.Abp.Emailing
{
public class TestEmailTemplateProvider : EmailTemplateDefinitionProvider
{
public override void Define(IEmailTemplateDefinitionContext context)
{
var template1 = new EmailTemplateDefinition("template1", defaultCultureName: "en", layout: null)
.AddTemplateVirtualFiles("/Volo/Abp/Emailing/TestTemplates/Template1");
context.Add(template1);
var template2 = new EmailTemplateDefinition("template2", layout: StandardEmailTemplates.DefaultLayout)
.AddTemplateVirtualFiles("/Volo/Abp/Emailing/TestTemplates/Template2");
context.Add(template2);
var template3 = new EmailTemplateDefinition("template3", layout: null, singleTemplateFile: true, localizationResource: typeof(AbpEmailingTestResource))
.AddTemplateVirtualFile("/Volo/Abp/Emailing/TestTemplates/Template3/Template.tpl");
context.Add(template3);
}
}
}

@ -0,0 +1,4 @@
Please confirm your email address by clicking the link below.
We may need to send you critical information about our service and it is important that we have an accurate email address.
<a href="#">Confirm email address</a>

@ -0,0 +1,4 @@
Lütfen aşağıdaki bağlantıya tıklayarak e-posta adresinizi onaylayın.
Size hizmetimizle ilgili kritik bilgileri göndermemiz gerekebilir ve doğru bir e-posta adresimizin olması önemlidir.
<a href="#">E-posta adresini onayla</a>

@ -0,0 +1,4 @@
Please confirm your email address by clicking the link below.
We may need to send you critical information about our service and it is important that we have an accurate email address.
<a href="#">Confirm email address</a>

@ -1,9 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
</head>
<body>
This is a test template!
</body>
</html>
Loading…
Cancel
Save