Browse Source

Created initial email template system

pull/7950/head
Halil ibrahim Kalkan 8 years ago
parent
commit
aaaa97f61d
  1. 17
      framework/Volo.Abp.sln
  2. 6
      framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs
  3. 1
      framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj
  4. 5
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs
  5. 12
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs
  6. 32
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs
  7. 9
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs
  8. 22
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs
  9. 20
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContext.cs
  10. 40
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateStore.cs
  11. 9
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs
  12. 9
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateStore.cs
  13. 16
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs
  14. 14
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateOptions.cs
  15. 61
      framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProvider.cs
  16. 2
      framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs
  17. 24
      framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj
  18. 29
      framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/AbpEmailingTestModule.cs
  19. 24
      framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs
  20. 9
      framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/TestTemplates/template1.html

17
framework/Volo.Abp.sln

@ -200,15 +200,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundWorkers"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.Tests", "test\Volo.Abp.BackgroundJobs.Tests\Volo.Abp.BackgroundJobs.Tests.csproj", "{D86548EA-7047-4623-8824-F6285CD254AA}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BackgroundJobs.Abstractions", "src\Volo.Abp.BackgroundJobs.Abstractions\Volo.Abp.BackgroundJobs.Abstractions.csproj", "{EB9C3B4D-FEBD-4691-8F34-AAC2C13F6F2F}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.Abstractions", "src\Volo.Abp.BackgroundJobs.Abstractions\Volo.Abp.BackgroundJobs.Abstractions.csproj", "{EB9C3B4D-FEBD-4691-8F34-AAC2C13F6F2F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BackgroundJobs.HangFire", "src\Volo.Abp.BackgroundJobs.HangFire\Volo.Abp.BackgroundJobs.HangFire.csproj", "{35AC93EF-E383-4F4E-839D-6EE1C62681F1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.HangFire", "src\Volo.Abp.BackgroundJobs.HangFire\Volo.Abp.BackgroundJobs.HangFire.csproj", "{35AC93EF-E383-4F4E-839D-6EE1C62681F1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.HangFire", "src\Volo.Abp.HangFire\Volo.Abp.HangFire.csproj", "{EE01E964-E60E-4C3C-BCF0-AF1A0C0A3DC9}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.HangFire", "src\Volo.Abp.HangFire\Volo.Abp.HangFire.csproj", "{EE01E964-E60E-4C3C-BCF0-AF1A0C0A3DC9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.BackgroundJobs.RabbitMQ", "src\Volo.Abp.BackgroundJobs.RabbitMQ\Volo.Abp.BackgroundJobs.RabbitMQ.csproj", "{DA7A2C04-E8C4-48AA-A37E-27C25BCE280A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.BackgroundJobs.RabbitMQ", "src\Volo.Abp.BackgroundJobs.RabbitMQ\Volo.Abp.BackgroundJobs.RabbitMQ.csproj", "{DA7A2C04-E8C4-48AA-A37E-27C25BCE280A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.RabbitMQ", "src\Volo.Abp.RabbitMQ\Volo.Abp.RabbitMQ.csproj", "{D91DE561-F403-416F-BD0B-DBF0BA1C4447}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Volo.Abp.RabbitMQ", "src\Volo.Abp.RabbitMQ\Volo.Abp.RabbitMQ.csproj", "{D91DE561-F403-416F-BD0B-DBF0BA1C4447}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Volo.Abp.Emailing.Tests", "test\Volo.Abp.Emailing.Tests\Volo.Abp.Emailing.Tests.csproj", "{D3E07597-BB3D-4249-B873-607E2C128C0E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -592,6 +594,10 @@ Global
{D91DE561-F403-416F-BD0B-DBF0BA1C4447}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D91DE561-F403-416F-BD0B-DBF0BA1C4447}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D91DE561-F403-416F-BD0B-DBF0BA1C4447}.Release|Any CPU.Build.0 = Release|Any CPU
{D3E07597-BB3D-4249-B873-607E2C128C0E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3E07597-BB3D-4249-B873-607E2C128C0E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3E07597-BB3D-4249-B873-607E2C128C0E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3E07597-BB3D-4249-B873-607E2C128C0E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -693,6 +699,7 @@ Global
{EE01E964-E60E-4C3C-BCF0-AF1A0C0A3DC9} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{DA7A2C04-E8C4-48AA-A37E-27C25BCE280A} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{D91DE561-F403-416F-BD0B-DBF0BA1C4447} = {5DF0E140-0513-4D0D-BE2E-3D4D85CD70E6}
{D3E07597-BB3D-4249-B873-607E2C128C0E} = {447C8A77-E5F0-4538-8687-7383196D04EA}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BB97ECF4-9A84-433F-A80B-2A3285BDD1D5}

