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:
@@ -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")]
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
285
src/Umbraco.Web.UI/web.config.temp-build
Normal file
285
src/Umbraco.Web.UI/web.config.temp-build
Normal 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=\"Web\" /optionInfer+" />
|
||||
</compilers>
|
||||
</system.codedom>
|
||||
|
||||
</configuration>
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user