Merge branch 'v8/8.17' into v8/dev

# Conflicts:
#	src/Umbraco.Web.UI.Client/src/common/services/contenttypehelper.service.js
This commit is contained in:
Sebastiaan Janssen
2021-11-09 11:02:21 +01:00
5 changed files with 418 additions and 43 deletions

View File

@@ -18,5 +18,5 @@ using System.Resources;
[assembly: AssemblyVersion("8.0.0")]
// these are FYI and changed automatically
[assembly: AssemblyFileVersion("8.17.0")]
[assembly: AssemblyInformationalVersion("8.17.0")]
[assembly: AssemblyFileVersion("8.17.1")]
[assembly: AssemblyInformationalVersion("8.17.1")]

View File

@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Moq;
@@ -10,6 +11,7 @@ using Umbraco.Core.Models;
using Umbraco.Core.Models.Membership;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Changes;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.Testing;
using Umbraco.Tests.Testing.Objects.Accessors;
using Umbraco.Web;
@@ -168,17 +170,73 @@ namespace Umbraco.Tests.Cache
}
[Test]
public void OnlyHandlesOnContentTypeEvent()
public void GroupsContentTypeEvents()
{
var definitions = new IEventDefinition[]
var num = 30;
var contentTypes = Enumerable.Repeat(MockedContentTypes.CreateBasicContentType(), num);
var mediaTypes = Enumerable.Repeat(MockedContentTypes.CreateImageMediaType(), num);
var memberTypes = Enumerable.Repeat(MockedContentTypes.CreateSimpleMemberType(), num);
var definitionsContent = contentTypes.SelectMany(x => new IEventDefinition[]
{
new EventDefinition<IContentTypeService, ContentTypeChange<IContentType>.EventArgs>(null, Current.Services.ContentTypeService, new ContentTypeChange<IContentType>.EventArgs(Enumerable.Empty<ContentTypeChange<IContentType>>()), "Changed"),
new EventDefinition<IContentTypeService, SaveEventArgs<IContentType>>(null, Current.Services.ContentTypeService, new SaveEventArgs<IContentType>(Enumerable.Empty<IContentType>()), "Saved"),
new EventDefinition<IContentTypeService, ContentTypeChange<IContentType>.EventArgs>(null, Current.Services.ContentTypeService, new ContentTypeChange<IContentType>.EventArgs(Enumerable.Empty<ContentTypeChange<IContentType>>()), "Changed"),
new EventDefinition<IContentTypeService, SaveEventArgs<IContentType>>(null, Current.Services.ContentTypeService, new SaveEventArgs<IContentType>(Enumerable.Empty<IContentType>()), "Saved"),
};
var result = DistributedCacheBinder.GetReducedEventList(definitions);
Assert.AreEqual(1, result.Count());
new EventDefinition<IContentTypeService, ContentTypeChange<IContentType>.EventArgs>(null, Current.Services.ContentTypeService, new ContentTypeChange<IContentType>.EventArgs(new ContentTypeChange<IContentType>(x, ContentTypeChangeTypes.Create)), "Changed"),
new EventDefinition<IContentTypeService, SaveEventArgs<IContentType>>(null, Current.Services.ContentTypeService, new SaveEventArgs<IContentType>(x), "Saved"),
});
var definitionsMedia = mediaTypes.SelectMany(x => new IEventDefinition[]
{
new EventDefinition<IMediaTypeService, ContentTypeChange<IMediaType>.EventArgs>(null, Current.Services.MediaTypeService, new ContentTypeChange<IMediaType>.EventArgs(new ContentTypeChange<IMediaType>(x, ContentTypeChangeTypes.Create)), "Changed"),
new EventDefinition<IMediaTypeService, SaveEventArgs<IMediaType>>(null, Current.Services.MediaTypeService, new SaveEventArgs<IMediaType>(x), "Saved"),
});
var definitionsMember = memberTypes.SelectMany(x => new IEventDefinition[]
{
new EventDefinition<IMemberTypeService, ContentTypeChange<IMemberType>.EventArgs>(null, Current.Services.MemberTypeService, new ContentTypeChange<IMemberType>.EventArgs(new ContentTypeChange<IMemberType>(x, ContentTypeChangeTypes.Create)), "Changed"),
new EventDefinition<IMemberTypeService, SaveEventArgs<IMemberType>>(null, Current.Services.MemberTypeService, new SaveEventArgs<IMemberType>(x), "Saved"),
});
var definitions = new List<IEventDefinition>();
definitions.AddRange(definitionsContent);
definitions.AddRange(definitionsMedia);
definitions.AddRange(definitionsMember);
var result = DistributedCacheBinder.GetGroupedEventList(definitions);
Assert.Multiple(() =>
{
Assert.AreEqual(num * 6, definitions.Count(), "Precondition is we have many definitions");
Assert.AreEqual(6, result.Count(), "Unexpected number of reduced definitions");
foreach (var eventDefinition in result)
{
if (eventDefinition.Args is SaveEventArgs<IContentType> saveContentEventArgs)
{
Assert.AreEqual(num, saveContentEventArgs.SavedEntities.Count());
}
if (eventDefinition.Args is ContentTypeChange<IContentType>.EventArgs changeContentEventArgs)
{
Assert.AreEqual(num, changeContentEventArgs.Changes.Count());
}
if (eventDefinition.Args is SaveEventArgs<IMediaType> saveMediaEventArgs)
{
Assert.AreEqual(num, saveMediaEventArgs.SavedEntities.Count());
}
if (eventDefinition.Args is ContentTypeChange<IMediaType>.EventArgs changeMediaEventArgs)
{
Assert.AreEqual(num, changeMediaEventArgs.Changes.Count());
}
if (eventDefinition.Args is SaveEventArgs<IMemberType> saveMemberEventArgs)
{
Assert.AreEqual(num, saveMemberEventArgs.SavedEntities.Count());
}
if (eventDefinition.Args is ContentTypeChange<IMemberType>.EventArgs changeMemberEventArgs)
{
Assert.AreEqual(num, changeMemberEventArgs.Changes.Count());
}
}
});
}
}
}