6
framework/src/Volo.Abp.AspNetCore/Microsoft/AspNetCore/Builder/VirtualFileSystemApplicationBuilderExtensions.cs

@ -1,9 +1,5 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.AspNetCore.VirtualFileSystem;
using Volo.Abp.VirtualFileSystem;
namespace Microsoft.AspNetCore.Builder
{

1
framework/src/Volo.Abp.Emailing/Volo.Abp.Emailing.csproj

@ -15,6 +15,7 @@
<ItemGroup>
<ProjectReference Include="..\Volo.Abp.Settings\Volo.Abp.Settings.csproj" />
<ProjectReference Include="..\Volo.Abp.VirtualFileSystem\Volo.Abp.VirtualFileSystem.csproj" />
</ItemGroup>
</Project>

5
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/AbpEmailingModule.cs

@ -1,9 +1,14 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Emailing
{
[DependsOn(
typeof(AbpSettingsModule),
typeof(AbpVirtualFileSystemModule)
)]
public class AbpEmailingModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)

12
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplate.cs

@ -0,0 +1,12 @@
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplate
{
public string Content { get; }
public EmailTemplate(string content)
{
Content = content;
}
}
}

32
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinition.cs

@ -0,0 +1,32 @@
using System.Collections.Generic;
using JetBrains.Annotations;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateDefinition
{
public string Name { get; }
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 EmailTemplateDefinition([NotNull]string name)
{
Name = Check.NotNullOrWhiteSpace(name, nameof(name));
Properties = new Dictionary<string, object>();
}
}
}

9
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateDefinitionDictionary.cs

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateDefinitionDictionary : Dictionary<string, EmailTemplateDefinition>
{
}
}

22
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateOptions.cs

@ -0,0 +1,22 @@
using System.Collections.Generic;
using Volo.Abp.Emailing.Templates.Virtual;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateOptions
{
public List<IEmailTemplateProvider> Providers { get; }
public EmailTemplateDefinitionDictionary Templates { get; }
public EmailTemplateOptions()
{
Providers = new List<IEmailTemplateProvider>
{
new VirtualFileEmailTemplateProvider()
};
Templates = new EmailTemplateDefinitionDictionary();
}
}
}

20
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateProviderContext.cs

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

40
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/EmailTemplateStore.cs

@ -0,0 +1,40 @@
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Emailing.Templates
{
public class EmailTemplateStore : IEmailTemplateStore, ITransientDependency
{
protected IServiceProvider ServiceProvider { get; }
protected EmailTemplateOptions Options { get; }
public EmailTemplateStore(IOptions<EmailTemplateOptions> options, IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
Options = options.Value;
}
public async Task<EmailTemplate> GetAsync(string name)
{
using (var scope = ServiceProvider.CreateScope())
{
var context = new EmailTemplateProviderContext(name, scope.ServiceProvider);
foreach (var provider in Options.Providers)
{
await provider.ProvideAsync(context);
}
if (context.Template == null)
{
//TODO: Return a default email template!
throw new NotImplementedException();
}
return context.Template;
}
}
}
}

9
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateProvider.cs

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

9
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/IEmailTemplateStore.cs

@ -0,0 +1,9 @@
using System.Threading.Tasks;
namespace Volo.Abp.Emailing.Templates
{
public interface IEmailTemplateStore
{
Task<EmailTemplate> GetAsync(string name);
}
}

16
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/EmailTemplateDefinitionExtensions.cs

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

14
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateOptions.cs

@ -0,0 +1,14 @@
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>();
}
}
}