View File

@@ -348,9 +348,9 @@
<WebProjectProperties>
<UseIIS>False</UseIIS>
<AutoAssignPort>True</AutoAssignPort>
<DevelopmentServerPort>8170</DevelopmentServerPort>
<DevelopmentServerPort>8171</DevelopmentServerPort>
<DevelopmentServerVPath>/</DevelopmentServerVPath>
<IISUrl>http://localhost:8170</IISUrl>
<IISUrl>http://localhost:8171</IISUrl>
<NTLMAuthentication>False</NTLMAuthentication>
<UseCustomServer>False</UseCustomServer>
<CustomServerUrl>

View File

@@ -0,0 +1,285 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
Define the Web.config template, which is used when creating the initial Web.config,
and then transforms from web.Template.[Debug|Release].config are applied.
Documentation for Web.config at: https://our.umbraco.com/documentation/Reference/Config/webconfig/
-->
<configSections>
<section name="clientDependency" type="ClientDependency.Core.Config.ClientDependencySection, ClientDependency.Core" requirePermission="false" />
<sectionGroup name="umbracoConfiguration">
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Core" requirePermission="false" />
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Core" requirePermission="false" />
</sectionGroup>
<sectionGroup name="imageProcessor">
<section name="security" requirePermission="false" type="ImageProcessor.Web.Configuration.ImageSecuritySection, ImageProcessor.Web" />
<section name="processing" requirePermission="false" type="ImageProcessor.Web.Configuration.ImageProcessingSection, ImageProcessor.Web" />
<section name="caching" requirePermission="false" type="ImageProcessor.Web.Configuration.ImageCacheSection, ImageProcessor.Web" />
</sectionGroup>
</configSections>
<umbracoConfiguration>
<settings configSource="config\umbracoSettings.config" />
<HealthChecks configSource="config\HealthChecks.config" />
</umbracoConfiguration>
<clientDependency configSource="config\ClientDependency.config" />
<appSettings>
<add key="Umbraco.Core.ConfigurationStatus" value="8.17.0" />
<add key="Umbraco.Core.ReservedUrls" value="" />
<add key="Umbraco.Core.ReservedPaths" value="" />
<add key="Umbraco.Core.Path" value="~/umbraco" />
<add key="Umbraco.Core.HideTopLevelNodeFromPath" value="true" />
<add key="Umbraco.Core.TimeOutInMinutes" value="20" />
<add key="Umbraco.Core.DefaultUILanguage" value="en-US" />
<add key="Umbraco.Core.UseHttps" value="false" />
<add key="ValidationSettings:UnobtrusiveValidationMode" value="None" />
<add key="webpages:Enabled" value="false" />
<add key="enableSimpleMembership" value="false" />
<add key="autoFormsAuthentication" value="false" />
<add key="dataAnnotations:dataTypeAttribute:disableRegEx" value="false" />
<add key="owin:appStartup" value="UmbracoDefaultOwinStartup" />
<add key="Umbraco.ModelsBuilder.Enable" value="true" />
<add key="Umbraco.ModelsBuilder.ModelsMode" value="PureLive" />
<add key="Umbraco.Core.SqlWriteLockTimeOut" value="10000" />
<add key="Umbraco.TestData.Enabled" value="true" />
</appSettings>
<!--
Important: if you're upgrading Umbraco, do not clear the connectionString/providerName during your Web.config merge.
-->
<connectionStrings>
<remove name="umbracoDbDSN" />
<add name="umbracoDbDSN" connectionString="Data Source=|DataDirectory|\Umbraco.sdf;Flush Interval=1;;default lock timeout=5000;" providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>
<system.data>
<DbProviderFactories>
<remove invariant="System.Data.SqlServerCe.4.0" />
<add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe" />
</DbProviderFactories>
</system.data>
<system.net>
<mailSettings>
<!--
If you need Umbraco to send out system mails (like reset password and invite user),
you must configure your SMTP settings here - for example:
-->
<!--
<smtp from="noreply@example.com">
<network host="localhost" port="25" enableSsl="false" userName="" password="" />
</smtp>
-->
</mailSettings>
</system.net>
<system.web>
<customErrors mode="RemoteOnly" />
<trace enabled="true" requestLimit="10" pageOutput="false" traceMode="SortByTime" localOnly="true" />
<httpRuntime requestValidationMode="2.0" enableVersionHeader="false" targetFramework="4.7.2" maxRequestLength="51200" fcnMode="Single" />
<httpModules>
<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="UmbracoModule" type="Umbraco.Web.UmbracoModule,Umbraco.Web" />
<add name="ClientDependencyModule" type="ClientDependency.Core.Module.ClientDependencyModule, ClientDependency.Core" />
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web" />
</httpModules>
<httpHandlers>
<remove verb="*" path="*.asmx" />
<add verb="*" path="*.asmx" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false" />
<add verb="*" path="*_AppService.axd" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false" />
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false" />
<add verb="*" path="DependencyHandler.axd" type="ClientDependency.Core.CompositeFiles.CompositeDependencyHandler, ClientDependency.Core " />
</httpHandlers>
<compilation defaultLanguage="c#" debug="true" batch="true" targetFramework="4.7.2" numRecompilesBeforeAppRestart="50" />
<authentication mode="Forms">
<forms name="yourAuthCookie" loginUrl="login.aspx" protection="All" path="/" />
</authentication>
<authorization>
<allow users="?" />
</authorization>
<!-- Membership Provider -->
<membership defaultProvider="UmbracoMembershipProvider" userIsOnlineTimeWindow="15">
<providers>
<clear />
<add name="UmbracoMembershipProvider" type="Umbraco.Web.Security.Providers.MembersMembershipProvider, Umbraco.Web" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="10" useLegacyEncoding="false" enablePasswordRetrieval="false" enablePasswordReset="false" requiresQuestionAndAnswer="false" defaultMemberTypeAlias="Member" passwordFormat="Hashed" allowManuallyChangingPassword="false" />
<add name="UsersMembershipProvider" type="Umbraco.Web.Security.Providers.UsersMembershipProvider, Umbraco.Web" />
</providers>
</membership>
<!-- Role Provider -->
<roleManager enabled="true" defaultProvider="UmbracoRoleProvider">
<providers>
<clear />
<add name="UmbracoRoleProvider" type="Umbraco.Web.Security.Providers.MembersRoleProvider" />
</providers>
</roleManager>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
<remove name="UmbracoModule" />
<remove name="ScriptModule" />
<remove name="ClientDependencyModule" />
<remove name="FormsAuthentication" />
<remove name="ImageProcessorModule" />
<add name="UmbracoModule" type="Umbraco.Web.UmbracoModule,Umbraco.Web" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ClientDependencyModule" type="ClientDependency.Core.Module.ClientDependencyModule, ClientDependency.Core" />
<!-- FormsAuthentication is needed for login/membership to work on homepage (as per http://stackoverflow.com/questions/218057/httpcontext-current-session-is-null-when-routing-requests) -->
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" />
<add name="ImageProcessorModule" type="ImageProcessor.Web.HttpModules.ImageProcessingModule, ImageProcessor.Web" />
</modules>
<handlers accessPolicy="Read, Write, Script, Execute">
<remove name="WebServiceHandlerFactory-Integrated" />
<remove name="ScriptHandlerFactory" />
<remove name="ScriptHandlerFactoryAppServices" />
<remove name="ScriptResource" />
<remove name="ClientDependency" />
<remove name="MiniProfiler" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptResource" verb="GET,HEAD" path="ScriptResource.axd" preCondition="integratedMode" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add verb="*" name="ClientDependency" preCondition="integratedMode" path="DependencyHandler.axd" type="ClientDependency.Core.CompositeFiles.CompositeDependencyHandler, ClientDependency.Core" />
<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<staticContent>
<remove fileExtension=".air" />
<mimeMap fileExtension=".air" mimeType="application/vnd.adobe.air-application-installer-package+zip" />
<remove fileExtension=".svg" />
<mimeMap fileExtension=".svg" mimeType="image/svg+xml" />
<remove fileExtension=".woff" />
<mimeMap fileExtension=".woff" mimeType="font/woff" />
<remove fileExtension=".woff2" />
<mimeMap fileExtension=".woff2" mimeType="font/woff2" />
<remove fileExtension=".less" />
<mimeMap fileExtension=".less" mimeType="text/css" />
<remove fileExtension=".mp4" />
<mimeMap fileExtension=".mp4" mimeType="video/mp4" />
<remove fileExtension=".json" />
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
<!-- Ensure the powered by header is not returned -->
<httpProtocol>
<customHeaders>
<remove name="X-Powered-By" />
</customHeaders>
</httpProtocol>
<!-- Increase the default upload file size limit -->
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="52428800" />
</requestFiltering>
</security>
<!--
If you wish to use IIS rewrite rules, see the documentation here: https://our.umbraco.com/documentation/Reference/Routing/IISRewriteRules
-->
<!--
<rewrite>
<rules></rules>
</rewrite>
-->
</system.webServer>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.2.5.0" newVersion="1.2.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
<bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" />
<bindingRedirect oldVersion="0.0.0.0-5.2.7.0" newVersion="5.2.7.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<location path="umbraco">
<system.webServer>
<urlCompression doStaticCompression="false" doDynamicCompression="false" dynamicCompressionBeforeCache="false" />
</system.webServer>
</location>
<location path="App_Plugins">
<system.webServer>
<urlCompression doStaticCompression="false" doDynamicCompression="false" dynamicCompressionBeforeCache="false" />
</system.webServer>
</location>
<imageProcessor>
<security configSource="config\imageprocessor\security.config" />
<caching configSource="config\imageprocessor\cache.config" />
<processing configSource="config\imageprocessor\processing.config" />
</imageProcessor>
<system.codedom>
<compilers>
<compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:7 /nowarn:1659;1699;1701" />
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
</compilers>
</system.codedom>
</configuration>

View File

@@ -6,6 +6,9 @@ using System.Reflection;
using Umbraco.Core;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Changes;
namespace Umbraco.Web.Cache
{
@@ -66,10 +69,9 @@ namespace Umbraco.Web.Cache
using (_umbracoContextFactory.EnsureUmbracoContext())
{
// When it comes to content types types, a change to any single one will trigger a reload of the content and media caches.
// As far as I (AB) can tell, there's no type specific logic here, they all clear caches for all content types, and trigger a reload of all content and media.
// We also have events registered for Changed and Saved, which do the same thing, so really only need one of these.
// Hence if we have more than one document or media types, we can and should only handle one of the events for one, to avoid repeated cache reloads.
foreach (var e in GetReducedEventList(events))
// We can reduce the impact of that by grouping the events to invoke just one per type, providing a collection of the individual arguments.
var groupedEvents = GetGroupedEventList(events);
foreach (var e in groupedEvents)
{
var handler = FindHandler(e);
if (handler == null)
@@ -86,47 +88,77 @@ namespace Umbraco.Web.Cache
}
// Internal for tests
internal static IEnumerable<IEventDefinition> GetReducedEventList(IEnumerable<IEventDefinition> events)
internal static IEnumerable<IEventDefinition> GetGroupedEventList(IEnumerable<IEventDefinition> events)
{
var reducedEvents = new List<IEventDefinition>();
var groupedEvents = new List<IEventDefinition>();
var gotDoumentType = false;
var gotMediaType = false;
var gotMemberType = false;
var grouped = events.GroupBy(x => x.GetType());
foreach (var evt in events)
foreach (var group in grouped)
{
if (evt.Sender.ToString().Contains(nameof(Core.Services.Implement.ContentTypeService)))
if (group.Key == typeof(EventDefinition<IContentTypeService, SaveEventArgs<IContentType>>))
{
if (gotDoumentType == false)
{
reducedEvents.Add(evt);
gotDoumentType = true;
}
GroupSaveEvents<IContentTypeService, IContentType>(groupedEvents, group);
}
else if (evt.Sender.ToString().Contains(nameof(Core.Services.Implement.MediaTypeService)))
else if (group.Key == typeof(EventDefinition<IContentTypeService, ContentTypeChange<IContentType>.EventArgs>))
{
if (gotMediaType == false)
{
reducedEvents.Add(evt);
gotMediaType = true;
}
GroupChangeEvents<IContentTypeService, IContentType>(groupedEvents, group);
}
else if (evt.Sender.ToString().Contains(nameof(Core.Services.Implement.MemberTypeService)))
else if (group.Key == typeof(EventDefinition<IMediaTypeService, SaveEventArgs<IMediaType>>))
{
if (gotMemberType == false)
{
reducedEvents.Add(evt);
gotMemberType = true;
}
GroupSaveEvents<IMediaTypeService, IMediaType>(groupedEvents, group);
}
else if (group.Key == typeof(EventDefinition<IMediaTypeService, ContentTypeChange<IMediaType>.EventArgs>))
{
GroupChangeEvents<IMediaTypeService, IMediaType>(groupedEvents, group);
}
else if (group.Key == typeof(EventDefinition<IMemberTypeService, SaveEventArgs<IMemberType>>))
{
GroupSaveEvents<IMemberTypeService, IMemberType>(groupedEvents, group);
}
else if (group.Key == typeof(EventDefinition<IMemberTypeService, ContentTypeChange<IMemberType>.EventArgs>))
{
GroupChangeEvents<IMemberTypeService, IMemberType>(groupedEvents, group);
}
else
{
reducedEvents.Add(evt);
groupedEvents.AddRange(group);
}
}
return reducedEvents;
return groupedEvents;
}
private static void GroupSaveEvents<TService, TType>(List<IEventDefinition> groupedEvents, IGrouping<Type, IEventDefinition> group)
where TService : IContentTypeBaseService
where TType : IContentTypeBase
{
var groupedGroups = group.GroupBy(x => (x.EventName, x.Sender));
foreach (var groupedGroup in groupedGroups)
{
groupedEvents.Add(new EventDefinition<TService, SaveEventArgs<TType>>(
null,
(TService)groupedGroup.Key.Sender,
new SaveEventArgs<TType>(groupedGroup.SelectMany(x => ((SaveEventArgs<TType>)x.Args).SavedEntities)),
groupedGroup.Key.EventName));
}
}
private static void GroupChangeEvents<TService, TType>(List<IEventDefinition> groupedEvents, IGrouping<Type, IEventDefinition> group)
where TService : IContentTypeBaseService
where TType : class, IContentTypeComposition
{
var groupedGroups = group.GroupBy(x => (x.EventName, x.Sender));
foreach (var groupedGroup in groupedGroups)
{
groupedEvents.Add(new EventDefinition<TService, ContentTypeChange<TType>.EventArgs>(
null,
(TService)groupedGroup.Key.Sender,
new ContentTypeChange<TType>.EventArgs(groupedGroup.SelectMany(x => ((ContentTypeChange<TType>.EventArgs)x.Args).Changes)),
groupedGroup.Key.EventName));
}
}
}
}