61
framework/src/Volo.Abp.Emailing/Volo/Abp/Emailing/Templates/Virtual/VirtualFileEmailTemplateProvider.cs

@ -0,0 +1,61 @@
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 VirtualFileEmailTemplateProvider : IEmailTemplateProvider
{
public const string VirtualFilePathKey = "VirtualFilePath";
public Task ProvideAsync(EmailTemplateProviderContext context)
{
var templateDefinition = FindTemplateDefinition(context);
if (templateDefinition == null)
{
return Task.CompletedTask;
}
var fileInfo = FindVirtualFileInfo(context, templateDefinition);
if (fileInfo == null)
{
return Task.CompletedTask;
}
context.Template = new EmailTemplate(fileInfo.ReadAsString());
return Task.CompletedTask;
}
protected virtual EmailTemplateDefinition FindTemplateDefinition(EmailTemplateProviderContext context)
{
return context
.ServiceProvider
.GetRequiredService<IOptions<EmailTemplateOptions>>()
.Value
.Templates
.GetOrDefault(context.Name);
}
protected virtual IFileInfo FindVirtualFileInfo(EmailTemplateProviderContext context, EmailTemplateDefinition templateDefinition)
{
var virtualFilePath = templateDefinition?.GetVirtualFilePathOrNull();
if (virtualFilePath == null)
{
return null;
}
var virtualFileProvider = context.ServiceProvider.GetRequiredService<IVirtualFileProvider>();
var fileInfo = virtualFileProvider.GetFileInfo(virtualFilePath);
if (fileInfo?.Exists != true)
{
return null;
}
return fileInfo;
}
}
}

2
framework/src/Volo.Abp.Settings/Volo/Abp/Settings/SettingDefinition.cs

@ -28,7 +28,7 @@
/// <summary>
/// Can be used to store a custom object related to this setting.
/// </summary>
public object CustomData { get; set; }
public object CustomData { get; set; } //TODO: Convert to dictionary!
//TODO: Add Properties dictionary for custom stuff (and remove CustomData)

24
framework/test/Volo.Abp.Emailing.Tests/Volo.Abp.Emailing.Tests.csproj

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>
<LangVersion>latest</LangVersion>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="Volo\Abp\Emailing\TestTemplates\*.*" />
<None Remove="Volo\Abp\Emailing\TestTemplates\*.*" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Volo.Abp.Emailing\Volo.Abp.Emailing.csproj" />
<ProjectReference Include="..\AbpTestBase\AbpTestBase.csproj" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.2" />
</ItemGroup>
</Project>

29
framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/AbpEmailingTestModule.cs

@ -0,0 +1,29 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Emailing.Templates;
using Volo.Abp.Emailing.Templates.Virtual;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace Volo.Abp.Emailing
{
[DependsOn(
typeof(AbpEmailingModule),
typeof(AbpTestBaseModule))]
public class AbpEmailingTestModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.Configure<VirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpEmailingTestModule>();
});
context.Services.Configure<EmailTemplateOptions>(options =>
{
options.Templates["template1"] =
new EmailTemplateDefinition("template1")
.SetVirtualFilePath("/Volo/Abp/Emailing/TestTemplates/template1.html");
});
}
}
}

24
framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/EmailTemplateStore_Tests.cs

@ -0,0 +1,24 @@
using System.Threading.Tasks;
using Shouldly;
using Volo.Abp.Emailing.Templates;
using Xunit;
namespace Volo.Abp.Emailing
{
public class EmailTemplateStore_Tests : AbpIntegratedTest<AbpEmailingTestModule>
{
private readonly IEmailTemplateStore _emailTemplateStore;
public EmailTemplateStore_Tests()
{
_emailTemplateStore = GetRequiredService<IEmailTemplateStore>();
}
[Fact]
public async Task Should_Get_Registered_Template()
{
var template = await _emailTemplateStore.GetAsync("template1");
template.Content.ShouldContain("This is a test template!");
}
}
}

9
framework/test/Volo.Abp.Emailing.Tests/Volo/Abp/Emailing/TestTemplates/template1.html

@ -0,0 +1,9 @@
<!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